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-2014 ImageMagick Studio LLC, a non-profit organization %
21 % dedicated to making software imaging solutions freely available. %
23 % You may not use this file except in compliance with the License. You may %
24 % obtain a copy of the License at %
26 % http://www.imagemagick.org/script/license.php %
28 % Unless required by applicable law or agreed to in writing, software %
29 % distributed under the License is distributed on an "AS IS" BASIS, %
30 % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
31 % See the License for the specific language governing permissions and %
32 % limitations under the License. %
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
42 #include "MagickCore/studio.h"
43 #include "MagickCore/artifact.h"
44 #include "MagickCore/attribute.h"
45 #include "MagickCore/blob.h"
46 #include "MagickCore/cache.h"
47 #include "MagickCore/cache-private.h"
48 #include "MagickCore/channel.h"
49 #include "MagickCore/client.h"
50 #include "MagickCore/color.h"
51 #include "MagickCore/colorspace.h"
52 #include "MagickCore/composite.h"
53 #include "MagickCore/constitute.h"
54 #include "MagickCore/decorate.h"
55 #include "MagickCore/delegate.h"
56 #include "MagickCore/display.h"
57 #include "MagickCore/display-private.h"
58 #include "MagickCore/distort.h"
59 #include "MagickCore/draw.h"
60 #include "MagickCore/effect.h"
61 #include "MagickCore/enhance.h"
62 #include "MagickCore/exception.h"
63 #include "MagickCore/exception-private.h"
64 #include "MagickCore/fx.h"
65 #include "MagickCore/geometry.h"
66 #include "MagickCore/image.h"
67 #include "MagickCore/image-private.h"
68 #include "MagickCore/list.h"
69 #include "MagickCore/log.h"
70 #include "MagickCore/magick.h"
71 #include "MagickCore/memory_.h"
72 #include "MagickCore/monitor.h"
73 #include "MagickCore/monitor-private.h"
74 #include "MagickCore/montage.h"
75 #include "MagickCore/nt-base-private.h"
76 #include "MagickCore/option.h"
77 #include "MagickCore/paint.h"
78 #include "MagickCore/pixel.h"
79 #include "MagickCore/pixel-accessor.h"
80 #include "MagickCore/PreRvIcccm.h"
81 #include "MagickCore/property.h"
82 #include "MagickCore/quantum.h"
83 #include "MagickCore/quantum-private.h"
84 #include "MagickCore/resize.h"
85 #include "MagickCore/resource_.h"
86 #include "MagickCore/shear.h"
87 #include "MagickCore/segment.h"
88 #include "MagickCore/statistic.h"
89 #include "MagickCore/string_.h"
90 #include "MagickCore/string-private.h"
91 #include "MagickCore/transform.h"
92 #include "MagickCore/threshold.h"
93 #include "MagickCore/utility.h"
94 #include "MagickCore/utility-private.h"
95 #include "MagickCore/version.h"
96 #include "MagickCore/widget.h"
97 #include "MagickCore/widget-private.h"
98 #include "MagickCore/xwindow.h"
99 #include "MagickCore/xwindow-private.h"
101 #if defined(MAGICKCORE_X11_DELEGATE)
105 #define MaxColors MagickMin((ssize_t) windows->visual_info->colormap_size,256L)
108 Constant declarations.
110 static const unsigned char
113 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55
117 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
121 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
145 Help widget declarations.
148 *ImageAnnotateHelp[] =
150 "In annotate mode, the Command widget has these options:",
200 "Choose a font name from the Font Name sub-menu. Additional",
201 "font names can be specified with the font browser. You can",
202 "change the menu names by setting the X resources font1",
205 "Choose a font color from the Font Color sub-menu.",
206 "Additional font colors can be specified with the color",
207 "browser. You can change the menu colors by setting the X",
208 "resources pen1 through pen9.",
210 "If you select the color browser and press Grab, you can",
211 "choose the font color by moving the pointer to the desired",
212 "color on the screen and press any button.",
214 "If you choose to rotate the text, choose Rotate Text from the",
215 "menu and select an angle. Typically you will only want to",
216 "rotate one line of text at a time. Depending on the angle you",
217 "choose, subsequent lines may end up overwriting each other.",
219 "Choosing a font and its color is optional. The default font",
220 "is fixed and the default color is black. However, you must",
221 "choose a location to begin entering text and press button 1.",
222 "An underscore character will appear at the location of the",
223 "pointer. The cursor changes to a pencil to indicate you are",
224 "in text mode. To exit immediately, press Dismiss.",
226 "In text mode, any key presses will display the character at",
227 "the location of the underscore and advance the underscore",
228 "cursor. Enter your text and once completed press Apply to",
229 "finish your image annotation. To correct errors press BACK",
230 "SPACE. To delete an entire line of text, press DELETE. Any",
231 "text that exceeds the boundaries of the image window is",
232 "automagically continued onto the next line.",
234 "The actual color you request for the font is saved in the",
235 "image. However, the color that appears in your image window",
236 "may be different. For example, on a monochrome screen the",
237 "text will appear black or white even if you choose the color",
238 "red as the font color. However, the image saved to a file",
239 "with -write is written with red lettering. To assure the",
240 "correct color text in the final image, any PseudoClass image",
241 "is promoted to DirectClass (see miff(5)). To force a",
242 "PseudoClass image to remain PseudoClass, use -colors.",
247 "In chop mode, the Command widget has these options:",
255 "If the you choose the horizontal direction (this the",
256 "default), the area of the image between the two horizontal",
257 "endpoints of the chop line is removed. Otherwise, the area",
258 "of the image between the two vertical endpoints of the chop",
261 "Select a location within the image window to begin your chop,",
262 "press and hold any button. Next, move the pointer to",
263 "another location in the image. As you move a line will",
264 "connect the initial location and the pointer. When you",
265 "release the button, the area within the image to chop is",
266 "determined by which direction you choose from the Command",
269 "To cancel the image chopping, move the pointer back to the",
270 "starting point of the line and release the button.",
273 *ImageColorEditHelp[] =
275 "In color edit mode, the Command widget has these options:",
316 "Choose a color editing method from the Method sub-menu",
317 "of the Command widget. The point method recolors any pixel",
318 "selected with the pointer until the button is released. The",
319 "replace method recolors any pixel that matches the color of",
320 "the pixel you select with a button press. Floodfill recolors",
321 "any pixel that matches the color of the pixel you select with",
322 "a button press and is a neighbor. Whereas filltoborder recolors",
323 "any neighbor pixel that is not the border color. Finally reset",
324 "changes the entire image to the designated color.",
326 "Next, choose a pixel color from the Pixel Color sub-menu.",
327 "Additional pixel colors can be specified with the color",
328 "browser. You can change the menu colors by setting the X",
329 "resources pen1 through pen9.",
331 "Now press button 1 to select a pixel within the image window",
332 "to change its color. Additional pixels may be recolored as",
333 "prescribed by the method you choose.",
335 "If the Magnify widget is mapped, it can be helpful in positioning",
336 "your pointer within the image (refer to button 2).",
338 "The actual color you request for the pixels is saved in the",
339 "image. However, the color that appears in your image window",
340 "may be different. For example, on a monochrome screen the",
341 "pixel will appear black or white even if you choose the",
342 "color red as the pixel color. However, the image saved to a",
343 "file with -write is written with red pixels. To assure the",
344 "correct color text in the final image, any PseudoClass image",
345 "is promoted to DirectClass (see miff(5)). To force a",
346 "PseudoClass image to remain PseudoClass, use -colors.",
349 *ImageCompositeHelp[] =
351 "First a widget window is displayed requesting you to enter an",
352 "image name. Press Composite, Grab or type a file name.",
353 "Press Cancel if you choose not to create a composite image.",
354 "When you choose Grab, move the pointer to the desired window",
355 "and press any button.",
357 "If the Composite image does not have any matte information,",
358 "you are informed and the file browser is displayed again.",
359 "Enter the name of a mask image. The image is typically",
360 "grayscale and the same size as the composite image. If the",
361 "image is not grayscale, it is converted to grayscale and the",
362 "resulting intensities are used as matte information.",
364 "A small window appears showing the location of the cursor in",
365 "the image window. You are now in composite mode. To exit",
366 "immediately, press Dismiss. In composite mode, the Command",
367 "widget has these options:",
393 "Choose a composite operation from the Operators sub-menu of",
394 "the Command widget. How each operator behaves is described",
395 "below. Image window is the image currently displayed on",
396 "your X server and image is the image obtained with the File",
399 "Over The result is the union of the two image shapes,",
400 " with image obscuring image window in the region of",
403 "In The result is simply image cut by the shape of",
404 " image window. None of the image data of image",
405 " window is in the result.",
407 "Out The resulting image is image with the shape of",
408 " image window cut out.",
410 "Atop The result is the same shape as image image window,",
411 " with image obscuring image window where the image",
412 " shapes overlap. Note this differs from over",
413 " because the portion of image outside image window's",
414 " shape does not appear in the result.",
416 "Xor The result is the image data from both image and",
417 " image window that is outside the overlap region.",
418 " The overlap region is blank.",
420 "Plus The result is just the sum of the image data.",
421 " Output values are cropped to QuantumRange (no overflow).",
423 "Minus The result of image - image window, with underflow",
426 "Add The result of image + image window, with overflow",
427 " wrapping around (mod 256).",
429 "Subtract The result of image - image window, with underflow",
430 " wrapping around (mod 256). The add and subtract",
431 " operators can be used to perform reversible",
435 " The result of abs(image - image window). This",
436 " useful for comparing two very similar images.",
439 " The result of image * image window. This",
440 " useful for the creation of drop-shadows.",
442 "Bumpmap The result of surface normals from image * image",
445 "Copy The resulting image is image window replaced with",
446 " image. Here the matte information is ignored.",
448 "CopyRed The red layer of the image window is replace with",
449 " the red layer of the image. The other layers are",
453 " The green layer of the image window is replace with",
454 " the green layer of the image. The other layers are",
457 "CopyBlue The blue layer of the image window is replace with",
458 " the blue layer of the image. The other layers are",
462 " The matte layer of the image window is replace with",
463 " the matte layer of the image. The other layers are",
466 "The image compositor requires a matte, or alpha channel in",
467 "the image for some operations. This extra channel usually",
468 "defines a mask which represents a sort of a cookie-cutter",
469 "for the image. This the case when matte is opaque (full",
470 "coverage) for pixels inside the shape, zero outside, and",
471 "between 0 and QuantumRange on the boundary. If image does not",
472 "have a matte channel, it is initialized with 0 for any pixel",
473 "matching in color to pixel location (0,0), otherwise QuantumRange.",
475 "If you choose Dissolve, the composite operator becomes Over. The",
476 "image matte channel percent transparency is initialized to factor.",
477 "The image window is initialized to (100-factor). Where factor is the",
478 "value you specify in the Dialog widget.",
480 "Displace shifts the image pixels as defined by a displacement",
481 "map. With this option, image is used as a displacement map.",
482 "Black, within the displacement map, is a maximum positive",
483 "displacement. White is a maximum negative displacement and",
484 "middle gray is neutral. The displacement is scaled to determine",
485 "the pixel shift. By default, the displacement applies in both the",
486 "horizontal and vertical directions. However, if you specify a mask,",
487 "image is the horizontal X displacement and mask the vertical Y",
490 "Note that matte information for image window is not retained",
491 "for colormapped X server visuals (e.g. StaticColor,",
492 "StaticColor, GrayScale, PseudoColor). Correct compositing",
493 "behavior may require a TrueColor or DirectColor visual or a",
494 "Standard Colormap.",
496 "Choosing a composite operator is optional. The default",
497 "operator is replace. However, you must choose a location to",
498 "composite your image and press button 1. Press and hold the",
499 "button before releasing and an outline of the image will",
500 "appear to help you identify your location.",
502 "The actual colors of the composite image is saved. However,",
503 "the color that appears in image window may be different.",
504 "For example, on a monochrome screen image window will appear",
505 "black or white even though your composited image may have",
506 "many colors. If the image is saved to a file it is written",
507 "with the correct colors. To assure the correct colors are",
508 "saved in the final image, any PseudoClass image is promoted",
509 "to DirectClass (see miff(5)). To force a PseudoClass image",
510 "to remain PseudoClass, use -colors.",
515 "In cut mode, the Command widget has these options:",
520 "To define a cut region, press button 1 and drag. The",
521 "cut region is defined by a highlighted rectangle that",
522 "expands or contracts as it follows the pointer. Once you",
523 "are satisfied with the cut region, release the button.",
524 "You are now in rectify mode. In rectify mode, the Command",
525 "widget has these options:",
531 "You can make adjustments by moving the pointer to one of the",
532 "cut rectangle corners, pressing a button, and dragging.",
533 "Finally, press Cut to commit your copy region. To",
534 "exit without cutting the image, press Dismiss.",
539 "In copy mode, the Command widget has these options:",
544 "To define a copy region, press button 1 and drag. The",
545 "copy region is defined by a highlighted rectangle that",
546 "expands or contracts as it follows the pointer. Once you",
547 "are satisfied with the copy region, release the button.",
548 "You are now in rectify mode. In rectify mode, the Command",
549 "widget has these options:",
555 "You can make adjustments by moving the pointer to one of the",
556 "copy rectangle corners, pressing a button, and dragging.",
557 "Finally, press Copy to commit your copy region. To",
558 "exit without copying the image, press Dismiss.",
563 "In crop mode, the Command widget has these options:",
568 "To define a cropping region, press button 1 and drag. The",
569 "cropping region is defined by a highlighted rectangle that",
570 "expands or contracts as it follows the pointer. Once you",
571 "are satisfied with the cropping region, release the button.",
572 "You are now in rectify mode. In rectify mode, the Command",
573 "widget has these options:",
579 "You can make adjustments by moving the pointer to one of the",
580 "cropping rectangle corners, pressing a button, and dragging.",
581 "Finally, press Crop to commit your cropping region. To",
582 "exit without cropping the image, press Dismiss.",
587 "The cursor changes to a crosshair to indicate you are in",
588 "draw mode. To exit immediately, press Dismiss. In draw mode,",
589 "the Command widget has these options:",
634 "Choose a drawing primitive from the Element sub-menu.",
636 "Choose a color from the Color sub-menu. Additional",
637 "colors can be specified with the color browser.",
639 "If you choose the color browser and press Grab, you can",
640 "select the color by moving the pointer to the desired",
641 "color on the screen and press any button. The transparent",
642 "color updates the image matte channel and is useful for",
643 "image compositing.",
645 "Choose a stipple, if appropriate, from the Stipple sub-menu.",
646 "Additional stipples can be specified with the file browser.",
647 "Stipples obtained from the file browser must be on disk in the",
648 "X11 bitmap format.",
650 "Choose a width, if appropriate, from the Width sub-menu. To",
651 "choose a specific width select the Dialog widget.",
653 "Choose a point in the Image window and press button 1 and",
654 "hold. Next, move the pointer to another location in the",
655 "image. As you move, a line connects the initial location and",
656 "the pointer. When you release the button, the image is",
657 "updated with the primitive you just drew. For polygons, the",
658 "image is updated when you press and release the button without",
659 "moving the pointer.",
661 "To cancel image drawing, move the pointer back to the",
662 "starting point of the line and release the button.",
668 " The effects of each button press is described below. Three",
669 " buttons are required. If you have a two button mouse,",
670 " button 1 and 3 are returned. Press ALT and button 3 to",
671 " simulate button 2.",
673 " 1 Press this button to map or unmap the Command widget.",
675 " 2 Press and drag to define a region of the image to",
678 " 3 Press and drag to choose from a select set of commands.",
679 " This button behaves differently if the image being",
680 " displayed is a visual image directory. Here, choose a",
681 " particular tile of the directory and press this button and",
682 " drag to select a command from a pop-up menu. Choose from",
683 " these menu items:",
691 " If you choose Open, the image represented by the tile is",
692 " displayed. To return to the visual image directory, choose",
693 " Next from the Command widget. Next and Former moves to the",
694 " next or former image respectively. Choose Delete to delete",
695 " a particular image tile. Finally, choose Update to",
696 " synchronize all the image tiles with their respective",
700 " The Command widget lists a number of sub-menus and commands.",
712 " Visual Directory...",
746 " Contrast Stretch...",
747 " Sigmoidal Contrast...",
775 " Charcoal Drawing...",
786 " Region of Interest...",
798 " Browse Documentation",
801 " Menu items with a indented triangle have a sub-menu. They",
802 " are represented above as the indented items. To access a",
803 " sub-menu item, move the pointer to the appropriate menu and",
804 " press a button and drag. When you find the desired sub-menu",
805 " item, release the button and the command is executed. Move",
806 " the pointer away from the sub-menu if you decide not to",
807 " execute a particular command.",
809 "KEYBOARD ACCELERATORS",
810 " Accelerators are one or two key presses that effect a",
811 " particular command. The keyboard accelerators that",
812 " display(1) understands is:",
814 " Ctl+O Press to open an image from a file.",
816 " space Press to display the next image.",
818 " If the image is a multi-paged document such as a Postscript",
819 " document, you can skip ahead several pages by preceding",
820 " this command with a number. For example to display the",
821 " third page beyond the current page, press 3<space>.",
823 " backspace Press to display the former image.",
825 " If the image is a multi-paged document such as a Postscript",
826 " document, you can skip behind several pages by preceding",
827 " this command with a number. For example to display the",
828 " third page preceding the current page, press 3<backspace>.",
830 " Ctl+S Press to write the image to a file.",
832 " Ctl+P Press to print the image to a Postscript printer.",
834 " Ctl+D Press to delete an image file.",
836 " Ctl+N Press to create a blank canvas.",
838 " Ctl+Q Press to discard all images and exit program.",
840 " Ctl+Z Press to undo last image transformation.",
842 " Ctl+R Press to redo last image transformation.",
844 " Ctl+X Press to cut a region of the image.",
846 " Ctl+C Press to copy a region of the image.",
848 " Ctl+V Press to paste a region to the image.",
850 " < Press to half the image size.",
852 " - Press to return to the original image size.",
854 " > Press to double the image size.",
856 " % Press to resize the image to a width and height you",
859 "Cmd-A Press to make any image transformations permanent."
861 " By default, any image size transformations are applied",
862 " to the original image to create the image displayed on",
863 " the X server. However, the transformations are not",
864 " permanent (i.e. the original image does not change",
865 " size only the X image does). For example, if you",
866 " press > the X image will appear to double in size,",
867 " but the original image will in fact remain the same size.",
868 " To force the original image to double in size, press >",
869 " followed by Cmd-A.",
871 " @ Press to refresh the image window.",
873 " C Press to cut out a rectangular region of the image.",
875 " [ Press to chop the image.",
877 " H Press to flop image in the horizontal direction.",
879 " V Press to flip image in the vertical direction.",
881 " / Press to rotate the image 90 degrees clockwise.",
883 " \\ Press to rotate the image 90 degrees counter-clockwise.",
885 " * Press to rotate the image the number of degrees you",
888 " S Press to shear the image the number of degrees you",
891 " R Press to roll the image.",
893 " T Press to trim the image edges.",
895 " Shft-H Press to vary the image hue.",
897 " Shft-S Press to vary the color saturation.",
899 " Shft-L Press to vary the color brightness.",
901 " Shft-G Press to gamma correct the image.",
903 " Shft-C Press to sharpen the image contrast.",
905 " Shft-Z Press to dull the image contrast.",
907 " = Press to perform histogram equalization on the image.",
909 " Shft-N Press to perform histogram normalization on the image.",
911 " Shft-~ Press to negate the colors of the image.",
913 " . Press to convert the image colors to gray.",
915 " Shft-# Press to set the maximum number of unique colors in the",
918 " F2 Press to reduce the speckles in an image.",
920 " F3 Press to eliminate peak noise from an image.",
922 " F4 Press to add noise to an image.",
924 " F5 Press to sharpen an image.",
926 " F6 Press to delete an image file.",
928 " F7 Press to threshold the image.",
930 " F8 Press to detect edges within an image.",
932 " F9 Press to emboss an image.",
934 " F10 Press to displace pixels by a random amount.",
936 " F11 Press to negate all pixels above the threshold level.",
938 " F12 Press to shade the image using a distant light source.",
940 " F13 Press to lighten or darken image edges to create a 3-D effect.",
942 " F14 Press to segment the image by color.",
944 " Meta-S Press to swirl image pixels about the center.",
946 " Meta-I Press to implode image pixels about the center.",
948 " Meta-W Press to alter an image along a sine wave.",
950 " Meta-P Press to simulate an oil painting.",
952 " Meta-C Press to simulate a charcoal drawing.",
954 " Alt-A Press to annotate the image with text.",
956 " Alt-D Press to draw on an image.",
958 " Alt-P Press to edit an image pixel color.",
960 " Alt-M Press to edit the image matte information.",
962 " Alt-V Press to composite the image with another.",
964 " Alt-B Press to add a border to the image.",
966 " Alt-F Press to add an ornamental border to the image.",
969 " Press to add an image comment.",
971 " Ctl-A Press to apply image processing techniques to a region",
974 " Shft-? Press to display information about the image.",
976 " Shft-+ Press to map the zoom image window.",
978 " Shft-P Press to preview an image enhancement, effect, or f/x.",
980 " F1 Press to display helpful information about display(1).",
982 " Find Press to browse documentation about ImageMagick.",
984 " 1-9 Press to change the level of magnification.",
986 " Use the arrow keys to move the image one pixel up, down,",
987 " left, or right within the magnify window. Be sure to first",
988 " map the magnify window by pressing button 2.",
990 " Press ALT and one of the arrow keys to trim off one pixel",
991 " from any side of the image.",
994 *ImageMatteEditHelp[] =
996 "Matte information within an image is useful for some",
997 "operations such as image compositing (See IMAGE",
998 "COMPOSITING). This extra channel usually defines a mask",
999 "which represents a sort of a cookie-cutter for the image.",
1000 "This the case when matte is opaque (full coverage) for",
1001 "pixels inside the shape, zero outside, and between 0 and",
1002 "QuantumRange on the boundary.",
1004 "A small window appears showing the location of the cursor in",
1005 "the image window. You are now in matte edit mode. To exit",
1006 "immediately, press Dismiss. In matte edit mode, the Command",
1007 "widget has these options:",
1041 "Choose a matte editing method from the Method sub-menu of",
1042 "the Command widget. The point method changes the matte value",
1043 "of any pixel selected with the pointer until the button is",
1044 "is released. The replace method changes the matte value of",
1045 "any pixel that matches the color of the pixel you select with",
1046 "a button press. Floodfill changes the matte value of any pixel",
1047 "that matches the color of the pixel you select with a button",
1048 "press and is a neighbor. Whereas filltoborder changes the matte",
1049 "value any neighbor pixel that is not the border color. Finally",
1050 "reset changes the entire image to the designated matte value.",
1052 "Choose Matte Value and pick Opaque or Transarent. For other values",
1053 "select the Dialog entry. Here a dialog appears requesting a matte",
1054 "value. The value you select is assigned as the opacity value of the",
1055 "selected pixel or pixels.",
1057 "Now, press any button to select a pixel within the image",
1058 "window to change its matte value.",
1060 "If the Magnify widget is mapped, it can be helpful in positioning",
1061 "your pointer within the image (refer to button 2).",
1063 "Matte information is only valid in a DirectClass image.",
1064 "Therefore, any PseudoClass image is promoted to DirectClass",
1065 "(see miff(5)). Note that matte information for PseudoClass",
1066 "is not retained for colormapped X server visuals (e.g.",
1067 "StaticColor, StaticColor, GrayScale, PseudoColor) unless you",
1068 "immediately save your image to a file (refer to Write).",
1069 "Correct matte editing behavior may require a TrueColor or",
1070 "DirectColor visual or a Standard Colormap.",
1075 "When an image exceeds the width or height of the X server",
1076 "screen, display maps a small panning icon. The rectangle",
1077 "within the panning icon shows the area that is currently",
1078 "displayed in the image window. To pan about the image,",
1079 "press any button and drag the pointer within the panning",
1080 "icon. The pan rectangle moves with the pointer and the",
1081 "image window is updated to reflect the location of the",
1082 "rectangle within the panning icon. When you have selected",
1083 "the area of the image you wish to view, release the button.",
1085 "Use the arrow keys to pan the image one pixel up, down,",
1086 "left, or right within the image window.",
1088 "The panning icon is withdrawn if the image becomes smaller",
1089 "than the dimensions of the X server screen.",
1094 "A small window appears showing the location of the cursor in",
1095 "the image window. You are now in paste mode. To exit",
1096 "immediately, press Dismiss. In paste mode, the Command",
1097 "widget has these options:",
1114 "Choose a composite operation from the Operators sub-menu of",
1115 "the Command widget. How each operator behaves is described",
1116 "below. Image window is the image currently displayed on",
1117 "your X server and image is the image obtained with the File",
1120 "Over The result is the union of the two image shapes,",
1121 " with image obscuring image window in the region of",
1124 "In The result is simply image cut by the shape of",
1125 " image window. None of the image data of image",
1126 " window is in the result.",
1128 "Out The resulting image is image with the shape of",
1129 " image window cut out.",
1131 "Atop The result is the same shape as image image window,",
1132 " with image obscuring image window where the image",
1133 " shapes overlap. Note this differs from over",
1134 " because the portion of image outside image window's",
1135 " shape does not appear in the result.",
1137 "Xor The result is the image data from both image and",
1138 " image window that is outside the overlap region.",
1139 " The overlap region is blank.",
1141 "Plus The result is just the sum of the image data.",
1142 " Output values are cropped to QuantumRange (no overflow).",
1143 " This operation is independent of the matte",
1146 "Minus The result of image - image window, with underflow",
1147 " cropped to zero.",
1149 "Add The result of image + image window, with overflow",
1150 " wrapping around (mod 256).",
1152 "Subtract The result of image - image window, with underflow",
1153 " wrapping around (mod 256). The add and subtract",
1154 " operators can be used to perform reversible",
1155 " transformations.",
1158 " The result of abs(image - image window). This",
1159 " useful for comparing two very similar images.",
1161 "Copy The resulting image is image window replaced with",
1162 " image. Here the matte information is ignored.",
1164 "CopyRed The red layer of the image window is replace with",
1165 " the red layer of the image. The other layers are",
1169 " The green layer of the image window is replace with",
1170 " the green layer of the image. The other layers are",
1173 "CopyBlue The blue layer of the image window is replace with",
1174 " the blue layer of the image. The other layers are",
1178 " The matte layer of the image window is replace with",
1179 " the matte layer of the image. The other layers are",
1182 "The image compositor requires a matte, or alpha channel in",
1183 "the image for some operations. This extra channel usually",
1184 "defines a mask which represents a sort of a cookie-cutter",
1185 "for the image. This the case when matte is opaque (full",
1186 "coverage) for pixels inside the shape, zero outside, and",
1187 "between 0 and QuantumRange on the boundary. If image does not",
1188 "have a matte channel, it is initialized with 0 for any pixel",
1189 "matching in color to pixel location (0,0), otherwise QuantumRange.",
1191 "Note that matte information for image window is not retained",
1192 "for colormapped X server visuals (e.g. StaticColor,",
1193 "StaticColor, GrayScale, PseudoColor). Correct compositing",
1194 "behavior may require a TrueColor or DirectColor visual or a",
1195 "Standard Colormap.",
1197 "Choosing a composite operator is optional. The default",
1198 "operator is replace. However, you must choose a location to",
1199 "paste your image and press button 1. Press and hold the",
1200 "button before releasing and an outline of the image will",
1201 "appear to help you identify your location.",
1203 "The actual colors of the pasted image is saved. However,",
1204 "the color that appears in image window may be different.",
1205 "For example, on a monochrome screen image window will appear",
1206 "black or white even though your pasted image may have",
1207 "many colors. If the image is saved to a file it is written",
1208 "with the correct colors. To assure the correct colors are",
1209 "saved in the final image, any PseudoClass image is promoted",
1210 "to DirectClass (see miff(5)). To force a PseudoClass image",
1211 "to remain PseudoClass, use -colors.",
1216 "In region of interest mode, the Command widget has these",
1222 "To define a region of interest, press button 1 and drag.",
1223 "The region of interest is defined by a highlighted rectangle",
1224 "that expands or contracts as it follows the pointer. Once",
1225 "you are satisfied with the region of interest, release the",
1226 "button. You are now in apply mode. In apply mode the",
1227 "Command widget has these options:",
1247 " Contrast Stretch",
1248 " Sigmoidal Contrast...",
1275 " Charcoal Drawing...",
1285 "You can make adjustments to the region of interest by moving",
1286 "the pointer to one of the rectangle corners, pressing a",
1287 "button, and dragging. Finally, choose an image processing",
1288 "technique from the Command widget. You can choose more than",
1289 "one image processing technique to apply to an area.",
1290 "Alternatively, you can move the region of interest before",
1291 "applying another image processing technique. To exit, press",
1295 *ImageRotateHelp[] =
1297 "In rotate mode, the Command widget has these options:",
1316 "Choose a background color from the Pixel Color sub-menu.",
1317 "Additional background colors can be specified with the color",
1318 "browser. You can change the menu colors by setting the X",
1319 "resources pen1 through pen9.",
1321 "If you choose the color browser and press Grab, you can",
1322 "select the background color by moving the pointer to the",
1323 "desired color on the screen and press any button.",
1325 "Choose a point in the image window and press this button and",
1326 "hold. Next, move the pointer to another location in the",
1327 "image. As you move a line connects the initial location and",
1328 "the pointer. When you release the button, the degree of",
1329 "image rotation is determined by the slope of the line you",
1330 "just drew. The slope is relative to the direction you",
1331 "choose from the Direction sub-menu of the Command widget.",
1333 "To cancel the image rotation, move the pointer back to the",
1334 "starting point of the line and release the button.",
1339 Enumeration declarations.
1358 VisualDirectoryCommand,
1366 OriginalSizeCommand,
1388 ContrastStretchCommand,
1389 SigmoidalContrastCommand,
1415 CharcoalDrawCommand,
1425 RegionofInterestCommand,
1431 ShowHistogramCommand,
1437 BrowseDocumentationCommand,
1439 SaveToUndoBufferCommand,
1446 AnnotateNameCommand,
1447 AnnotateFontColorCommand,
1448 AnnotateBackgroundColorCommand,
1449 AnnotateRotateCommand,
1450 AnnotateHelpCommand,
1451 AnnotateDismissCommand,
1454 ChopDirectionCommand,
1457 HorizontalChopCommand,
1458 VerticalChopCommand,
1459 ColorEditMethodCommand,
1460 ColorEditColorCommand,
1461 ColorEditBorderCommand,
1462 ColorEditFuzzCommand,
1463 ColorEditUndoCommand,
1464 ColorEditHelpCommand,
1465 ColorEditDismissCommand,
1466 CompositeOperatorsCommand,
1467 CompositeDissolveCommand,
1468 CompositeDisplaceCommand,
1469 CompositeHelpCommand,
1470 CompositeDismissCommand,
1475 RectifyDismissCommand,
1484 MatteEditBorderCommand,
1485 MatteEditFuzzCommand,
1486 MatteEditValueCommand,
1487 MatteEditUndoCommand,
1488 MatteEditHelpCommand,
1489 MatteEditDismissCommand,
1490 PasteOperatorsCommand,
1492 PasteDismissCommand,
1494 RotateDirectionCommand,
1496 RotateSharpenCommand,
1498 RotateDismissCommand,
1499 HorizontalRotateCommand,
1500 VerticalRotateCommand,
1511 #define BricksWidth 20
1512 #define BricksHeight 20
1513 #define DiagonalWidth 16
1514 #define DiagonalHeight 16
1515 #define HighlightWidth 8
1516 #define HighlightHeight 8
1517 #define OpaqueWidth 8
1518 #define OpaqueHeight 8
1519 #define ScalesWidth 16
1520 #define ScalesHeight 16
1521 #define ShadowWidth 8
1522 #define ShadowHeight 8
1523 #define VerticalWidth 16
1524 #define VerticalHeight 16
1525 #define WavyWidth 16
1526 #define WavyHeight 16
1529 Constant declaration.
1534 static const unsigned char
1537 0xff, 0xff, 0x0f, 0x03, 0x0c, 0x00, 0x03, 0x0c, 0x00, 0x03, 0x0c, 0x00,
1538 0x03, 0x0c, 0x00, 0xff, 0xff, 0x0f, 0x60, 0x80, 0x01, 0x60, 0x80, 0x01,
1539 0x60, 0x80, 0x01, 0x60, 0x80, 0x01, 0xff, 0xff, 0x0f, 0x03, 0x0c, 0x00,
1540 0x03, 0x0c, 0x00, 0x03, 0x0c, 0x00, 0x03, 0x0c, 0x00, 0xff, 0xff, 0x0f,
1541 0x60, 0x80, 0x01, 0x60, 0x80, 0x01, 0x60, 0x80, 0x01, 0x60, 0x80, 0x01
1545 0x44, 0x44, 0x88, 0x88, 0x11, 0x11, 0x22, 0x22, 0x44, 0x44, 0x88, 0x88,
1546 0x11, 0x11, 0x22, 0x22, 0x44, 0x44, 0x88, 0x88, 0x11, 0x11, 0x22, 0x22,
1547 0x44, 0x44, 0x88, 0x88, 0x11, 0x11, 0x22, 0x22
1551 0x08, 0x08, 0x08, 0x08, 0x14, 0x14, 0xe3, 0xe3, 0x80, 0x80, 0x80, 0x80,
1552 0x41, 0x41, 0x3e, 0x3e, 0x08, 0x08, 0x08, 0x08, 0x14, 0x14, 0xe3, 0xe3,
1553 0x80, 0x80, 0x80, 0x80, 0x41, 0x41, 0x3e, 0x3e
1557 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
1558 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
1559 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
1563 0xfe, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfd, 0xff, 0xfd, 0xff, 0xfb, 0xff,
1564 0xe7, 0xff, 0x1f, 0xff, 0xff, 0xf8, 0xff, 0xe7, 0xff, 0xdf, 0xff, 0xbf,
1565 0xff, 0xbf, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f
1569 Function prototypes.
1572 XImageWindowCommand(Display *,XResourceInfo *,XWindows *,
1573 const MagickStatusType,KeySym,Image **,ExceptionInfo *);
1576 *XMagickCommand(Display *,XResourceInfo *,XWindows *,const CommandType,
1577 Image **,ExceptionInfo *),
1578 *XOpenImage(Display *,XResourceInfo *,XWindows *,const MagickBooleanType),
1579 *XTileImage(Display *,XResourceInfo *,XWindows *,Image *,XEvent *,
1581 *XVisualDirectoryImage(Display *,XResourceInfo *,XWindows *,
1584 static MagickBooleanType
1585 XAnnotateEditImage(Display *,XResourceInfo *,XWindows *,Image *,
1587 XBackgroundImage(Display *,XResourceInfo *,XWindows *,Image **,
1589 XChopImage(Display *,XResourceInfo *,XWindows *,Image **,
1591 XCropImage(Display *,XResourceInfo *,XWindows *,Image *,const ClipboardMode,
1593 XColorEditImage(Display *,XResourceInfo *,XWindows *,Image **,
1595 XCompositeImage(Display *,XResourceInfo *,XWindows *,Image *,
1597 XConfigureImage(Display *,XResourceInfo *,XWindows *,Image *,ExceptionInfo *),
1598 XDrawEditImage(Display *,XResourceInfo *,XWindows *,Image **,
1600 XMatteEditImage(Display *,XResourceInfo *,XWindows *,Image **,
1602 XPasteImage(Display *,XResourceInfo *,XWindows *,Image *,ExceptionInfo *),
1603 XPrintImage(Display *,XResourceInfo *,XWindows *,Image *,ExceptionInfo *),
1604 XRotateImage(Display *,XResourceInfo *,XWindows *,double,Image **,
1606 XROIImage(Display *,XResourceInfo *,XWindows *,Image **,ExceptionInfo *),
1607 XSaveImage(Display *,XResourceInfo *,XWindows *,Image *,ExceptionInfo *),
1608 XTrimImage(Display *,XResourceInfo *,XWindows *,Image *,ExceptionInfo *);
1611 XDrawPanRectangle(Display *,XWindows *),
1612 XImageCache(Display *,XResourceInfo *,XWindows *,const CommandType,Image **,
1614 XMagnifyImage(Display *,XWindows *,XEvent *,ExceptionInfo *),
1615 XMakePanImage(Display *,XResourceInfo *,XWindows *,Image *,ExceptionInfo *),
1616 XPanImage(Display *,XWindows *,XEvent *,ExceptionInfo *),
1617 XMagnifyWindowCommand(Display *,XWindows *,const MagickStatusType,
1618 const KeySym,ExceptionInfo *),
1619 XSetCropGeometry(Display *,XWindows *,RectangleInfo *,Image *),
1620 XScreenEvent(Display *,XWindows *,XEvent *,ExceptionInfo *),
1621 XTranslateImage(Display *,XWindows *,Image *,const KeySym);
1624 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1628 % D i s p l a y I m a g e s %
1632 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1634 % DisplayImages() displays an image sequence to any X window screen. It
1635 % returns a value other than 0 if successful. Check the exception member
1636 % of image to determine the reason for any failure.
1638 % The format of the DisplayImages method is:
1640 % MagickBooleanType DisplayImages(const ImageInfo *image_info,
1641 % Image *images,ExceptionInfo *exception)
1643 % A description of each parameter follows:
1645 % o image_info: the image info.
1647 % o image: the image.
1649 % o exception: return any errors or warnings in this structure.
1652 MagickExport MagickBooleanType DisplayImages(const ImageInfo *image_info,
1653 Image *images,ExceptionInfo *exception)
1676 assert(image_info != (const ImageInfo *) NULL);
1677 assert(image_info->signature == MagickSignature);
1678 assert(images != (Image *) NULL);
1679 assert(images->signature == MagickSignature);
1680 if (IfMagickTrue(images->debug) )
1681 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",images->filename);
1682 display=XOpenDisplay(image_info->server_name);
1683 if (display == (Display *) NULL)
1685 (void) ThrowMagickException(exception,GetMagickModule(),XServerError,
1686 "UnableToOpenXServer","`%s'",XDisplayName(image_info->server_name));
1687 return(MagickFalse);
1689 if (exception->severity != UndefinedException)
1690 CatchException(exception);
1691 (void) XSetErrorHandler(XError);
1692 resource_database=XGetResourceDatabase(display,GetClientName());
1693 (void) ResetMagickMemory(&resource_info,0,sizeof(resource_info));
1694 XGetResourceInfo(image_info,resource_database,GetClientName(),&resource_info);
1695 if (image_info->page != (char *) NULL)
1696 resource_info.image_geometry=AcquireString(image_info->page);
1697 resource_info.immutable=MagickTrue;
1698 argv[0]=AcquireString(GetClientName());
1700 for (i=0; (state & ExitState) == 0; i++)
1702 if ((images->iterations != 0) && (i >= (ssize_t) images->iterations))
1704 image=GetImageFromList(images,i % GetImageListLength(images));
1705 (void) XDisplayImage(display,&resource_info,argv,1,&image,&state,exception);
1707 (void) SetErrorHandler((ErrorHandler) NULL);
1708 (void) SetWarningHandler((WarningHandler) NULL);
1709 argv[0]=DestroyString(argv[0]);
1710 (void) XCloseDisplay(display);
1711 XDestroyResourceInfo(&resource_info);
1712 if (exception->severity != UndefinedException)
1713 return(MagickFalse);
1718 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1722 % R e m o t e D i s p l a y C o m m a n d %
1726 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1728 % RemoteDisplayCommand() encourages a remote display program to display the
1729 % specified image filename.
1731 % The format of the RemoteDisplayCommand method is:
1733 % MagickBooleanType RemoteDisplayCommand(const ImageInfo *image_info,
1734 % const char *window,const char *filename,ExceptionInfo *exception)
1736 % A description of each parameter follows:
1738 % o image_info: the image info.
1740 % o window: Specifies the name or id of an X window.
1742 % o filename: the name of the image filename to display.
1744 % o exception: return any errors or warnings in this structure.
1747 MagickExport MagickBooleanType RemoteDisplayCommand(const ImageInfo *image_info,
1748 const char *window,const char *filename,ExceptionInfo *exception)
1756 assert(image_info != (const ImageInfo *) NULL);
1757 assert(image_info->signature == MagickSignature);
1758 assert(filename != (char *) NULL);
1759 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
1760 display=XOpenDisplay(image_info->server_name);
1761 if (display == (Display *) NULL)
1763 (void) ThrowMagickException(exception,GetMagickModule(),XServerError,
1764 "UnableToOpenXServer","`%s'",XDisplayName(image_info->server_name));
1765 return(MagickFalse);
1767 (void) XSetErrorHandler(XError);
1768 status=XRemoteCommand(display,window,filename);
1769 (void) XCloseDisplay(display);
1770 return(IsMagickTrue(status));
1774 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1778 + X A n n o t a t e E d i t I m a g e %
1782 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1784 % XAnnotateEditImage() annotates the image with text.
1786 % The format of the XAnnotateEditImage method is:
1788 % MagickBooleanType XAnnotateEditImage(Display *display,
1789 % XResourceInfo *resource_info,XWindows *windows,Image *image,
1790 % ExceptionInfo *exception)
1792 % A description of each parameter follows:
1794 % o display: Specifies a connection to an X server; returned from
1797 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1799 % o windows: Specifies a pointer to a XWindows structure.
1801 % o image: the image; returned from ReadImage.
1805 static inline ssize_t MagickMax(const ssize_t x,const ssize_t y)
1812 static inline ssize_t MagickMin(const ssize_t x,const ssize_t y)
1819 static MagickBooleanType XAnnotateEditImage(Display *display,
1820 XResourceInfo *resource_info,XWindows *windows,Image *image,
1821 ExceptionInfo *exception)
1841 static const ModeType
1842 AnnotateCommands[] =
1844 AnnotateNameCommand,
1845 AnnotateFontColorCommand,
1846 AnnotateBackgroundColorCommand,
1847 AnnotateRotateCommand,
1848 AnnotateHelpCommand,
1849 AnnotateDismissCommand
1857 static MagickBooleanType
1858 transparent_box = MagickTrue,
1859 transparent_pen = MagickFalse;
1865 box_id = MaxNumberPens-2,
1870 command[MaxTextExtent],
1871 text[MaxTextExtent];
1874 *ColorMenu[MaxNumberPens+1];
1922 (void) CloneString(&windows->command.name,"Annotate");
1923 windows->command.data=4;
1924 (void) XCommandWidget(display,windows,AnnotateMenu,(XEvent *) NULL);
1925 (void) XMapRaised(display,windows->command.id);
1926 XClientMessage(display,windows->image.id,windows->im_protocols,
1927 windows->im_update_widget,CurrentTime);
1929 Track pointer until button 1 is pressed.
1931 XQueryPosition(display,windows->image.id,&x,&y);
1932 (void) XSelectInput(display,windows->image.id,
1933 windows->image.attributes.event_mask | PointerMotionMask);
1934 cursor=XCreateFontCursor(display,XC_left_side);
1935 (void) XCheckDefineCursor(display,windows->image.id,cursor);
1939 if (IfMagickTrue(windows->info.mapped) )
1942 Display pointer position.
1944 (void) FormatLocaleString(text,MaxTextExtent," %+d%+d ",
1945 x+windows->image.x,y+windows->image.y);
1946 XInfoWidget(display,windows,text);
1949 Wait for next event.
1951 XScreenEvent(display,windows,&event,exception);
1952 if (event.xany.window == windows->command.id)
1955 Select a command from the Command widget.
1957 id=XCommandWidget(display,windows,AnnotateMenu,&event);
1958 (void) XCheckDefineCursor(display,windows->image.id,cursor);
1961 switch (AnnotateCommands[id])
1963 case AnnotateNameCommand:
1966 *FontMenu[MaxNumberFonts];
1972 Initialize menu selections.
1974 for (i=0; i < MaxNumberFonts; i++)
1975 FontMenu[i]=resource_info->font_name[i];
1976 FontMenu[MaxNumberFonts-2]="Browser...";
1977 FontMenu[MaxNumberFonts-1]=(const char *) NULL;
1979 Select a font name from the pop-up menu.
1981 font_number=XMenuWidget(display,windows,AnnotateMenu[id],
1982 (const char **) FontMenu,command);
1983 if (font_number < 0)
1985 if (font_number == (MaxNumberFonts-2))
1988 font_name[MaxTextExtent] = "fixed";
1991 Select a font name from a browser.
1993 resource_info->font_name[font_number]=font_name;
1994 XFontBrowserWidget(display,windows,"Select",font_name);
1995 if (*font_name == '\0')
1999 Initialize font info.
2001 font_info=XLoadQueryFont(display,resource_info->font_name[
2003 if (font_info == (XFontStruct *) NULL)
2005 XNoticeWidget(display,windows,"Unable to load font:",
2006 resource_info->font_name[font_number]);
2009 font_id=(unsigned int) font_number;
2010 (void) XFreeFont(display,font_info);
2013 case AnnotateFontColorCommand:
2016 Initialize menu selections.
2018 for (i=0; i < (int) (MaxNumberPens-2); i++)
2019 ColorMenu[i]=resource_info->pen_colors[i];
2020 ColorMenu[MaxNumberPens-2]="transparent";
2021 ColorMenu[MaxNumberPens-1]="Browser...";
2022 ColorMenu[MaxNumberPens]=(const char *) NULL;
2024 Select a pen color from the pop-up menu.
2026 pen_number=XMenuWidget(display,windows,AnnotateMenu[id],
2027 (const char **) ColorMenu,command);
2030 transparent_pen=pen_number == (MaxNumberPens-2) ? MagickTrue :
2032 if (IfMagickTrue(transparent_pen) )
2034 if (pen_number == (MaxNumberPens-1))
2037 color_name[MaxTextExtent] = "gray";
2040 Select a pen color from a dialog.
2042 resource_info->pen_colors[pen_number]=color_name;
2043 XColorBrowserWidget(display,windows,"Select",color_name);
2044 if (*color_name == '\0')
2050 (void) XParseColor(display,windows->map_info->colormap,
2051 resource_info->pen_colors[pen_number],&color);
2052 XBestPixel(display,windows->map_info->colormap,(XColor *) NULL,
2053 (unsigned int) MaxColors,&color);
2054 windows->pixel_info->pen_colors[pen_number]=color;
2055 pen_id=(unsigned int) pen_number;
2058 case AnnotateBackgroundColorCommand:
2061 Initialize menu selections.
2063 for (i=0; i < (int) (MaxNumberPens-2); i++)
2064 ColorMenu[i]=resource_info->pen_colors[i];
2065 ColorMenu[MaxNumberPens-2]="transparent";
2066 ColorMenu[MaxNumberPens-1]="Browser...";
2067 ColorMenu[MaxNumberPens]=(const char *) NULL;
2069 Select a pen color from the pop-up menu.
2071 pen_number=XMenuWidget(display,windows,AnnotateMenu[id],
2072 (const char **) ColorMenu,command);
2075 transparent_box=pen_number == (MaxNumberPens-2) ? MagickTrue :
2077 if (IfMagickTrue(transparent_box) )
2079 if (pen_number == (MaxNumberPens-1))
2082 color_name[MaxTextExtent] = "gray";
2085 Select a pen color from a dialog.
2087 resource_info->pen_colors[pen_number]=color_name;
2088 XColorBrowserWidget(display,windows,"Select",color_name);
2089 if (*color_name == '\0')
2095 (void) XParseColor(display,windows->map_info->colormap,
2096 resource_info->pen_colors[pen_number],&color);
2097 XBestPixel(display,windows->map_info->colormap,(XColor *) NULL,
2098 (unsigned int) MaxColors,&color);
2099 windows->pixel_info->pen_colors[pen_number]=color;
2100 box_id=(unsigned int) pen_number;
2103 case AnnotateRotateCommand:
2109 angle[MaxTextExtent] = "30.0";
2127 Select a command from the pop-up menu.
2129 entry=XMenuWidget(display,windows,AnnotateMenu[id],RotateMenu,
2135 degrees=StringToDouble(RotateMenu[entry],(char **) NULL);
2138 (void) XDialogWidget(display,windows,"OK","Enter rotation angle:",
2142 degrees=StringToDouble(angle,(char **) NULL);
2145 case AnnotateHelpCommand:
2147 XTextViewWidget(display,resource_info,windows,MagickFalse,
2148 "Help Viewer - Image Annotation",ImageAnnotateHelp);
2151 case AnnotateDismissCommand:
2169 if (event.xbutton.button != Button1)
2171 if (event.xbutton.window != windows->image.id)
2174 Change to text entering mode.
2187 if (event.xkey.window != windows->image.id)
2190 Respond to a user key press.
2192 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
2193 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
2194 switch ((int) key_symbol)
2209 XTextViewWidget(display,resource_info,windows,MagickFalse,
2210 "Help Viewer - Image Annotation",ImageAnnotateHelp);
2215 (void) XBell(display,0);
2224 Map and unmap Info widget as cursor crosses its boundaries.
2228 if (IfMagickTrue(windows->info.mapped) )
2230 if ((x < (int) (windows->info.x+windows->info.width)) &&
2231 (y < (int) (windows->info.y+windows->info.height)))
2232 (void) XWithdrawWindow(display,windows->info.id,
2233 windows->info.screen);
2236 if ((x > (int) (windows->info.x+windows->info.width)) ||
2237 (y > (int) (windows->info.y+windows->info.height)))
2238 (void) XMapWindow(display,windows->info.id);
2244 } while ((state & ExitState) == 0);
2245 (void) XSelectInput(display,windows->image.id,
2246 windows->image.attributes.event_mask);
2247 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
2248 if ((state & EscapeState) != 0)
2251 Set font info and check boundary conditions.
2253 font_info=XLoadQueryFont(display,resource_info->font_name[font_id]);
2254 if (font_info == (XFontStruct *) NULL)
2256 XNoticeWidget(display,windows,"Unable to load font:",
2257 resource_info->font_name[font_id]);
2258 font_info=windows->font_info;
2260 if ((x+font_info->max_bounds.width) >= (int) windows->image.width)
2261 x=(int) windows->image.width-font_info->max_bounds.width;
2262 if (y < (int) (font_info->ascent+font_info->descent))
2263 y=(int) font_info->ascent+font_info->descent;
2264 if (((int) font_info->max_bounds.width > (int) windows->image.width) ||
2265 ((font_info->ascent+font_info->descent) >= (int) windows->image.height))
2266 return(MagickFalse);
2268 Initialize annotate structure.
2270 annotate_info=(XAnnotateInfo *) AcquireMagickMemory(sizeof(*annotate_info));
2271 if (annotate_info == (XAnnotateInfo *) NULL)
2272 return(MagickFalse);
2273 XGetAnnotateInfo(annotate_info);
2276 if (IfMagickFalse(transparent_box) && IfMagickFalse(transparent_pen))
2277 annotate_info->stencil=OpaqueStencil;
2279 if (IfMagickFalse(transparent_box) )
2280 annotate_info->stencil=BackgroundStencil;
2282 annotate_info->stencil=ForegroundStencil;
2283 annotate_info->height=(unsigned int) font_info->ascent+font_info->descent;
2284 annotate_info->degrees=degrees;
2285 annotate_info->font_info=font_info;
2286 annotate_info->text=(char *) AcquireQuantumMemory((size_t)
2287 windows->image.width/MagickMax((ssize_t) font_info->min_bounds.width,1)+2UL,
2288 sizeof(*annotate_info->text));
2289 if (annotate_info->text == (char *) NULL)
2290 return(MagickFalse);
2292 Create cursor and set graphic context.
2294 cursor=XCreateFontCursor(display,XC_pencil);
2295 (void) XCheckDefineCursor(display,windows->image.id,cursor);
2296 annotate_context=windows->image.annotate_context;
2297 (void) XSetFont(display,annotate_context,font_info->fid);
2298 (void) XSetBackground(display,annotate_context,
2299 windows->pixel_info->pen_colors[box_id].pixel);
2300 (void) XSetForeground(display,annotate_context,
2301 windows->pixel_info->pen_colors[pen_id].pixel);
2303 Begin annotating the image with text.
2305 (void) CloneString(&windows->command.name,"Text");
2306 windows->command.data=0;
2307 (void) XCommandWidget(display,windows,TextMenu,(XEvent *) NULL);
2309 (void) XDrawString(display,windows->image.id,annotate_context,x,y,"_",1);
2310 text_event.xexpose.width=(int) font_info->max_bounds.width;
2311 text_event.xexpose.height=font_info->max_bounds.ascent+
2312 font_info->max_bounds.descent;
2313 p=annotate_info->text;
2317 Display text cursor.
2320 (void) XDrawString(display,windows->image.id,annotate_context,x,y,"_",1);
2322 Wait for next event.
2324 XScreenEvent(display,windows,&event,exception);
2325 if (event.xany.window == windows->command.id)
2328 Select a command from the Command widget.
2330 (void) XSetBackground(display,annotate_context,
2331 windows->pixel_info->background_color.pixel);
2332 (void) XSetForeground(display,annotate_context,
2333 windows->pixel_info->foreground_color.pixel);
2334 id=XCommandWidget(display,windows,AnnotateMenu,&event);
2335 (void) XSetBackground(display,annotate_context,
2336 windows->pixel_info->pen_colors[box_id].pixel);
2337 (void) XSetForeground(display,annotate_context,
2338 windows->pixel_info->pen_colors[pen_id].pixel);
2341 switch (TextCommands[id])
2343 case TextHelpCommand:
2345 XTextViewWidget(display,resource_info,windows,MagickFalse,
2346 "Help Viewer - Image Annotation",ImageAnnotateHelp);
2347 (void) XCheckDefineCursor(display,windows->image.id,cursor);
2350 case TextApplyCommand:
2353 Finished annotating.
2355 annotate_info->width=(unsigned int) XTextWidth(font_info,
2356 annotate_info->text,(int) strlen(annotate_info->text));
2357 XRefreshWindow(display,&windows->image,&text_event);
2369 text_event.xexpose.x=x;
2370 text_event.xexpose.y=y-font_info->max_bounds.ascent;
2371 (void) XClearArea(display,windows->image.id,x,text_event.xexpose.y,
2372 (unsigned int) text_event.xexpose.width,(unsigned int)
2373 text_event.xexpose.height,MagickFalse);
2374 XRefreshWindow(display,&windows->image,&text_event);
2379 if (event.xbutton.window != windows->image.id)
2381 if (event.xbutton.button == Button2)
2384 Request primary selection.
2386 (void) XConvertSelection(display,XA_PRIMARY,XA_STRING,XA_STRING,
2387 windows->image.id,CurrentTime);
2394 if (event.xexpose.count == 0)
2400 Refresh Image window.
2402 XRefreshWindow(display,&windows->image,(XEvent *) NULL);
2403 text_info=annotate_info;
2404 while (text_info != (XAnnotateInfo *) NULL)
2406 if (annotate_info->stencil == ForegroundStencil)
2407 (void) XDrawString(display,windows->image.id,annotate_context,
2408 text_info->x,text_info->y,text_info->text,
2409 (int) strlen(text_info->text));
2411 (void) XDrawImageString(display,windows->image.id,
2412 annotate_context,text_info->x,text_info->y,text_info->text,
2413 (int) strlen(text_info->text));
2414 text_info=text_info->previous;
2416 (void) XDrawString(display,windows->image.id,annotate_context,
2426 if (event.xkey.window != windows->image.id)
2429 Respond to a user key press.
2431 length=XLookupString((XKeyEvent *) &event.xkey,command,(int)
2432 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
2433 *(command+length)='\0';
2434 if (((event.xkey.state & ControlMask) != 0) ||
2435 ((event.xkey.state & Mod1Mask) != 0))
2436 state|=ModifierState;
2437 if ((state & ModifierState) != 0)
2438 switch ((int) key_symbol)
2443 key_symbol=DeleteCommand;
2449 switch ((int) key_symbol)
2454 Erase one character.
2456 if (p == annotate_info->text)
2458 if (annotate_info->previous == (XAnnotateInfo *) NULL)
2463 Go to end of the previous line of text.
2465 annotate_info=annotate_info->previous;
2466 p=annotate_info->text;
2467 x=annotate_info->x+annotate_info->width;
2469 if (annotate_info->width != 0)
2470 p+=strlen(annotate_info->text);
2475 x-=XTextWidth(font_info,p,1);
2476 text_event.xexpose.x=x;
2477 text_event.xexpose.y=y-font_info->max_bounds.ascent;
2478 XRefreshWindow(display,&windows->image,&text_event);
2481 case XK_bracketleft:
2483 key_symbol=XK_Escape;
2489 Erase the entire line of text.
2491 while (p != annotate_info->text)
2494 x-=XTextWidth(font_info,p,1);
2495 text_event.xexpose.x=x;
2496 XRefreshWindow(display,&windows->image,&text_event);
2504 Finished annotating.
2506 annotate_info->width=(unsigned int) XTextWidth(font_info,
2507 annotate_info->text,(int) strlen(annotate_info->text));
2508 XRefreshWindow(display,&windows->image,&text_event);
2515 Draw a single character on the Image window.
2517 if ((state & ModifierState) != 0)
2519 if (*command == '\0')
2522 if (annotate_info->stencil == ForegroundStencil)
2523 (void) XDrawString(display,windows->image.id,annotate_context,
2526 (void) XDrawImageString(display,windows->image.id,
2527 annotate_context,x,y,p,1);
2528 x+=XTextWidth(font_info,p,1);
2530 if ((x+font_info->max_bounds.width) < (int) windows->image.width)
2537 Advance to the next line of text.
2540 annotate_info->width=(unsigned int) XTextWidth(font_info,
2541 annotate_info->text,(int) strlen(annotate_info->text));
2542 if (annotate_info->next != (XAnnotateInfo *) NULL)
2545 Line of text already exists.
2547 annotate_info=annotate_info->next;
2550 p=annotate_info->text;
2553 annotate_info->next=(XAnnotateInfo *) AcquireMagickMemory(
2554 sizeof(*annotate_info->next));
2555 if (annotate_info->next == (XAnnotateInfo *) NULL)
2556 return(MagickFalse);
2557 *annotate_info->next=(*annotate_info);
2558 annotate_info->next->previous=annotate_info;
2559 annotate_info=annotate_info->next;
2560 annotate_info->text=(char *) AcquireQuantumMemory((size_t)
2561 windows->image.width/MagickMax((ssize_t)
2562 font_info->min_bounds.width,1)+2UL,sizeof(*annotate_info->text));
2563 if (annotate_info->text == (char *) NULL)
2564 return(MagickFalse);
2565 annotate_info->y+=annotate_info->height;
2566 if (annotate_info->y > (int) windows->image.height)
2567 annotate_info->y=(int) annotate_info->height;
2568 annotate_info->next=(XAnnotateInfo *) NULL;
2571 p=annotate_info->text;
2580 Respond to a user key release.
2582 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
2583 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
2584 state&=(~ModifierState);
2587 case SelectionNotify:
2603 Obtain response from primary selection.
2605 if (event.xselection.property == (Atom) None)
2607 status=XGetWindowProperty(display,event.xselection.requestor,
2608 event.xselection.property,0L,(long) MaxTextExtent,True,XA_STRING,
2609 &type,&format,&length,&after,&data);
2610 if ((status != Success) || (type != XA_STRING) || (format == 32) ||
2614 Annotate Image window with primary selection.
2616 for (i=0; i < (ssize_t) length; i++)
2618 if ((char) data[i] != '\n')
2621 Draw a single character on the Image window.
2624 (void) XDrawString(display,windows->image.id,annotate_context,
2626 x+=XTextWidth(font_info,p,1);
2628 if ((x+font_info->max_bounds.width) < (int) windows->image.width)
2632 Advance to the next line of text.
2635 annotate_info->width=(unsigned int) XTextWidth(font_info,
2636 annotate_info->text,(int) strlen(annotate_info->text));
2637 if (annotate_info->next != (XAnnotateInfo *) NULL)
2640 Line of text already exists.
2642 annotate_info=annotate_info->next;
2645 p=annotate_info->text;
2648 annotate_info->next=(XAnnotateInfo *) AcquireMagickMemory(
2649 sizeof(*annotate_info->next));
2650 if (annotate_info->next == (XAnnotateInfo *) NULL)
2651 return(MagickFalse);
2652 *annotate_info->next=(*annotate_info);
2653 annotate_info->next->previous=annotate_info;
2654 annotate_info=annotate_info->next;
2655 annotate_info->text=(char *) AcquireQuantumMemory((size_t)
2656 windows->image.width/MagickMax((ssize_t)
2657 font_info->min_bounds.width,1)+2UL,sizeof(*annotate_info->text));
2658 if (annotate_info->text == (char *) NULL)
2659 return(MagickFalse);
2660 annotate_info->y+=annotate_info->height;
2661 if (annotate_info->y > (int) windows->image.height)
2662 annotate_info->y=(int) annotate_info->height;
2663 annotate_info->next=(XAnnotateInfo *) NULL;
2666 p=annotate_info->text;
2668 (void) XFree((void *) data);
2674 } while ((state & ExitState) == 0);
2675 (void) XFreeCursor(display,cursor);
2677 Annotation is relative to image configuration.
2679 width=(unsigned int) image->columns;
2680 height=(unsigned int) image->rows;
2683 if (windows->image.crop_geometry != (char *) NULL)
2684 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
2686 Initialize annotated image.
2688 XSetCursorState(display,windows,MagickTrue);
2689 XCheckRefreshWindows(display,windows);
2690 while (annotate_info != (XAnnotateInfo *) NULL)
2692 if (annotate_info->width == 0)
2695 No text on this line-- go to the next line of text.
2697 previous_info=annotate_info->previous;
2698 annotate_info->text=(char *)
2699 RelinquishMagickMemory(annotate_info->text);
2700 annotate_info=(XAnnotateInfo *) RelinquishMagickMemory(annotate_info);
2701 annotate_info=previous_info;
2705 Determine pixel index for box and pen color.
2707 windows->pixel_info->box_color=windows->pixel_info->pen_colors[box_id];
2708 if (windows->pixel_info->colors != 0)
2709 for (i=0; i < (ssize_t) windows->pixel_info->colors; i++)
2710 if (windows->pixel_info->pixels[i] ==
2711 windows->pixel_info->pen_colors[box_id].pixel)
2713 windows->pixel_info->box_index=(unsigned short) i;
2716 windows->pixel_info->pen_color=windows->pixel_info->pen_colors[pen_id];
2717 if (windows->pixel_info->colors != 0)
2718 for (i=0; i < (ssize_t) windows->pixel_info->colors; i++)
2719 if (windows->pixel_info->pixels[i] ==
2720 windows->pixel_info->pen_colors[pen_id].pixel)
2722 windows->pixel_info->pen_index=(unsigned short) i;
2726 Define the annotate geometry string.
2728 annotate_info->x=(int)
2729 width*(annotate_info->x+windows->image.x)/windows->image.ximage->width;
2730 annotate_info->y=(int) height*(annotate_info->y-font_info->ascent+
2731 windows->image.y)/windows->image.ximage->height;
2732 (void) FormatLocaleString(annotate_info->geometry,MaxTextExtent,
2733 "%ux%u%+d%+d",width*annotate_info->width/windows->image.ximage->width,
2734 height*annotate_info->height/windows->image.ximage->height,
2735 annotate_info->x+x,annotate_info->y+y);
2737 Annotate image with text.
2739 status=XAnnotateImage(display,windows->pixel_info,annotate_info,image,
2742 return(MagickFalse);
2746 previous_info=annotate_info->previous;
2747 annotate_info->text=DestroyString(annotate_info->text);
2748 annotate_info=(XAnnotateInfo *) RelinquishMagickMemory(annotate_info);
2749 annotate_info=previous_info;
2751 (void) XSetForeground(display,annotate_context,
2752 windows->pixel_info->foreground_color.pixel);
2753 (void) XSetBackground(display,annotate_context,
2754 windows->pixel_info->background_color.pixel);
2755 (void) XSetFont(display,annotate_context,windows->font_info->fid);
2756 XSetCursorState(display,windows,MagickFalse);
2757 (void) XFreeFont(display,font_info);
2759 Update image configuration.
2761 XConfigureImageColormap(display,resource_info,windows,image,exception);
2762 (void) XConfigureImage(display,resource_info,windows,image,exception);
2767 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2771 + X B a c k g r o u n d I m a g e %
2775 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2777 % XBackgroundImage() displays the image in the background of a window.
2779 % The format of the XBackgroundImage method is:
2781 % MagickBooleanType XBackgroundImage(Display *display,
2782 % XResourceInfo *resource_info,XWindows *windows,Image **image,
2783 % ExceptionInfo *exception)
2785 % A description of each parameter follows:
2787 % o display: Specifies a connection to an X server; returned from
2790 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
2792 % o windows: Specifies a pointer to a XWindows structure.
2794 % o image: the image.
2796 % o exception: return any errors or warnings in this structure.
2799 static MagickBooleanType XBackgroundImage(Display *display,
2800 XResourceInfo *resource_info,XWindows *windows,Image **image,
2801 ExceptionInfo *exception)
2803 #define BackgroundImageTag "Background/Image"
2809 window_id[MaxTextExtent] = "root";
2812 background_resources;
2815 Put image in background.
2817 status=XDialogWidget(display,windows,"Background",
2818 "Enter window id (id 0x00 selects window with pointer):",window_id);
2819 if (*window_id == '\0')
2820 return(MagickFalse);
2821 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image,
2823 XInfoWidget(display,windows,BackgroundImageTag);
2824 XSetCursorState(display,windows,MagickTrue);
2825 XCheckRefreshWindows(display,windows);
2826 background_resources=(*resource_info);
2827 background_resources.window_id=window_id;
2828 background_resources.backdrop=IsMagickTrue(status);
2829 status=XDisplayBackgroundImage(display,&background_resources,*image,
2831 if (IfMagickTrue(status))
2832 XClientMessage(display,windows->image.id,windows->im_protocols,
2833 windows->im_retain_colors,CurrentTime);
2834 XSetCursorState(display,windows,MagickFalse);
2835 (void) XMagickCommand(display,resource_info,windows,UndoCommand,image,
2841 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2845 + X C h o p I m a g e %
2849 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2851 % XChopImage() chops the X image.
2853 % The format of the XChopImage method is:
2855 % MagickBooleanType XChopImage(Display *display,XResourceInfo *resource_info,
2856 % XWindows *windows,Image **image,ExceptionInfo *exception)
2858 % A description of each parameter follows:
2860 % o display: Specifies a connection to an X server; returned from
2863 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
2865 % o windows: Specifies a pointer to a XWindows structure.
2867 % o image: the image.
2869 % o exception: return any errors or warnings in this structure.
2872 static MagickBooleanType XChopImage(Display *display,
2873 XResourceInfo *resource_info,XWindows *windows,Image **image,
2874 ExceptionInfo *exception)
2886 direction = HorizontalChopCommand;
2888 static const ModeType
2891 ChopDirectionCommand,
2895 DirectionCommands[] =
2897 HorizontalChopCommand,
2902 text[MaxTextExtent];
2935 (void) CloneString(&windows->command.name,"Chop");
2936 windows->command.data=1;
2937 (void) XCommandWidget(display,windows,ChopMenu,(XEvent *) NULL);
2938 (void) XMapRaised(display,windows->command.id);
2939 XClientMessage(display,windows->image.id,windows->im_protocols,
2940 windows->im_update_widget,CurrentTime);
2942 Track pointer until button 1 is pressed.
2944 XQueryPosition(display,windows->image.id,&x,&y);
2945 (void) XSelectInput(display,windows->image.id,
2946 windows->image.attributes.event_mask | PointerMotionMask);
2950 if (IfMagickTrue(windows->info.mapped) )
2953 Display pointer position.
2955 (void) FormatLocaleString(text,MaxTextExtent," %+d%+d ",
2956 x+windows->image.x,y+windows->image.y);
2957 XInfoWidget(display,windows,text);
2960 Wait for next event.
2962 XScreenEvent(display,windows,&event,exception);
2963 if (event.xany.window == windows->command.id)
2966 Select a command from the Command widget.
2968 id=XCommandWidget(display,windows,ChopMenu,&event);
2971 switch (ChopCommands[id])
2973 case ChopDirectionCommand:
2976 command[MaxTextExtent];
2987 Select a command from the pop-up menu.
2989 id=XMenuWidget(display,windows,ChopMenu[id],Directions,command);
2991 direction=DirectionCommands[id];
2994 case ChopHelpCommand:
2996 XTextViewWidget(display,resource_info,windows,MagickFalse,
2997 "Help Viewer - Image Chop",ImageChopHelp);
3000 case ChopDismissCommand:
3018 if (event.xbutton.button != Button1)
3020 if (event.xbutton.window != windows->image.id)
3023 User has committed to start point of chopping line.
3025 segment_info.x1=(short int) event.xbutton.x;
3026 segment_info.x2=(short int) event.xbutton.x;
3027 segment_info.y1=(short int) event.xbutton.y;
3028 segment_info.y2=(short int) event.xbutton.y;
3039 command[MaxTextExtent];
3044 if (event.xkey.window != windows->image.id)
3047 Respond to a user key press.
3049 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
3050 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
3051 switch ((int) key_symbol)
3066 (void) XSetFunction(display,windows->image.highlight_context,
3068 XTextViewWidget(display,resource_info,windows,MagickFalse,
3069 "Help Viewer - Image Chop",ImageChopHelp);
3070 (void) XSetFunction(display,windows->image.highlight_context,
3076 (void) XBell(display,0);
3085 Map and unmap Info widget as text cursor crosses its boundaries.
3089 if (IfMagickTrue(windows->info.mapped) )
3091 if ((x < (int) (windows->info.x+windows->info.width)) &&
3092 (y < (int) (windows->info.y+windows->info.height)))
3093 (void) XWithdrawWindow(display,windows->info.id,
3094 windows->info.screen);
3097 if ((x > (int) (windows->info.x+windows->info.width)) ||
3098 (y > (int) (windows->info.y+windows->info.height)))
3099 (void) XMapWindow(display,windows->info.id);
3102 } while ((state & ExitState) == 0);
3103 (void) XSelectInput(display,windows->image.id,
3104 windows->image.attributes.event_mask);
3105 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
3106 if ((state & EscapeState) != 0)
3109 Draw line as pointer moves until the mouse button is released.
3116 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
3123 Display info and draw chopping line.
3125 if (IfMagickFalse(windows->info.mapped) )
3126 (void) XMapWindow(display,windows->info.id);
3127 (void) FormatLocaleString(text,MaxTextExtent,
3128 " %.20gx%.20g%+.20g%+.20g",(double) chop_info.width,(double)
3129 chop_info.height,(double) chop_info.x,(double) chop_info.y);
3130 XInfoWidget(display,windows,text);
3131 XHighlightLine(display,windows->image.id,
3132 windows->image.highlight_context,&segment_info);
3135 if (IfMagickTrue(windows->info.mapped) )
3136 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
3138 Wait for next event.
3140 XScreenEvent(display,windows,&event,exception);
3142 XHighlightLine(display,windows->image.id,
3143 windows->image.highlight_context,&segment_info);
3148 segment_info.x2=(short int) event.xmotion.x;
3149 segment_info.y2=(short int) event.xmotion.y;
3155 User has committed to chopping line.
3157 segment_info.x2=(short int) event.xbutton.x;
3158 segment_info.y2=(short int) event.xbutton.y;
3166 segment_info.x2=(short int) event.xmotion.x;
3167 segment_info.y2=(short int) event.xmotion.y;
3173 Check boundary conditions.
3175 if (segment_info.x2 < 0)
3178 if (segment_info.x2 > windows->image.ximage->width)
3179 segment_info.x2=windows->image.ximage->width;
3180 if (segment_info.y2 < 0)
3183 if (segment_info.y2 > windows->image.ximage->height)
3184 segment_info.y2=windows->image.ximage->height;
3185 distance=(unsigned int)
3186 (((segment_info.x2-segment_info.x1)*(segment_info.x2-segment_info.x1))+
3187 ((segment_info.y2-segment_info.y1)*(segment_info.y2-segment_info.y1)));
3189 Compute chopping geometry.
3191 if (direction == HorizontalChopCommand)
3193 chop_info.width=(size_t) (segment_info.x2-segment_info.x1+1);
3194 chop_info.x=(ssize_t) windows->image.x+segment_info.x1;
3197 if (segment_info.x1 > (int) segment_info.x2)
3199 chop_info.width=(size_t) (segment_info.x1-segment_info.x2+1);
3200 chop_info.x=(ssize_t) windows->image.x+segment_info.x2;
3206 chop_info.height=(size_t) (segment_info.y2-segment_info.y1+1);
3208 chop_info.y=(ssize_t) windows->image.y+segment_info.y1;
3209 if (segment_info.y1 > segment_info.y2)
3211 chop_info.height=(size_t) (segment_info.y1-segment_info.y2+1);
3212 chop_info.y=(ssize_t) windows->image.y+segment_info.y2;
3215 } while ((state & ExitState) == 0);
3216 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
3217 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
3221 Image chopping is relative to image configuration.
3223 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image,
3225 XSetCursorState(display,windows,MagickTrue);
3226 XCheckRefreshWindows(display,windows);
3227 windows->image.window_changes.width=windows->image.ximage->width-
3228 (unsigned int) chop_info.width;
3229 windows->image.window_changes.height=windows->image.ximage->height-
3230 (unsigned int) chop_info.height;
3231 width=(unsigned int) (*image)->columns;
3232 height=(unsigned int) (*image)->rows;
3235 if (windows->image.crop_geometry != (char *) NULL)
3236 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
3237 scale_factor=(double) width/windows->image.ximage->width;
3239 chop_info.x=(ssize_t) (scale_factor*chop_info.x+0.5);
3240 chop_info.width=(unsigned int) (scale_factor*chop_info.width+0.5);
3241 scale_factor=(double) height/windows->image.ximage->height;
3243 chop_info.y=(ssize_t) (scale_factor*chop_info.y+0.5);
3244 chop_info.height=(unsigned int) (scale_factor*chop_info.height+0.5);
3248 chop_image=ChopImage(*image,&chop_info,exception);
3249 XSetCursorState(display,windows,MagickFalse);
3250 if (chop_image == (Image *) NULL)
3251 return(MagickFalse);
3252 *image=DestroyImage(*image);
3255 Update image configuration.
3257 XConfigureImageColormap(display,resource_info,windows,*image,exception);
3258 (void) XConfigureImage(display,resource_info,windows,*image,exception);
3263 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3267 + X C o l o r E d i t I m a g e %
3271 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3273 % XColorEditImage() allows the user to interactively change the color of one
3274 % pixel for a DirectColor image or one colormap entry for a PseudoClass image.
3276 % The format of the XColorEditImage method is:
3278 % MagickBooleanType XColorEditImage(Display *display,
3279 % XResourceInfo *resource_info,XWindows *windows,Image **image,
3280 % ExceptionInfo *exception)
3282 % A description of each parameter follows:
3284 % o display: Specifies a connection to an X server; returned from
3287 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
3289 % o windows: Specifies a pointer to a XWindows structure.
3291 % o image: the image; returned from ReadImage.
3293 % o exception: return any errors or warnings in this structure.
3296 static MagickBooleanType XColorEditImage(Display *display,
3297 XResourceInfo *resource_info,XWindows *windows,Image **image,
3298 ExceptionInfo *exception)
3313 static const ModeType
3314 ColorEditCommands[] =
3316 ColorEditMethodCommand,
3317 ColorEditColorCommand,
3318 ColorEditBorderCommand,
3319 ColorEditFuzzCommand,
3320 ColorEditUndoCommand,
3321 ColorEditHelpCommand,
3322 ColorEditDismissCommand
3326 method = PointMethod;
3332 border_color = { 0, 0, 0, 0, 0, 0 };
3335 command[MaxTextExtent],
3336 text[MaxTextExtent];
3371 (void) CloneString(&windows->command.name,"Color Edit");
3372 windows->command.data=4;
3373 (void) XCommandWidget(display,windows,ColorEditMenu,(XEvent *) NULL);
3374 (void) XMapRaised(display,windows->command.id);
3375 XClientMessage(display,windows->image.id,windows->im_protocols,
3376 windows->im_update_widget,CurrentTime);
3380 cursor=XMakeCursor(display,windows->image.id,windows->map_info->colormap,
3381 resource_info->background_color,resource_info->foreground_color);
3382 (void) XCheckDefineCursor(display,windows->image.id,cursor);
3384 Track pointer until button 1 is pressed.
3386 XQueryPosition(display,windows->image.id,&x,&y);
3387 (void) XSelectInput(display,windows->image.id,
3388 windows->image.attributes.event_mask | PointerMotionMask);
3392 if (IfMagickTrue(windows->info.mapped) )
3395 Display pointer position.
3397 (void) FormatLocaleString(text,MaxTextExtent," %+d%+d ",
3398 x+windows->image.x,y+windows->image.y);
3399 XInfoWidget(display,windows,text);
3402 Wait for next event.
3404 XScreenEvent(display,windows,&event,exception);
3405 if (event.xany.window == windows->command.id)
3408 Select a command from the Command widget.
3410 id=XCommandWidget(display,windows,ColorEditMenu,&event);
3413 (void) XCheckDefineCursor(display,windows->image.id,cursor);
3416 switch (ColorEditCommands[id])
3418 case ColorEditMethodCommand:
3424 Select a method from the pop-up menu.
3426 methods=(char **) GetCommandOptions(MagickMethodOptions);
3427 if (methods == (char **) NULL)
3429 entry=XMenuWidget(display,windows,ColorEditMenu[id],
3430 (const char **) methods,command);
3432 method=(PaintMethod) ParseCommandOption(MagickMethodOptions,
3433 MagickFalse,methods[entry]);
3434 methods=DestroyStringList(methods);
3437 case ColorEditColorCommand:
3440 *ColorMenu[MaxNumberPens];
3446 Initialize menu selections.
3448 for (i=0; i < (int) (MaxNumberPens-2); i++)
3449 ColorMenu[i]=resource_info->pen_colors[i];
3450 ColorMenu[MaxNumberPens-2]="Browser...";
3451 ColorMenu[MaxNumberPens-1]=(const char *) NULL;
3453 Select a pen color from the pop-up menu.
3455 pen_number=XMenuWidget(display,windows,ColorEditMenu[id],
3456 (const char **) ColorMenu,command);
3459 if (pen_number == (MaxNumberPens-2))
3462 color_name[MaxTextExtent] = "gray";
3465 Select a pen color from a dialog.
3467 resource_info->pen_colors[pen_number]=color_name;
3468 XColorBrowserWidget(display,windows,"Select",color_name);
3469 if (*color_name == '\0')
3475 (void) XParseColor(display,windows->map_info->colormap,
3476 resource_info->pen_colors[pen_number],&color);
3477 XBestPixel(display,windows->map_info->colormap,(XColor *) NULL,
3478 (unsigned int) MaxColors,&color);
3479 windows->pixel_info->pen_colors[pen_number]=color;
3480 pen_id=(unsigned int) pen_number;
3483 case ColorEditBorderCommand:
3486 *ColorMenu[MaxNumberPens];
3492 Initialize menu selections.
3494 for (i=0; i < (int) (MaxNumberPens-2); i++)
3495 ColorMenu[i]=resource_info->pen_colors[i];
3496 ColorMenu[MaxNumberPens-2]="Browser...";
3497 ColorMenu[MaxNumberPens-1]=(const char *) NULL;
3499 Select a pen color from the pop-up menu.
3501 pen_number=XMenuWidget(display,windows,ColorEditMenu[id],
3502 (const char **) ColorMenu,command);
3505 if (pen_number == (MaxNumberPens-2))
3508 color_name[MaxTextExtent] = "gray";
3511 Select a pen color from a dialog.
3513 resource_info->pen_colors[pen_number]=color_name;
3514 XColorBrowserWidget(display,windows,"Select",color_name);
3515 if (*color_name == '\0')
3521 (void) XParseColor(display,windows->map_info->colormap,
3522 resource_info->pen_colors[pen_number],&border_color);
3525 case ColorEditFuzzCommand:
3528 fuzz[MaxTextExtent];
3543 Select a command from the pop-up menu.
3545 entry=XMenuWidget(display,windows,ColorEditMenu[id],FuzzMenu,
3551 (*image)->fuzz=StringToDoubleInterval(FuzzMenu[entry],(double)
3555 (void) (void) CopyMagickString(fuzz,"20%",MaxTextExtent);
3556 (void) XDialogWidget(display,windows,"Ok",
3557 "Enter fuzz factor (0.0 - 99.9%):",fuzz);
3560 (void) ConcatenateMagickString(fuzz,"%",MaxTextExtent);
3561 (*image)->fuzz=StringToDoubleInterval(fuzz,(double) QuantumRange+
3565 case ColorEditUndoCommand:
3567 (void) XMagickCommand(display,resource_info,windows,UndoCommand,
3571 case ColorEditHelpCommand:
3574 XTextViewWidget(display,resource_info,windows,MagickFalse,
3575 "Help Viewer - Image Annotation",ImageColorEditHelp);
3578 case ColorEditDismissCommand:
3588 (void) XCheckDefineCursor(display,windows->image.id,cursor);
3595 if (event.xbutton.button != Button1)
3597 if ((event.xbutton.window != windows->image.id) &&
3598 (event.xbutton.window != windows->magnify.id))
3605 (void) XMagickCommand(display,resource_info,windows,
3606 SaveToUndoBufferCommand,image,exception);
3607 state|=UpdateConfigurationState;
3612 if (event.xbutton.button != Button1)
3614 if ((event.xbutton.window != windows->image.id) &&
3615 (event.xbutton.window != windows->magnify.id))
3618 Update colormap information.
3622 XConfigureImageColormap(display,resource_info,windows,*image,exception);
3623 (void) XConfigureImage(display,resource_info,windows,*image,exception);
3624 XInfoWidget(display,windows,text);
3625 (void) XCheckDefineCursor(display,windows->image.id,cursor);
3626 state&=(~UpdateConfigurationState);
3636 if (event.xkey.window == windows->magnify.id)
3641 window=windows->magnify.id;
3642 while (XCheckWindowEvent(display,window,KeyPressMask,&event)) ;
3644 if (event.xkey.window != windows->image.id)
3647 Respond to a user key press.
3649 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
3650 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
3651 switch ((int) key_symbol)
3665 XTextViewWidget(display,resource_info,windows,MagickFalse,
3666 "Help Viewer - Image Annotation",ImageColorEditHelp);
3671 (void) XBell(display,0);
3680 Map and unmap Info widget as cursor crosses its boundaries.
3684 if (IfMagickTrue(windows->info.mapped) )
3686 if ((x < (int) (windows->info.x+windows->info.width)) &&
3687 (y < (int) (windows->info.y+windows->info.height)))
3688 (void) XWithdrawWindow(display,windows->info.id,
3689 windows->info.screen);
3692 if ((x > (int) (windows->info.x+windows->info.width)) ||
3693 (y > (int) (windows->info.y+windows->info.height)))
3694 (void) XMapWindow(display,windows->info.id);
3700 if (event.xany.window == windows->magnify.id)
3702 x=windows->magnify.x-windows->image.x;
3703 y=windows->magnify.y-windows->image.y;
3707 if ((state & UpdateConfigurationState) != 0)
3717 Pixel edit is relative to image configuration.
3719 (void) XClearArea(display,windows->image.id,x_offset,y_offset,1,1,
3721 color=windows->pixel_info->pen_colors[pen_id];
3722 XPutPixel(windows->image.ximage,x_offset,y_offset,color.pixel);
3723 width=(unsigned int) (*image)->columns;
3724 height=(unsigned int) (*image)->rows;
3727 if (windows->image.crop_geometry != (char *) NULL)
3728 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,
3731 (width*(windows->image.x+x_offset)/windows->image.ximage->width+x);
3733 (height*(windows->image.y+y_offset)/windows->image.ximage->height+y);
3734 if ((x_offset < 0) || (y_offset < 0))
3736 if ((x_offset >= (int) (*image)->columns) ||
3737 (y_offset >= (int) (*image)->rows))
3739 image_view=AcquireAuthenticCacheView(*image,exception);
3746 Update color information using point algorithm.
3748 if (IfMagickFalse(SetImageStorageClass(*image,DirectClass,exception)) )
3749 return(MagickFalse);
3750 q=GetCacheViewAuthenticPixels(image_view,(ssize_t)x_offset,
3751 (ssize_t) y_offset,1,1,exception);
3752 if (q == (Quantum *) NULL)
3754 SetPixelRed(*image,ScaleShortToQuantum(color.red),q);
3755 SetPixelGreen(*image,ScaleShortToQuantum(color.green),q);
3756 SetPixelBlue(*image,ScaleShortToQuantum(color.blue),q);
3757 (void) SyncCacheViewAuthenticPixels(image_view,exception);
3767 Update color information using replace algorithm.
3769 (void) GetOneCacheViewVirtualPixelInfo(image_view,(ssize_t)
3770 x_offset,(ssize_t) y_offset,&target,exception);
3771 if ((*image)->storage_class == DirectClass)
3773 for (y=0; y < (int) (*image)->rows; y++)
3775 q=GetCacheViewAuthenticPixels(image_view,0,(ssize_t) y,
3776 (*image)->columns,1,exception);
3777 if (q == (Quantum *) NULL)
3779 for (x=0; x < (int) (*image)->columns; x++)
3781 GetPixelInfoPixel(*image,q,&pixel);
3782 if (IsFuzzyEquivalencePixelInfo(&pixel,&target))
3784 SetPixelRed(*image,ScaleShortToQuantum(
3786 SetPixelGreen(*image,ScaleShortToQuantum(
3788 SetPixelBlue(*image,ScaleShortToQuantum(
3791 q+=GetPixelChannels(*image);
3793 if (IfMagickFalse(SyncCacheViewAuthenticPixels(image_view,exception)) )
3799 for (i=0; i < (ssize_t) (*image)->colors; i++)
3800 if (IsFuzzyEquivalencePixelInfo((*image)->colormap+i,&target))
3802 (*image)->colormap[i].red=(double) ScaleShortToQuantum(
3804 (*image)->colormap[i].green=(double) ScaleShortToQuantum(
3806 (*image)->colormap[i].blue=(double) ScaleShortToQuantum(
3809 (void) SyncImage(*image,exception);
3813 case FloodfillMethod:
3814 case FillToBorderMethod:
3823 Update color information using floodfill algorithm.
3825 (void) GetOneVirtualPixelInfo(*image,
3826 GetPixelCacheVirtualMethod(*image),(ssize_t) x_offset,(ssize_t)
3827 y_offset,&target,exception);
3828 if (method == FillToBorderMethod)
3831 ScaleShortToQuantum(border_color.red);
3832 target.green=(double)
3833 ScaleShortToQuantum(border_color.green);
3834 target.blue=(double)
3835 ScaleShortToQuantum(border_color.blue);
3837 draw_info=CloneDrawInfo(resource_info->image_info,
3839 (void) QueryColorCompliance(resource_info->pen_colors[pen_id],
3840 AllCompliance,&draw_info->fill,exception);
3841 (void) FloodfillPaintImage(*image,draw_info,&target,
3842 (ssize_t)x_offset,(ssize_t)y_offset,
3843 IsMagickFalse(method == FloodfillMethod),exception);
3844 draw_info=DestroyDrawInfo(draw_info);
3850 Update color information using reset algorithm.
3852 if (IfMagickFalse(SetImageStorageClass(*image,DirectClass,exception)) )
3853 return(MagickFalse);
3854 for (y=0; y < (int) (*image)->rows; y++)
3856 q=QueueCacheViewAuthenticPixels(image_view,0,(ssize_t) y,
3857 (*image)->columns,1,exception);
3858 if (q == (Quantum *) NULL)
3860 for (x=0; x < (int) (*image)->columns; x++)
3862 SetPixelRed(*image,ScaleShortToQuantum(color.red),q);
3863 SetPixelGreen(*image,ScaleShortToQuantum(color.green),q);
3864 SetPixelBlue(*image,ScaleShortToQuantum(color.blue),q);
3865 q+=GetPixelChannels(*image);
3867 if (IfMagickFalse(SyncCacheViewAuthenticPixels(image_view,exception)) )
3873 image_view=DestroyCacheView(image_view);
3874 state&=(~UpdateConfigurationState);
3876 } while ((state & ExitState) == 0);
3877 (void) XSelectInput(display,windows->image.id,
3878 windows->image.attributes.event_mask);
3879 XSetCursorState(display,windows,MagickFalse);
3880 (void) XFreeCursor(display,cursor);
3885 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3889 + X C o m p o s i t e I m a g e %
3893 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3895 % XCompositeImage() requests an image name from the user, reads the image and
3896 % composites it with the X window image at a location the user chooses with
3899 % The format of the XCompositeImage method is:
3901 % MagickBooleanType XCompositeImage(Display *display,
3902 % XResourceInfo *resource_info,XWindows *windows,Image *image,
3903 % ExceptionInfo *exception)
3905 % A description of each parameter follows:
3907 % o display: Specifies a connection to an X server; returned from
3910 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
3912 % o windows: Specifies a pointer to a XWindows structure.
3914 % o image: the image; returned from ReadImage.
3916 % o exception: return any errors or warnings in this structure.
3919 static MagickBooleanType XCompositeImage(Display *display,
3920 XResourceInfo *resource_info,XWindows *windows,Image *image,
3921 ExceptionInfo *exception)
3924 displacement_geometry[MaxTextExtent] = "30x30",
3925 filename[MaxTextExtent] = "\0";
3938 static CompositeOperator
3939 compose = CopyCompositeOp;
3941 static const ModeType
3942 CompositeCommands[] =
3944 CompositeOperatorsCommand,
3945 CompositeDissolveCommand,
3946 CompositeDisplaceCommand,
3947 CompositeHelpCommand,
3948 CompositeDismissCommand
3952 text[MaxTextExtent];
3985 Request image file name from user.
3987 XFileBrowserWidget(display,windows,"Composite",filename);
3988 if (*filename == '\0')
3993 XSetCursorState(display,windows,MagickTrue);
3994 XCheckRefreshWindows(display,windows);
3995 (void) CopyMagickString(resource_info->image_info->filename,filename,
3997 composite_image=ReadImage(resource_info->image_info,exception);
3998 CatchException(exception);
3999 XSetCursorState(display,windows,MagickFalse);
4000 if (composite_image == (Image *) NULL)
4001 return(MagickFalse);
4005 (void) CloneString(&windows->command.name,"Composite");
4006 windows->command.data=1;
4007 (void) XCommandWidget(display,windows,CompositeMenu,(XEvent *) NULL);
4008 (void) XMapRaised(display,windows->command.id);
4009 XClientMessage(display,windows->image.id,windows->im_protocols,
4010 windows->im_update_widget,CurrentTime);
4012 Track pointer until button 1 is pressed.
4014 XQueryPosition(display,windows->image.id,&x,&y);
4015 (void) XSelectInput(display,windows->image.id,
4016 windows->image.attributes.event_mask | PointerMotionMask);
4017 composite_info.x=(ssize_t) windows->image.x+x;
4018 composite_info.y=(ssize_t) windows->image.y+y;
4019 composite_info.width=0;
4020 composite_info.height=0;
4021 cursor=XCreateFontCursor(display,XC_ul_angle);
4022 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
4027 if (IfMagickTrue(windows->info.mapped) )
4030 Display pointer position.
4032 (void) FormatLocaleString(text,MaxTextExtent," %+ld%+ld ",
4033 (long) composite_info.x,(long) composite_info.y);
4034 XInfoWidget(display,windows,text);
4036 highlight_info=composite_info;
4037 highlight_info.x=composite_info.x-windows->image.x;
4038 highlight_info.y=composite_info.y-windows->image.y;
4039 XHighlightRectangle(display,windows->image.id,
4040 windows->image.highlight_context,&highlight_info);
4042 Wait for next event.
4044 XScreenEvent(display,windows,&event,exception);
4045 XHighlightRectangle(display,windows->image.id,
4046 windows->image.highlight_context,&highlight_info);
4047 if (event.xany.window == windows->command.id)
4050 Select a command from the Command widget.
4052 id=XCommandWidget(display,windows,CompositeMenu,&event);
4055 switch (CompositeCommands[id])
4057 case CompositeOperatorsCommand:
4060 command[MaxTextExtent],
4064 Select a command from the pop-up menu.
4066 operators=GetCommandOptions(MagickComposeOptions);
4067 if (operators == (char **) NULL)
4069 entry=XMenuWidget(display,windows,CompositeMenu[id],
4070 (const char **) operators,command);
4072 compose=(CompositeOperator) ParseCommandOption(
4073 MagickComposeOptions,MagickFalse,operators[entry]);
4074 operators=DestroyStringList(operators);
4077 case CompositeDissolveCommand:
4080 factor[MaxTextExtent] = "20.0";
4083 Dissolve the two images a given percent.
4085 (void) XSetFunction(display,windows->image.highlight_context,
4087 (void) XDialogWidget(display,windows,"Dissolve",
4088 "Enter the blend factor (0.0 - 99.9%):",factor);
4089 (void) XSetFunction(display,windows->image.highlight_context,
4091 if (*factor == '\0')
4093 blend=StringToDouble(factor,(char **) NULL);
4094 compose=DissolveCompositeOp;
4097 case CompositeDisplaceCommand:
4100 Get horizontal and vertical scale displacement geometry.
4102 (void) XSetFunction(display,windows->image.highlight_context,
4104 (void) XDialogWidget(display,windows,"Displace",
4105 "Enter the horizontal and vertical scale:",displacement_geometry);
4106 (void) XSetFunction(display,windows->image.highlight_context,
4108 if (*displacement_geometry == '\0')
4110 compose=DisplaceCompositeOp;
4113 case CompositeHelpCommand:
4115 (void) XSetFunction(display,windows->image.highlight_context,
4117 XTextViewWidget(display,resource_info,windows,MagickFalse,
4118 "Help Viewer - Image Composite",ImageCompositeHelp);
4119 (void) XSetFunction(display,windows->image.highlight_context,
4123 case CompositeDismissCommand:
4141 if (IfMagickTrue(image->debug) )
4142 (void) LogMagickEvent(X11Event,GetMagickModule(),
4143 "Button Press: 0x%lx %u +%d+%d",event.xbutton.window,
4144 event.xbutton.button,event.xbutton.x,event.xbutton.y);
4145 if (event.xbutton.button != Button1)
4147 if (event.xbutton.window != windows->image.id)
4152 composite_info.width=composite_image->columns;
4153 composite_info.height=composite_image->rows;
4154 (void) XCheckDefineCursor(display,windows->image.id,cursor);
4155 composite_info.x=(ssize_t) windows->image.x+event.xbutton.x;
4156 composite_info.y=(ssize_t) windows->image.y+event.xbutton.y;
4161 if (IfMagickTrue(image->debug) )
4162 (void) LogMagickEvent(X11Event,GetMagickModule(),
4163 "Button Release: 0x%lx %u +%d+%d",event.xbutton.window,
4164 event.xbutton.button,event.xbutton.x,event.xbutton.y);
4165 if (event.xbutton.button != Button1)
4167 if (event.xbutton.window != windows->image.id)
4169 if ((composite_info.width != 0) && (composite_info.height != 0))
4172 User has selected the location of the composite image.
4174 composite_info.x=(ssize_t) windows->image.x+event.xbutton.x;
4175 composite_info.y=(ssize_t) windows->image.y+event.xbutton.y;
4185 command[MaxTextExtent];
4193 if (event.xkey.window != windows->image.id)
4196 Respond to a user key press.
4198 length=XLookupString((XKeyEvent *) &event.xkey,command,(int)
4199 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
4200 *(command+length)='\0';
4201 if (IfMagickTrue(image->debug) )
4202 (void) LogMagickEvent(X11Event,GetMagickModule(),
4203 "Key press: 0x%lx (%s)",(unsigned long) key_symbol,command);
4204 switch ((int) key_symbol)
4212 composite_image=DestroyImage(composite_image);
4220 (void) XSetFunction(display,windows->image.highlight_context,
4222 XTextViewWidget(display,resource_info,windows,MagickFalse,
4223 "Help Viewer - Image Composite",ImageCompositeHelp);
4224 (void) XSetFunction(display,windows->image.highlight_context,
4230 (void) XBell(display,0);
4239 Map and unmap Info widget as text cursor crosses its boundaries.
4243 if (IfMagickTrue(windows->info.mapped) )
4245 if ((x < (int) (windows->info.x+windows->info.width)) &&
4246 (y < (int) (windows->info.y+windows->info.height)))
4247 (void) XWithdrawWindow(display,windows->info.id,
4248 windows->info.screen);
4251 if ((x > (int) (windows->info.x+windows->info.width)) ||
4252 (y > (int) (windows->info.y+windows->info.height)))
4253 (void) XMapWindow(display,windows->info.id);
4254 composite_info.x=(ssize_t) windows->image.x+x;
4255 composite_info.y=(ssize_t) windows->image.y+y;
4260 if (IfMagickTrue(image->debug) )
4261 (void) LogMagickEvent(X11Event,GetMagickModule(),"Event type: %d",
4266 } while ((state & ExitState) == 0);
4267 (void) XSelectInput(display,windows->image.id,
4268 windows->image.attributes.event_mask);
4269 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
4270 XSetCursorState(display,windows,MagickFalse);
4271 (void) XFreeCursor(display,cursor);
4272 if ((state & EscapeState) != 0)
4275 Image compositing is relative to image configuration.
4277 XSetCursorState(display,windows,MagickTrue);
4278 XCheckRefreshWindows(display,windows);
4279 width=(unsigned int) image->columns;
4280 height=(unsigned int) image->rows;
4283 if (windows->image.crop_geometry != (char *) NULL)
4284 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
4285 scale_factor=(double) width/windows->image.ximage->width;
4286 composite_info.x+=x;
4287 composite_info.x=(ssize_t) (scale_factor*composite_info.x+0.5);
4288 composite_info.width=(unsigned int) (scale_factor*composite_info.width+0.5);
4289 scale_factor=(double) height/windows->image.ximage->height;
4290 composite_info.y+=y;
4291 composite_info.y=(ssize_t) (scale_factor*composite_info.y+0.5);
4292 composite_info.height=(unsigned int) (scale_factor*composite_info.height+0.5);
4293 if ((composite_info.width != composite_image->columns) ||
4294 (composite_info.height != composite_image->rows))
4300 Scale composite image.
4302 resize_image=ResizeImage(composite_image,composite_info.width,
4303 composite_info.height,composite_image->filter,exception);
4304 composite_image=DestroyImage(composite_image);
4305 if (resize_image == (Image *) NULL)
4307 XSetCursorState(display,windows,MagickFalse);
4308 return(MagickFalse);
4310 composite_image=resize_image;
4312 if (compose == DisplaceCompositeOp)
4313 (void) SetImageArtifact(composite_image,"compose:args",
4314 displacement_geometry);
4333 Create mattes for blending.
4335 (void) SetImageAlphaChannel(composite_image,OpaqueAlphaChannel,exception);
4336 opacity=(Quantum) (ScaleQuantumToChar(QuantumRange)-
4337 ((ssize_t) ScaleQuantumToChar(QuantumRange)*blend)/100);
4338 if (IfMagickFalse(SetImageStorageClass(image,DirectClass,exception)) )
4339 return(MagickFalse);
4340 image->alpha_trait=BlendPixelTrait;
4341 image_view=AcquireAuthenticCacheView(image,exception);
4342 for (y=0; y < (int) image->rows; y++)
4344 q=GetCacheViewAuthenticPixels(image_view,0,(ssize_t) y,image->columns,1,
4346 if (q == (Quantum *) NULL)
4348 for (x=0; x < (int) image->columns; x++)
4350 SetPixelAlpha(image,opacity,q);
4351 q+=GetPixelChannels(image);
4353 if (IfMagickFalse(SyncCacheViewAuthenticPixels(image_view,exception)) )
4356 image_view=DestroyCacheView(image_view);
4359 Composite image with X Image window.
4361 (void) CompositeImage(image,composite_image,compose,MagickTrue,
4362 composite_info.x,composite_info.y,exception);
4363 composite_image=DestroyImage(composite_image);
4364 XSetCursorState(display,windows,MagickFalse);
4366 Update image configuration.
4368 XConfigureImageColormap(display,resource_info,windows,image,exception);
4369 (void) XConfigureImage(display,resource_info,windows,image,exception);
4374 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4378 + X C o n f i g u r e I m a g e %
4382 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4384 % XConfigureImage() creates a new X image. It also notifies the window
4385 % manager of the new image size and configures the transient widows.
4387 % The format of the XConfigureImage method is:
4389 % MagickBooleanType XConfigureImage(Display *display,
4390 % XResourceInfo *resource_info,XWindows *windows,Image *image,
4391 % ExceptionInfo *exception)
4393 % A description of each parameter follows:
4395 % o display: Specifies a connection to an X server; returned from
4398 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
4400 % o windows: Specifies a pointer to a XWindows structure.
4402 % o image: the image.
4404 % o exception: return any errors or warnings in this structure.
4406 % o exception: return any errors or warnings in this structure.
4409 static MagickBooleanType XConfigureImage(Display *display,
4410 XResourceInfo *resource_info,XWindows *windows,Image *image,
4411 ExceptionInfo *exception)
4414 geometry[MaxTextExtent];
4435 Dismiss if window dimensions are zero.
4437 width=(unsigned int) windows->image.window_changes.width;
4438 height=(unsigned int) windows->image.window_changes.height;
4439 if (IfMagickTrue(image->debug) )
4440 (void) LogMagickEvent(X11Event,GetMagickModule(),
4441 "Configure Image: %dx%d=>%.20gx%.20g",windows->image.ximage->width,
4442 windows->image.ximage->height,(double) width,(double) height);
4443 if ((width*height) == 0)
4448 Resize image to fit Image window dimensions.
4450 XSetCursorState(display,windows,MagickTrue);
4451 (void) XFlush(display);
4452 if (((int) width != windows->image.ximage->width) ||
4453 ((int) height != windows->image.ximage->height))
4454 image->taint=MagickTrue;
4455 windows->magnify.x=(int)
4456 width*windows->magnify.x/windows->image.ximage->width;
4457 windows->magnify.y=(int)
4458 height*windows->magnify.y/windows->image.ximage->height;
4459 windows->image.x=(int) (width*windows->image.x/windows->image.ximage->width);
4460 windows->image.y=(int)
4461 (height*windows->image.y/windows->image.ximage->height);
4462 status=XMakeImage(display,resource_info,&windows->image,image,
4463 (unsigned int) width,(unsigned int) height,exception);
4464 if (IfMagickFalse(status) )
4465 XNoticeWidget(display,windows,"Unable to configure X image:",
4466 windows->image.name);
4468 Notify window manager of the new configuration.
4470 if (resource_info->image_geometry != (char *) NULL)
4471 (void) FormatLocaleString(geometry,MaxTextExtent,"%s>!",
4472 resource_info->image_geometry);
4474 (void) FormatLocaleString(geometry,MaxTextExtent,"%ux%u+0+0>!",
4475 XDisplayWidth(display,windows->image.screen),
4476 XDisplayHeight(display,windows->image.screen));
4477 (void) ParseMetaGeometry(geometry,&x,&y,&width,&height);
4478 window_changes.width=(int) width;
4479 if (window_changes.width > XDisplayWidth(display,windows->image.screen))
4480 window_changes.width=XDisplayWidth(display,windows->image.screen);
4481 window_changes.height=(int) height;
4482 if (window_changes.height > XDisplayHeight(display,windows->image.screen))
4483 window_changes.height=XDisplayHeight(display,windows->image.screen);
4484 mask=(size_t) (CWWidth | CWHeight);
4485 if (resource_info->backdrop)
4488 window_changes.x=(int)
4489 ((XDisplayWidth(display,windows->image.screen)/2)-(width/2));
4490 window_changes.y=(int)
4491 ((XDisplayHeight(display,windows->image.screen)/2)-(height/2));
4493 (void) XReconfigureWMWindow(display,windows->image.id,windows->image.screen,
4494 (unsigned int) mask,&window_changes);
4495 (void) XClearWindow(display,windows->image.id);
4496 XRefreshWindow(display,&windows->image,(XEvent *) NULL);
4498 Update Magnify window configuration.
4500 if (IfMagickTrue(windows->magnify.mapped) )
4501 XMakeMagnifyImage(display,windows,exception);
4502 windows->pan.crop_geometry=windows->image.crop_geometry;
4503 XBestIconSize(display,&windows->pan,image);
4504 while (((windows->pan.width << 1) < MaxIconSize) &&
4505 ((windows->pan.height << 1) < MaxIconSize))
4507 windows->pan.width<<=1;
4508 windows->pan.height<<=1;
4510 if (windows->pan.geometry != (char *) NULL)
4511 (void) XParseGeometry(windows->pan.geometry,&windows->pan.x,&windows->pan.y,
4512 &windows->pan.width,&windows->pan.height);
4513 window_changes.width=(int) windows->pan.width;
4514 window_changes.height=(int) windows->pan.height;
4515 size_hints=XAllocSizeHints();
4516 if (size_hints != (XSizeHints *) NULL)
4521 size_hints->flags=PSize | PMinSize | PMaxSize;
4522 size_hints->width=window_changes.width;
4523 size_hints->height=window_changes.height;
4524 size_hints->min_width=size_hints->width;
4525 size_hints->min_height=size_hints->height;
4526 size_hints->max_width=size_hints->width;
4527 size_hints->max_height=size_hints->height;
4528 (void) XSetNormalHints(display,windows->pan.id,size_hints);
4529 (void) XFree((void *) size_hints);
4531 (void) XReconfigureWMWindow(display,windows->pan.id,windows->pan.screen,
4532 (unsigned int) (CWWidth | CWHeight),&window_changes);
4534 Update icon window configuration.
4536 windows->icon.crop_geometry=windows->image.crop_geometry;
4537 XBestIconSize(display,&windows->icon,image);
4538 window_changes.width=(int) windows->icon.width;
4539 window_changes.height=(int) windows->icon.height;
4540 (void) XReconfigureWMWindow(display,windows->icon.id,windows->icon.screen,
4541 (unsigned int) (CWWidth | CWHeight),&window_changes);
4542 XSetCursorState(display,windows,MagickFalse);
4543 return(IsMagickTrue(status));
4547 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4551 + X C r o p I m a g e %
4555 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4557 % XCropImage() allows the user to select a region of the image and crop, copy,
4558 % or cut it. For copy or cut, the image can subsequently be composited onto
4559 % the image with XPasteImage.
4561 % The format of the XCropImage method is:
4563 % MagickBooleanType XCropImage(Display *display,
4564 % XResourceInfo *resource_info,XWindows *windows,Image *image,
4565 % const ClipboardMode mode,ExceptionInfo *exception)
4567 % A description of each parameter follows:
4569 % o display: Specifies a connection to an X server; returned from
4572 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
4574 % o windows: Specifies a pointer to a XWindows structure.
4576 % o image: the image; returned from ReadImage.
4578 % o mode: This unsigned value specified whether the image should be
4579 % cropped, copied, or cut.
4581 % o exception: return any errors or warnings in this structure.
4584 static MagickBooleanType XCropImage(Display *display,
4585 XResourceInfo *resource_info,XWindows *windows,Image *image,
4586 const ClipboardMode mode,ExceptionInfo *exception)
4595 *RectifyModeMenu[] =
4603 static const ModeType
4613 RectifyDismissCommand
4620 command[MaxTextExtent],
4621 text[MaxTextExtent];
4664 (void) CloneString(&windows->command.name,"Copy");
4669 (void) CloneString(&windows->command.name,"Crop");
4674 (void) CloneString(&windows->command.name,"Cut");
4678 RectifyModeMenu[0]=windows->command.name;
4679 windows->command.data=0;
4680 (void) XCommandWidget(display,windows,CropModeMenu,(XEvent *) NULL);
4681 (void) XMapRaised(display,windows->command.id);
4682 XClientMessage(display,windows->image.id,windows->im_protocols,
4683 windows->im_update_widget,CurrentTime);
4685 Track pointer until button 1 is pressed.
4687 XQueryPosition(display,windows->image.id,&x,&y);
4688 (void) XSelectInput(display,windows->image.id,
4689 windows->image.attributes.event_mask | PointerMotionMask);
4690 crop_info.x=(ssize_t) windows->image.x+x;
4691 crop_info.y=(ssize_t) windows->image.y+y;
4694 cursor=XCreateFontCursor(display,XC_fleur);
4698 if (IfMagickTrue(windows->info.mapped) )
4701 Display pointer position.
4703 (void) FormatLocaleString(text,MaxTextExtent," %+ld%+ld ",
4704 (long) crop_info.x,(long) crop_info.y);
4705 XInfoWidget(display,windows,text);
4708 Wait for next event.
4710 XScreenEvent(display,windows,&event,exception);
4711 if (event.xany.window == windows->command.id)
4714 Select a command from the Command widget.
4716 id=XCommandWidget(display,windows,CropModeMenu,&event);
4719 switch (CropCommands[id])
4721 case CropHelpCommand:
4727 XTextViewWidget(display,resource_info,windows,MagickFalse,
4728 "Help Viewer - Image Copy",ImageCopyHelp);
4733 XTextViewWidget(display,resource_info,windows,MagickFalse,
4734 "Help Viewer - Image Crop",ImageCropHelp);
4739 XTextViewWidget(display,resource_info,windows,MagickFalse,
4740 "Help Viewer - Image Cut",ImageCutHelp);
4746 case CropDismissCommand:
4764 if (event.xbutton.button != Button1)
4766 if (event.xbutton.window != windows->image.id)
4769 Note first corner of cropping rectangle-- exit loop.
4771 (void) XCheckDefineCursor(display,windows->image.id,cursor);
4772 crop_info.x=(ssize_t) windows->image.x+event.xbutton.x;
4773 crop_info.y=(ssize_t) windows->image.y+event.xbutton.y;
4783 if (event.xkey.window != windows->image.id)
4786 Respond to a user key press.
4788 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
4789 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
4790 switch ((int) key_symbol)
4809 XTextViewWidget(display,resource_info,windows,MagickFalse,
4810 "Help Viewer - Image Copy",ImageCopyHelp);
4815 XTextViewWidget(display,resource_info,windows,MagickFalse,
4816 "Help Viewer - Image Crop",ImageCropHelp);
4821 XTextViewWidget(display,resource_info,windows,MagickFalse,
4822 "Help Viewer - Image Cut",ImageCutHelp);
4830 (void) XBell(display,0);
4838 if (event.xmotion.window != windows->image.id)
4841 Map and unmap Info widget as text cursor crosses its boundaries.
4845 if (IfMagickTrue(windows->info.mapped) )
4847 if ((x < (int) (windows->info.x+windows->info.width)) &&
4848 (y < (int) (windows->info.y+windows->info.height)))
4849 (void) XWithdrawWindow(display,windows->info.id,
4850 windows->info.screen);
4853 if ((x > (int) (windows->info.x+windows->info.width)) ||
4854 (y > (int) (windows->info.y+windows->info.height)))
4855 (void) XMapWindow(display,windows->info.id);
4856 crop_info.x=(ssize_t) windows->image.x+x;
4857 crop_info.y=(ssize_t) windows->image.y+y;
4863 } while ((state & ExitState) == 0);
4864 (void) XSelectInput(display,windows->image.id,
4865 windows->image.attributes.event_mask);
4866 if ((state & EscapeState) != 0)
4869 User want to exit without cropping.
4871 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
4872 (void) XFreeCursor(display,cursor);
4875 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
4879 Size rectangle as pointer moves until the mouse button is released.
4881 x=(int) crop_info.x;
4882 y=(int) crop_info.y;
4888 highlight_info=crop_info;
4889 highlight_info.x=crop_info.x-windows->image.x;
4890 highlight_info.y=crop_info.y-windows->image.y;
4891 if ((highlight_info.width > 3) && (highlight_info.height > 3))
4894 Display info and draw cropping rectangle.
4896 if (IfMagickFalse(windows->info.mapped) )
4897 (void) XMapWindow(display,windows->info.id);
4898 (void) FormatLocaleString(text,MaxTextExtent,
4899 " %.20gx%.20g%+.20g%+.20g",(double) crop_info.width,(double)
4900 crop_info.height,(double) crop_info.x,(double) crop_info.y);
4901 XInfoWidget(display,windows,text);
4902 XHighlightRectangle(display,windows->image.id,
4903 windows->image.highlight_context,&highlight_info);
4906 if (IfMagickTrue(windows->info.mapped) )
4907 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
4909 Wait for next event.
4911 XScreenEvent(display,windows,&event,exception);
4912 if ((highlight_info.width > 3) && (highlight_info.height > 3))
4913 XHighlightRectangle(display,windows->image.id,
4914 windows->image.highlight_context,&highlight_info);
4919 crop_info.x=(ssize_t) windows->image.x+event.xbutton.x;
4920 crop_info.y=(ssize_t) windows->image.y+event.xbutton.y;
4926 User has committed to cropping rectangle.
4928 crop_info.x=(ssize_t) windows->image.x+event.xbutton.x;
4929 crop_info.y=(ssize_t) windows->image.y+event.xbutton.y;
4930 XSetCursorState(display,windows,MagickFalse);
4932 windows->command.data=0;
4933 (void) XCommandWidget(display,windows,RectifyModeMenu,
4941 crop_info.x=(ssize_t) windows->image.x+event.xmotion.x;
4942 crop_info.y=(ssize_t) windows->image.y+event.xmotion.y;
4947 if ((((int) crop_info.x != x) && ((int) crop_info.y != y)) ||
4948 ((state & ExitState) != 0))
4951 Check boundary conditions.
4953 if (crop_info.x < 0)
4956 if (crop_info.x > (ssize_t) windows->image.ximage->width)
4957 crop_info.x=(ssize_t) windows->image.ximage->width;
4958 if ((int) crop_info.x < x)
4959 crop_info.width=(unsigned int) (x-crop_info.x);
4962 crop_info.width=(unsigned int) (crop_info.x-x);
4963 crop_info.x=(ssize_t) x;
4965 if (crop_info.y < 0)
4968 if (crop_info.y > (ssize_t) windows->image.ximage->height)
4969 crop_info.y=(ssize_t) windows->image.ximage->height;
4970 if ((int) crop_info.y < y)
4971 crop_info.height=(unsigned int) (y-crop_info.y);
4974 crop_info.height=(unsigned int) (crop_info.y-y);
4975 crop_info.y=(ssize_t) y;
4978 } while ((state & ExitState) == 0);
4980 Wait for user to grab a corner of the rectangle or press return.
4983 (void) XMapWindow(display,windows->info.id);
4986 if (IfMagickTrue(windows->info.mapped) )
4989 Display pointer position.
4991 (void) FormatLocaleString(text,MaxTextExtent,
4992 " %.20gx%.20g%+.20g%+.20g",(double) crop_info.width,(double)
4993 crop_info.height,(double) crop_info.x,(double) crop_info.y);
4994 XInfoWidget(display,windows,text);
4996 highlight_info=crop_info;
4997 highlight_info.x=crop_info.x-windows->image.x;
4998 highlight_info.y=crop_info.y-windows->image.y;
4999 if ((highlight_info.width <= 3) || (highlight_info.height <= 3))
5005 XHighlightRectangle(display,windows->image.id,
5006 windows->image.highlight_context,&highlight_info);
5007 XScreenEvent(display,windows,&event,exception);
5008 if (event.xany.window == windows->command.id)
5011 Select a command from the Command widget.
5013 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
5014 id=XCommandWidget(display,windows,RectifyModeMenu,&event);
5015 (void) XSetFunction(display,windows->image.highlight_context,
5017 XHighlightRectangle(display,windows->image.id,
5018 windows->image.highlight_context,&highlight_info);
5020 switch (RectifyCommands[id])
5022 case RectifyCopyCommand:
5027 case RectifyHelpCommand:
5029 (void) XSetFunction(display,windows->image.highlight_context,
5035 XTextViewWidget(display,resource_info,windows,MagickFalse,
5036 "Help Viewer - Image Copy",ImageCopyHelp);
5041 XTextViewWidget(display,resource_info,windows,MagickFalse,
5042 "Help Viewer - Image Crop",ImageCropHelp);
5047 XTextViewWidget(display,resource_info,windows,MagickFalse,
5048 "Help Viewer - Image Cut",ImageCutHelp);
5052 (void) XSetFunction(display,windows->image.highlight_context,
5056 case RectifyDismissCommand:
5070 XHighlightRectangle(display,windows->image.id,
5071 windows->image.highlight_context,&highlight_info);
5076 if (event.xbutton.button != Button1)
5078 if (event.xbutton.window != windows->image.id)
5080 x=windows->image.x+event.xbutton.x;
5081 y=windows->image.y+event.xbutton.y;
5082 if ((x < (int) (crop_info.x+RoiDelta)) &&
5083 (x > (int) (crop_info.x-RoiDelta)) &&
5084 (y < (int) (crop_info.y+RoiDelta)) &&
5085 (y > (int) (crop_info.y-RoiDelta)))
5087 crop_info.x=(ssize_t) (crop_info.x+crop_info.width);
5088 crop_info.y=(ssize_t) (crop_info.y+crop_info.height);
5089 state|=UpdateConfigurationState;
5092 if ((x < (int) (crop_info.x+RoiDelta)) &&
5093 (x > (int) (crop_info.x-RoiDelta)) &&
5094 (y < (int) (crop_info.y+crop_info.height+RoiDelta)) &&
5095 (y > (int) (crop_info.y+crop_info.height-RoiDelta)))
5097 crop_info.x=(ssize_t) (crop_info.x+crop_info.width);
5098 state|=UpdateConfigurationState;
5101 if ((x < (int) (crop_info.x+crop_info.width+RoiDelta)) &&
5102 (x > (int) (crop_info.x+crop_info.width-RoiDelta)) &&
5103 (y < (int) (crop_info.y+RoiDelta)) &&
5104 (y > (int) (crop_info.y-RoiDelta)))
5106 crop_info.y=(ssize_t) (crop_info.y+crop_info.height);
5107 state|=UpdateConfigurationState;
5110 if ((x < (int) (crop_info.x+crop_info.width+RoiDelta)) &&
5111 (x > (int) (crop_info.x+crop_info.width-RoiDelta)) &&
5112 (y < (int) (crop_info.y+crop_info.height+RoiDelta)) &&
5113 (y > (int) (crop_info.y+crop_info.height-RoiDelta)))
5115 state|=UpdateConfigurationState;
5121 if (event.xbutton.window == windows->pan.id)
5122 if ((highlight_info.x != crop_info.x-windows->image.x) ||
5123 (highlight_info.y != crop_info.y-windows->image.y))
5124 XHighlightRectangle(display,windows->image.id,
5125 windows->image.highlight_context,&highlight_info);
5126 (void) XSetSelectionOwner(display,XA_PRIMARY,windows->image.id,
5127 event.xbutton.time);
5132 if (event.xexpose.window == windows->image.id)
5133 if (event.xexpose.count == 0)
5135 event.xexpose.x=(int) highlight_info.x;
5136 event.xexpose.y=(int) highlight_info.y;
5137 event.xexpose.width=(int) highlight_info.width;
5138 event.xexpose.height=(int) highlight_info.height;
5139 XRefreshWindow(display,&windows->image,&event);
5141 if (event.xexpose.window == windows->info.id)
5142 if (event.xexpose.count == 0)
5143 XInfoWidget(display,windows,text);
5148 if (event.xkey.window != windows->image.id)
5151 Respond to a user key press.
5153 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
5154 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
5155 switch ((int) key_symbol)
5168 crop_info.x=(ssize_t) (windows->image.width/2L-
5169 crop_info.width/2L);
5170 crop_info.y=(ssize_t) (windows->image.height/2L-
5171 crop_info.height/2L);
5203 (void) XSetFunction(display,windows->image.highlight_context,
5209 XTextViewWidget(display,resource_info,windows,MagickFalse,
5210 "Help Viewer - Image Copy",ImageCopyHelp);
5215 XTextViewWidget(display,resource_info,windows,MagickFalse,
5216 "Help Viewer - Image Cropg",ImageCropHelp);
5221 XTextViewWidget(display,resource_info,windows,MagickFalse,
5222 "Help Viewer - Image Cutg",ImageCutHelp);
5226 (void) XSetFunction(display,windows->image.highlight_context,
5232 (void) XBell(display,0);
5236 (void) XSetSelectionOwner(display,XA_PRIMARY,windows->image.id,
5244 if (event.xmotion.window != windows->image.id)
5247 Map and unmap Info widget as text cursor crosses its boundaries.
5251 if (IfMagickTrue(windows->info.mapped) )
5253 if ((x < (int) (windows->info.x+windows->info.width)) &&
5254 (y < (int) (windows->info.y+windows->info.height)))
5255 (void) XWithdrawWindow(display,windows->info.id,
5256 windows->info.screen);
5259 if ((x > (int) (windows->info.x+windows->info.width)) ||
5260 (y > (int) (windows->info.y+windows->info.height)))
5261 (void) XMapWindow(display,windows->info.id);
5262 crop_info.x=(ssize_t) windows->image.x+event.xmotion.x;
5263 crop_info.y=(ssize_t) windows->image.y+event.xmotion.y;
5266 case SelectionRequest:
5271 XSelectionRequestEvent
5275 Set primary selection.
5277 (void) FormatLocaleString(text,MaxTextExtent,
5278 "%.20gx%.20g%+.20g%+.20g",(double) crop_info.width,(double)
5279 crop_info.height,(double) crop_info.x,(double) crop_info.y);
5280 request=(&(event.xselectionrequest));
5281 (void) XChangeProperty(request->display,request->requestor,
5282 request->property,request->target,8,PropModeReplace,
5283 (unsigned char *) text,(int) strlen(text));
5284 notify.type=SelectionNotify;
5285 notify.display=request->display;
5286 notify.requestor=request->requestor;
5287 notify.selection=request->selection;
5288 notify.target=request->target;
5289 notify.time=request->time;
5290 if (request->property == None)
5291 notify.property=request->target;
5293 notify.property=request->property;
5294 (void) XSendEvent(request->display,request->requestor,False,0,
5295 (XEvent *) ¬ify);
5300 if ((state & UpdateConfigurationState) != 0)
5302 (void) XPutBackEvent(display,&event);
5303 (void) XCheckDefineCursor(display,windows->image.id,cursor);
5306 } while ((state & ExitState) == 0);
5307 } while ((state & ExitState) == 0);
5308 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
5309 XSetCursorState(display,windows,MagickFalse);
5310 if ((state & EscapeState) != 0)
5312 if (mode == CropMode)
5313 if (((int) crop_info.width != windows->image.ximage->width) ||
5314 ((int) crop_info.height != windows->image.ximage->height))
5317 Reconfigure Image window as defined by cropping rectangle.
5319 XSetCropGeometry(display,windows,&crop_info,image);
5320 windows->image.window_changes.width=(int) crop_info.width;
5321 windows->image.window_changes.height=(int) crop_info.height;
5322 (void) XConfigureImage(display,resource_info,windows,image,exception);
5326 Copy image before applying image transforms.
5328 XSetCursorState(display,windows,MagickTrue);
5329 XCheckRefreshWindows(display,windows);
5330 width=(unsigned int) image->columns;
5331 height=(unsigned int) image->rows;
5334 if (windows->image.crop_geometry != (char *) NULL)
5335 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
5336 scale_factor=(double) width/windows->image.ximage->width;
5338 crop_info.x=(ssize_t) (scale_factor*crop_info.x+0.5);
5339 crop_info.width=(unsigned int) (scale_factor*crop_info.width+0.5);
5340 scale_factor=(double) height/windows->image.ximage->height;
5342 crop_info.y=(ssize_t) (scale_factor*crop_info.y+0.5);
5343 crop_info.height=(unsigned int) (scale_factor*crop_info.height+0.5);
5344 crop_image=CropImage(image,&crop_info,exception);
5345 XSetCursorState(display,windows,MagickFalse);
5346 if (crop_image == (Image *) NULL)
5347 return(MagickFalse);
5348 if (resource_info->copy_image != (Image *) NULL)
5349 resource_info->copy_image=DestroyImage(resource_info->copy_image);
5350 resource_info->copy_image=crop_image;
5351 if (mode == CopyMode)
5353 (void) XConfigureImage(display,resource_info,windows,image,exception);
5359 if (IfMagickFalse(SetImageStorageClass(image,DirectClass,exception)) )
5360 return(MagickFalse);
5361 image->alpha_trait=BlendPixelTrait;
5362 image_view=AcquireAuthenticCacheView(image,exception);
5363 for (y=0; y < (int) crop_info.height; y++)
5365 q=GetCacheViewAuthenticPixels(image_view,crop_info.x,y+crop_info.y,
5366 crop_info.width,1,exception);
5367 if (q == (Quantum *) NULL)
5369 for (x=0; x < (int) crop_info.width; x++)
5371 SetPixelAlpha(image,TransparentAlpha,q);
5372 q+=GetPixelChannels(image);
5374 if (IfMagickFalse(SyncCacheViewAuthenticPixels(image_view,exception)) )
5377 image_view=DestroyCacheView(image_view);
5379 Update image configuration.
5381 XConfigureImageColormap(display,resource_info,windows,image,exception);
5382 (void) XConfigureImage(display,resource_info,windows,image,exception);
5387 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5391 + X D r a w I m a g e %
5395 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5397 % XDrawEditImage() draws a graphic element (point, line, rectangle, etc.) on
5400 % The format of the XDrawEditImage method is:
5402 % MagickBooleanType XDrawEditImage(Display *display,
5403 % XResourceInfo *resource_info,XWindows *windows,Image **image,
5404 % ExceptionInfo *exception)
5406 % A description of each parameter follows:
5408 % o display: Specifies a connection to an X server; returned from
5411 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5413 % o windows: Specifies a pointer to a XWindows structure.
5415 % o image: the image.
5417 % o exception: return any errors or warnings in this structure.
5420 static MagickBooleanType XDrawEditImage(Display *display,
5421 XResourceInfo *resource_info,XWindows *windows,Image **image,
5422 ExceptionInfo *exception)
5438 element = PointElement;
5440 static const ModeType
5453 stipple = (Pixmap) NULL;
5460 command[MaxTextExtent],
5461 text[MaxTextExtent];
5510 Allocate polygon info.
5512 max_coordinates=2048;
5513 coordinate_info=(XPoint *) AcquireQuantumMemory((size_t) max_coordinates,
5514 sizeof(*coordinate_info));
5515 if (coordinate_info == (XPoint *) NULL)
5517 (void) ThrowMagickException(exception,GetMagickModule(),
5518 ResourceLimitError,"MemoryAllocationFailed","`%s'","...");
5519 return(MagickFalse);
5524 (void) CloneString(&windows->command.name,"Draw");
5525 windows->command.data=4;
5526 (void) XCommandWidget(display,windows,DrawMenu,(XEvent *) NULL);
5527 (void) XMapRaised(display,windows->command.id);
5528 XClientMessage(display,windows->image.id,windows->im_protocols,
5529 windows->im_update_widget,CurrentTime);
5531 Wait for first button press.
5533 root_window=XRootWindow(display,XDefaultScreen(display));
5534 draw_info.stencil=OpaqueStencil;
5536 cursor=XCreateFontCursor(display,XC_tcross);
5539 XQueryPosition(display,windows->image.id,&x,&y);
5540 (void) XSelectInput(display,windows->image.id,
5541 windows->image.attributes.event_mask | PointerMotionMask);
5542 (void) XCheckDefineCursor(display,windows->image.id,cursor);
5546 if (IfMagickTrue(windows->info.mapped) )
5549 Display pointer position.
5551 (void) FormatLocaleString(text,MaxTextExtent," %+d%+d ",
5552 x+windows->image.x,y+windows->image.y);
5553 XInfoWidget(display,windows,text);
5556 Wait for next event.
5558 XScreenEvent(display,windows,&event,exception);
5559 if (event.xany.window == windows->command.id)
5562 Select a command from the Command widget.
5564 id=XCommandWidget(display,windows,DrawMenu,&event);
5567 switch (DrawCommands[id])
5569 case DrawElementCommand:
5588 Select a command from the pop-up menu.
5590 element=(ElementType) (XMenuWidget(display,windows,
5591 DrawMenu[id],Elements,command)+1);
5594 case DrawColorCommand:
5597 *ColorMenu[MaxNumberPens+1];
5609 Initialize menu selections.
5611 for (i=0; i < (int) (MaxNumberPens-2); i++)
5612 ColorMenu[i]=resource_info->pen_colors[i];
5613 ColorMenu[MaxNumberPens-2]="transparent";
5614 ColorMenu[MaxNumberPens-1]="Browser...";
5615 ColorMenu[MaxNumberPens]=(char *) NULL;
5617 Select a pen color from the pop-up menu.
5619 pen_number=XMenuWidget(display,windows,DrawMenu[id],
5620 (const char **) ColorMenu,command);
5623 transparent=pen_number == (MaxNumberPens-2) ? MagickTrue :
5625 if (IfMagickTrue(transparent) )
5627 draw_info.stencil=TransparentStencil;
5630 if (pen_number == (MaxNumberPens-1))
5633 color_name[MaxTextExtent] = "gray";
5636 Select a pen color from a dialog.
5638 resource_info->pen_colors[pen_number]=color_name;
5639 XColorBrowserWidget(display,windows,"Select",color_name);
5640 if (*color_name == '\0')
5646 (void) XParseColor(display,windows->map_info->colormap,
5647 resource_info->pen_colors[pen_number],&color);
5648 XBestPixel(display,windows->map_info->colormap,(XColor *) NULL,
5649 (unsigned int) MaxColors,&color);
5650 windows->pixel_info->pen_colors[pen_number]=color;
5651 pen_id=(unsigned int) pen_number;
5652 draw_info.stencil=OpaqueStencil;
5655 case DrawStippleCommand:
5667 filename[MaxTextExtent] = "\0";
5684 Select a command from the pop-up menu.
5686 StipplesMenu[7]="Open...";
5687 entry=XMenuWidget(display,windows,DrawMenu[id],StipplesMenu,
5691 if (stipple != (Pixmap) NULL)
5692 (void) XFreePixmap(display,stipple);
5693 stipple=(Pixmap) NULL;
5700 stipple=XCreateBitmapFromData(display,root_window,
5701 (char *) BricksBitmap,BricksWidth,BricksHeight);
5706 stipple=XCreateBitmapFromData(display,root_window,
5707 (char *) DiagonalBitmap,DiagonalWidth,DiagonalHeight);
5712 stipple=XCreateBitmapFromData(display,root_window,
5713 (char *) ScalesBitmap,ScalesWidth,ScalesHeight);
5718 stipple=XCreateBitmapFromData(display,root_window,
5719 (char *) VerticalBitmap,VerticalWidth,VerticalHeight);
5724 stipple=XCreateBitmapFromData(display,root_window,
5725 (char *) WavyBitmap,WavyWidth,WavyHeight);
5730 stipple=XCreateBitmapFromData(display,root_window,
5731 (char *) HighlightBitmap,HighlightWidth,
5738 stipple=XCreateBitmapFromData(display,root_window,
5739 (char *) OpaqueBitmap,OpaqueWidth,OpaqueHeight);
5745 XFileBrowserWidget(display,windows,"Stipple",filename);
5746 if (*filename == '\0')
5751 XSetCursorState(display,windows,MagickTrue);
5752 XCheckRefreshWindows(display,windows);
5753 image_info=AcquireImageInfo();
5754 (void) CopyMagickString(image_info->filename,filename,
5756 stipple_image=ReadImage(image_info,exception);
5757 CatchException(exception);
5758 XSetCursorState(display,windows,MagickFalse);
5759 if (stipple_image == (Image *) NULL)
5761 (void) AcquireUniqueFileResource(filename);
5762 (void) FormatLocaleString(stipple_image->filename,MaxTextExtent,
5764 (void) WriteImage(image_info,stipple_image,exception);
5765 stipple_image=DestroyImage(stipple_image);
5766 image_info=DestroyImageInfo(image_info);
5767 status=XReadBitmapFile(display,root_window,filename,&width,
5768 &height,&stipple,&x,&y);
5769 (void) RelinquishUniqueFileResource(filename);
5770 if ((status != BitmapSuccess) != 0)
5771 XNoticeWidget(display,windows,"Unable to read X bitmap image:",
5775 case DrawWidthCommand:
5778 width[MaxTextExtent] = "0";
5793 Select a command from the pop-up menu.
5795 entry=XMenuWidget(display,windows,DrawMenu[id],WidthsMenu,
5801 line_width=(unsigned int) StringToUnsignedLong(
5805 (void) XDialogWidget(display,windows,"Ok","Enter line width:",
5809 line_width=(unsigned int) StringToUnsignedLong(width);
5812 case DrawUndoCommand:
5814 (void) XMagickCommand(display,resource_info,windows,UndoCommand,
5818 case DrawHelpCommand:
5820 XTextViewWidget(display,resource_info,windows,MagickFalse,
5821 "Help Viewer - Image Rotation",ImageDrawHelp);
5822 (void) XCheckDefineCursor(display,windows->image.id,cursor);
5825 case DrawDismissCommand:
5837 (void) XCheckDefineCursor(display,windows->image.id,cursor);
5844 if (event.xbutton.button != Button1)
5846 if (event.xbutton.window != windows->image.id)
5865 if (event.xkey.window != windows->image.id)
5868 Respond to a user key press.
5870 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
5871 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
5872 switch ((int) key_symbol)
5887 XTextViewWidget(display,resource_info,windows,MagickFalse,
5888 "Help Viewer - Image Rotation",ImageDrawHelp);
5893 (void) XBell(display,0);
5902 Map and unmap Info widget as text cursor crosses its boundaries.
5906 if (IfMagickTrue(windows->info.mapped) )
5908 if ((x < (int) (windows->info.x+windows->info.width)) &&
5909 (y < (int) (windows->info.y+windows->info.height)))
5910 (void) XWithdrawWindow(display,windows->info.id,
5911 windows->info.screen);
5914 if ((x > (int) (windows->info.x+windows->info.width)) ||
5915 (y > (int) (windows->info.y+windows->info.height)))
5916 (void) XMapWindow(display,windows->info.id);
5920 } while ((state & ExitState) == 0);
5921 (void) XSelectInput(display,windows->image.id,
5922 windows->image.attributes.event_mask);
5923 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
5924 if ((state & EscapeState) != 0)
5927 Draw element as pointer moves until the button is released.
5935 rectangle_info.x=(ssize_t) x;
5936 rectangle_info.y=(ssize_t) y;
5937 rectangle_info.width=0;
5938 rectangle_info.height=0;
5939 number_coordinates=1;
5940 coordinate_info->x=x;
5941 coordinate_info->y=y;
5942 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
5951 if (number_coordinates > 1)
5953 (void) XDrawLines(display,windows->image.id,
5954 windows->image.highlight_context,coordinate_info,
5955 number_coordinates,CoordModeOrigin);
5956 (void) FormatLocaleString(text,MaxTextExtent," %+d%+d",
5957 coordinate_info[number_coordinates-1].x,
5958 coordinate_info[number_coordinates-1].y);
5959 XInfoWidget(display,windows,text);
5968 Display angle of the line.
5970 degrees=RadiansToDegrees(-atan2((double) (line_info.y2-
5971 line_info.y1),(double) (line_info.x2-line_info.x1)));
5972 (void) FormatLocaleString(text,MaxTextExtent," %g",
5974 XInfoWidget(display,windows,text);
5975 XHighlightLine(display,windows->image.id,
5976 windows->image.highlight_context,&line_info);
5979 if (IfMagickTrue(windows->info.mapped) )
5980 (void) XWithdrawWindow(display,windows->info.id,
5981 windows->info.screen);
5984 case RectangleElement:
5985 case FillRectangleElement:
5987 if ((rectangle_info.width > 3) && (rectangle_info.height > 3))
5990 Display info and draw drawing rectangle.
5992 (void) FormatLocaleString(text,MaxTextExtent,
5993 " %.20gx%.20g%+.20g%+.20g",(double) rectangle_info.width,
5994 (double) rectangle_info.height,(double) rectangle_info.x,
5995 (double) rectangle_info.y);
5996 XInfoWidget(display,windows,text);
5997 XHighlightRectangle(display,windows->image.id,
5998 windows->image.highlight_context,&rectangle_info);
6001 if (IfMagickTrue(windows->info.mapped) )
6002 (void) XWithdrawWindow(display,windows->info.id,
6003 windows->info.screen);
6007 case FillCircleElement:
6008 case EllipseElement:
6009 case FillEllipseElement:
6011 if ((rectangle_info.width > 3) && (rectangle_info.height > 3))
6014 Display info and draw drawing rectangle.
6016 (void) FormatLocaleString(text,MaxTextExtent,
6017 " %.20gx%.20g%+.20g%+.20g",(double) rectangle_info.width,
6018 (double) rectangle_info.height,(double) rectangle_info.x,
6019 (double) rectangle_info.y);
6020 XInfoWidget(display,windows,text);
6021 XHighlightEllipse(display,windows->image.id,
6022 windows->image.highlight_context,&rectangle_info);
6025 if (IfMagickTrue(windows->info.mapped) )
6026 (void) XWithdrawWindow(display,windows->info.id,
6027 windows->info.screen);
6030 case PolygonElement:
6031 case FillPolygonElement:
6033 if (number_coordinates > 1)
6034 (void) XDrawLines(display,windows->image.id,
6035 windows->image.highlight_context,coordinate_info,
6036 number_coordinates,CoordModeOrigin);
6040 Display angle of the line.
6042 degrees=RadiansToDegrees(-atan2((double) (line_info.y2-
6043 line_info.y1),(double) (line_info.x2-line_info.x1)));
6044 (void) FormatLocaleString(text,MaxTextExtent," %g",
6046 XInfoWidget(display,windows,text);
6047 XHighlightLine(display,windows->image.id,
6048 windows->image.highlight_context,&line_info);
6051 if (IfMagickTrue(windows->info.mapped) )
6052 (void) XWithdrawWindow(display,windows->info.id,
6053 windows->info.screen);
6058 Wait for next event.
6060 XScreenEvent(display,windows,&event,exception);
6066 if (number_coordinates > 1)
6067 (void) XDrawLines(display,windows->image.id,
6068 windows->image.highlight_context,coordinate_info,
6069 number_coordinates,CoordModeOrigin);
6075 XHighlightLine(display,windows->image.id,
6076 windows->image.highlight_context,&line_info);
6079 case RectangleElement:
6080 case FillRectangleElement:
6082 if ((rectangle_info.width > 3) && (rectangle_info.height > 3))
6083 XHighlightRectangle(display,windows->image.id,
6084 windows->image.highlight_context,&rectangle_info);
6088 case FillCircleElement:
6089 case EllipseElement:
6090 case FillEllipseElement:
6092 if ((rectangle_info.width > 3) && (rectangle_info.height > 3))
6093 XHighlightEllipse(display,windows->image.id,
6094 windows->image.highlight_context,&rectangle_info);
6097 case PolygonElement:
6098 case FillPolygonElement:
6100 if (number_coordinates > 1)
6101 (void) XDrawLines(display,windows->image.id,
6102 windows->image.highlight_context,coordinate_info,
6103 number_coordinates,CoordModeOrigin);
6105 XHighlightLine(display,windows->image.id,
6106 windows->image.highlight_context,&line_info);
6117 User has committed to element.
6119 line_info.x2=event.xbutton.x;
6120 line_info.y2=event.xbutton.y;
6121 rectangle_info.x=(ssize_t) event.xbutton.x;
6122 rectangle_info.y=(ssize_t) event.xbutton.y;
6123 coordinate_info[number_coordinates].x=event.xbutton.x;
6124 coordinate_info[number_coordinates].y=event.xbutton.y;
6125 if (((element != PolygonElement) &&
6126 (element != FillPolygonElement)) || (distance <= 9))
6131 number_coordinates++;
6132 if (number_coordinates < (int) max_coordinates)
6134 line_info.x1=event.xbutton.x;
6135 line_info.y1=event.xbutton.y;
6138 max_coordinates<<=1;
6139 coordinate_info=(XPoint *) ResizeQuantumMemory(coordinate_info,
6140 max_coordinates,sizeof(*coordinate_info));
6141 if (coordinate_info == (XPoint *) NULL)
6142 (void) ThrowMagickException(exception,GetMagickModule(),
6143 ResourceLimitError,"MemoryAllocationFailed","`%s'","...");
6150 if (event.xmotion.window != windows->image.id)
6152 if (element != PointElement)
6154 line_info.x2=event.xmotion.x;
6155 line_info.y2=event.xmotion.y;
6156 rectangle_info.x=(ssize_t) event.xmotion.x;
6157 rectangle_info.y=(ssize_t) event.xmotion.y;
6160 coordinate_info[number_coordinates].x=event.xbutton.x;
6161 coordinate_info[number_coordinates].y=event.xbutton.y;
6162 number_coordinates++;
6163 if (number_coordinates < (int) max_coordinates)
6165 max_coordinates<<=1;
6166 coordinate_info=(XPoint *) ResizeQuantumMemory(coordinate_info,
6167 max_coordinates,sizeof(*coordinate_info));
6168 if (coordinate_info == (XPoint *) NULL)
6169 (void) ThrowMagickException(exception,GetMagickModule(),
6170 ResourceLimitError,"MemoryAllocationFailed","`%s'","...");
6177 Check boundary conditions.
6179 if (line_info.x2 < 0)
6182 if (line_info.x2 > (int) windows->image.width)
6183 line_info.x2=(short) windows->image.width;
6184 if (line_info.y2 < 0)
6187 if (line_info.y2 > (int) windows->image.height)
6188 line_info.y2=(short) windows->image.height;
6189 distance=(unsigned int)
6190 (((line_info.x2-line_info.x1+1)*(line_info.x2-line_info.x1+1))+
6191 ((line_info.y2-line_info.y1+1)*(line_info.y2-line_info.y1+1)));
6192 if ((((int) rectangle_info.x != x) && ((int) rectangle_info.y != y)) ||
6193 ((state & ExitState) != 0))
6195 if (rectangle_info.x < 0)
6198 if (rectangle_info.x > (ssize_t) windows->image.width)
6199 rectangle_info.x=(ssize_t) windows->image.width;
6200 if ((int) rectangle_info.x < x)
6201 rectangle_info.width=(unsigned int) (x-rectangle_info.x);
6204 rectangle_info.width=(unsigned int) (rectangle_info.x-x);
6205 rectangle_info.x=(ssize_t) x;
6207 if (rectangle_info.y < 0)
6210 if (rectangle_info.y > (ssize_t) windows->image.height)
6211 rectangle_info.y=(ssize_t) windows->image.height;
6212 if ((int) rectangle_info.y < y)
6213 rectangle_info.height=(unsigned int) (y-rectangle_info.y);
6216 rectangle_info.height=(unsigned int) (rectangle_info.y-y);
6217 rectangle_info.y=(ssize_t) y;
6220 } while ((state & ExitState) == 0);
6221 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
6222 if ((element == PointElement) || (element == PolygonElement) ||
6223 (element == FillPolygonElement))
6226 Determine polygon bounding box.
6228 rectangle_info.x=(ssize_t) coordinate_info->x;
6229 rectangle_info.y=(ssize_t) coordinate_info->y;
6230 x=coordinate_info->x;
6231 y=coordinate_info->y;
6232 for (i=1; i < number_coordinates; i++)
6234 if (coordinate_info[i].x > x)
6235 x=coordinate_info[i].x;
6236 if (coordinate_info[i].y > y)
6237 y=coordinate_info[i].y;
6238 if ((ssize_t) coordinate_info[i].x < rectangle_info.x)
6239 rectangle_info.x=MagickMax((ssize_t) coordinate_info[i].x,0);
6240 if ((ssize_t) coordinate_info[i].y < rectangle_info.y)
6241 rectangle_info.y=MagickMax((ssize_t) coordinate_info[i].y,0);
6243 rectangle_info.width=(size_t) (x-rectangle_info.x);
6244 rectangle_info.height=(size_t) (y-rectangle_info.y);
6245 for (i=0; i < number_coordinates; i++)
6247 coordinate_info[i].x-=rectangle_info.x;
6248 coordinate_info[i].y-=rectangle_info.y;
6255 if ((element == RectangleElement) ||
6256 (element == CircleElement) || (element == EllipseElement))
6258 rectangle_info.width--;
6259 rectangle_info.height--;
6262 Drawing is relative to image configuration.
6264 draw_info.x=(int) rectangle_info.x;
6265 draw_info.y=(int) rectangle_info.y;
6266 (void) XMagickCommand(display,resource_info,windows,SaveToUndoBufferCommand,
6268 width=(unsigned int) (*image)->columns;
6269 height=(unsigned int) (*image)->rows;
6272 if (windows->image.crop_geometry != (char *) NULL)
6273 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
6274 draw_info.x+=windows->image.x-(line_width/2);
6275 if (draw_info.x < 0)
6277 draw_info.x=(int) (width*draw_info.x/windows->image.ximage->width);
6278 draw_info.y+=windows->image.y-(line_width/2);
6279 if (draw_info.y < 0)
6281 draw_info.y=(int) height*draw_info.y/windows->image.ximage->height;
6282 draw_info.width=(unsigned int) rectangle_info.width+(line_width << 1);
6283 if (draw_info.width > (unsigned int) (*image)->columns)
6284 draw_info.width=(unsigned int) (*image)->columns;
6285 draw_info.height=(unsigned int) rectangle_info.height+(line_width << 1);
6286 if (draw_info.height > (unsigned int) (*image)->rows)
6287 draw_info.height=(unsigned int) (*image)->rows;
6288 (void) FormatLocaleString(draw_info.geometry,MaxTextExtent,"%ux%u%+d%+d",
6289 width*draw_info.width/windows->image.ximage->width,
6290 height*draw_info.height/windows->image.ximage->height,
6291 draw_info.x+x,draw_info.y+y);
6293 Initialize drawing attributes.
6295 draw_info.degrees=0.0;
6296 draw_info.element=element;
6297 draw_info.stipple=stipple;
6298 draw_info.line_width=line_width;
6299 draw_info.line_info=line_info;
6300 if (line_info.x1 > (int) (line_width/2))
6301 draw_info.line_info.x1=(short) line_width/2;
6302 if (line_info.y1 > (int) (line_width/2))
6303 draw_info.line_info.y1=(short) line_width/2;
6304 draw_info.line_info.x2=(short) (line_info.x2-line_info.x1+(line_width/2));
6305 draw_info.line_info.y2=(short) (line_info.y2-line_info.y1+(line_width/2));
6306 if ((draw_info.line_info.x2 < 0) && (draw_info.line_info.y2 < 0))
6308 draw_info.line_info.x2=(-draw_info.line_info.x2);
6309 draw_info.line_info.y2=(-draw_info.line_info.y2);
6311 if (draw_info.line_info.x2 < 0)
6313 draw_info.line_info.x2=(-draw_info.line_info.x2);
6314 Swap(draw_info.line_info.x1,draw_info.line_info.x2);
6316 if (draw_info.line_info.y2 < 0)
6318 draw_info.line_info.y2=(-draw_info.line_info.y2);
6319 Swap(draw_info.line_info.y1,draw_info.line_info.y2);
6321 draw_info.rectangle_info=rectangle_info;
6322 if (draw_info.rectangle_info.x > (ssize_t) (line_width/2))
6323 draw_info.rectangle_info.x=(ssize_t) line_width/2;
6324 if (draw_info.rectangle_info.y > (ssize_t) (line_width/2))
6325 draw_info.rectangle_info.y=(ssize_t) line_width/2;
6326 draw_info.number_coordinates=(unsigned int) number_coordinates;
6327 draw_info.coordinate_info=coordinate_info;
6328 windows->pixel_info->pen_color=windows->pixel_info->pen_colors[pen_id];
6330 Draw element on image.
6332 XSetCursorState(display,windows,MagickTrue);
6333 XCheckRefreshWindows(display,windows);
6334 status=XDrawImage(display,windows->pixel_info,&draw_info,*image,exception);
6335 XSetCursorState(display,windows,MagickFalse);
6337 Update image colormap and return to image drawing.
6339 XConfigureImageColormap(display,resource_info,windows,*image,exception);
6340 (void) XConfigureImage(display,resource_info,windows,*image,exception);
6342 XSetCursorState(display,windows,MagickFalse);
6343 coordinate_info=(XPoint *) RelinquishMagickMemory(coordinate_info);
6344 return(IsMagickTrue(status));
6348 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6352 + X D r a w P a n R e c t a n g l e %
6356 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6358 % XDrawPanRectangle() draws a rectangle in the pan window. The pan window
6359 % displays a zoom image and the rectangle shows which portion of the image is
6360 % displayed in the Image window.
6362 % The format of the XDrawPanRectangle method is:
6364 % XDrawPanRectangle(Display *display,XWindows *windows)
6366 % A description of each parameter follows:
6368 % o display: Specifies a connection to an X server; returned from
6371 % o windows: Specifies a pointer to a XWindows structure.
6374 static void XDrawPanRectangle(Display *display,XWindows *windows)
6383 Determine dimensions of the panning rectangle.
6385 scale_factor=(double) windows->pan.width/windows->image.ximage->width;
6386 highlight_info.x=(ssize_t) (scale_factor*windows->image.x+0.5);
6387 highlight_info.width=(unsigned int) (scale_factor*windows->image.width+0.5);
6388 scale_factor=(double)
6389 windows->pan.height/windows->image.ximage->height;
6390 highlight_info.y=(ssize_t) (scale_factor*windows->image.y+0.5);
6391 highlight_info.height=(unsigned int) (scale_factor*windows->image.height+0.5);
6393 Display the panning rectangle.
6395 (void) XClearWindow(display,windows->pan.id);
6396 XHighlightRectangle(display,windows->pan.id,windows->pan.annotate_context,
6401 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6405 + X I m a g e C a c h e %
6409 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6411 % XImageCache() handles the creation, manipulation, and destruction of the
6412 % image cache (undo and redo buffers).
6414 % The format of the XImageCache method is:
6416 % void XImageCache(Display *display,XResourceInfo *resource_info,
6417 % XWindows *windows,const CommandType command,Image **image,
6418 % ExceptionInfo *exception)
6420 % A description of each parameter follows:
6422 % o display: Specifies a connection to an X server; returned from
6425 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
6427 % o windows: Specifies a pointer to a XWindows structure.
6429 % o command: Specifies a command to perform.
6431 % o image: the image; XImageCache may transform the image and return a new
6434 % o exception: return any errors or warnings in this structure.
6437 static void XImageCache(Display *display,XResourceInfo *resource_info,
6438 XWindows *windows,const CommandType command,Image **image,
6439 ExceptionInfo *exception)
6445 *redo_image = (Image *) NULL,
6446 *undo_image = (Image *) NULL;
6450 case FreeBuffersCommand:
6453 Free memory from the undo and redo cache.
6455 while (undo_image != (Image *) NULL)
6457 cache_image=undo_image;
6458 undo_image=GetPreviousImageInList(undo_image);
6459 cache_image->list=DestroyImage(cache_image->list);
6460 cache_image=DestroyImage(cache_image);
6462 undo_image=NewImageList();
6463 if (redo_image != (Image *) NULL)
6464 redo_image=DestroyImage(redo_image);
6465 redo_image=NewImageList();
6471 image_geometry[MaxTextExtent];
6474 Undo the last image transformation.
6476 if (undo_image == (Image *) NULL)
6478 (void) XBell(display,0);
6481 cache_image=undo_image;
6482 undo_image=GetPreviousImageInList(undo_image);
6483 windows->image.window_changes.width=(int) cache_image->columns;
6484 windows->image.window_changes.height=(int) cache_image->rows;
6485 (void) FormatLocaleString(image_geometry,MaxTextExtent,"%dx%d!",
6486 windows->image.ximage->width,windows->image.ximage->height);
6487 (void) TransformImage(image,windows->image.crop_geometry,image_geometry,
6489 if (windows->image.crop_geometry != (char *) NULL)
6490 windows->image.crop_geometry=(char *) RelinquishMagickMemory(
6491 windows->image.crop_geometry);
6492 windows->image.crop_geometry=cache_image->geometry;
6493 if (redo_image != (Image *) NULL)
6494 redo_image=DestroyImage(redo_image);
6495 redo_image=(*image);
6496 *image=cache_image->list;
6497 cache_image=DestroyImage(cache_image);
6498 if (IfMagickTrue(windows->image.orphan) )
6500 XConfigureImageColormap(display,resource_info,windows,*image,exception);
6501 (void) XConfigureImage(display,resource_info,windows,*image,exception);
6507 case HalfSizeCommand:
6508 case OriginalSizeCommand:
6509 case DoubleSizeCommand:
6516 case RotateRightCommand:
6517 case RotateLeftCommand:
6522 case ContrastStretchCommand:
6523 case SigmoidalContrastCommand:
6524 case NormalizeCommand:
6525 case EqualizeCommand:
6527 case SaturationCommand:
6528 case BrightnessCommand:
6532 case GrayscaleCommand:
6534 case QuantizeCommand:
6535 case DespeckleCommand:
6537 case ReduceNoiseCommand:
6538 case AddNoiseCommand:
6539 case SharpenCommand:
6541 case ThresholdCommand:
6542 case EdgeDetectCommand:
6546 case SegmentCommand:
6547 case SolarizeCommand:
6548 case SepiaToneCommand:
6550 case ImplodeCommand:
6551 case VignetteCommand:
6553 case OilPaintCommand:
6554 case CharcoalDrawCommand:
6555 case AnnotateCommand:
6556 case AddBorderCommand:
6557 case AddFrameCommand:
6558 case CompositeCommand:
6559 case CommentCommand:
6561 case RegionofInterestCommand:
6562 case SaveToUndoBufferCommand:
6571 bytes=(ssize_t) ((*image)->columns*(*image)->rows*sizeof(PixelInfo));
6572 if (undo_image != (Image *) NULL)
6575 Ensure the undo cache has enough memory available.
6577 previous_image=undo_image;
6578 while (previous_image != (Image *) NULL)
6580 bytes+=previous_image->list->columns*previous_image->list->rows*
6582 if (bytes <= (ssize_t) (resource_info->undo_cache << 20))
6584 previous_image=GetPreviousImageInList(previous_image);
6587 bytes-=previous_image->list->columns*previous_image->list->rows*
6589 if (previous_image == undo_image)
6590 undo_image=NewImageList();
6592 previous_image->next->previous=NewImageList();
6595 while (previous_image != (Image *) NULL)
6598 Delete any excess memory from undo cache.
6600 cache_image=previous_image;
6601 previous_image=GetPreviousImageInList(previous_image);
6602 cache_image->list=DestroyImage(cache_image->list);
6603 cache_image=DestroyImage(cache_image);
6606 if (bytes > (ssize_t) (resource_info->undo_cache << 20))
6609 Save image before transformations are applied.
6611 cache_image=AcquireImage((ImageInfo *) NULL,exception);
6612 if (cache_image == (Image *) NULL)
6614 XSetCursorState(display,windows,MagickTrue);
6615 XCheckRefreshWindows(display,windows);
6616 cache_image->list=CloneImage(*image,0,0,MagickTrue,exception);
6617 XSetCursorState(display,windows,MagickFalse);
6618 if (cache_image->list == (Image *) NULL)
6620 cache_image=DestroyImage(cache_image);
6623 cache_image->columns=(size_t) windows->image.ximage->width;
6624 cache_image->rows=(size_t) windows->image.ximage->height;
6625 cache_image->geometry=windows->image.crop_geometry;
6626 if (windows->image.crop_geometry != (char *) NULL)
6628 cache_image->geometry=AcquireString((char *) NULL);
6629 (void) CopyMagickString(cache_image->geometry,
6630 windows->image.crop_geometry,MaxTextExtent);
6632 if (undo_image == (Image *) NULL)
6634 undo_image=cache_image;
6637 undo_image->next=cache_image;
6638 undo_image->next->previous=undo_image;
6639 undo_image=undo_image->next;
6645 if (command == RedoCommand)
6648 Redo the last image transformation.
6650 if (redo_image == (Image *) NULL)
6652 (void) XBell(display,0);
6655 windows->image.window_changes.width=(int) redo_image->columns;
6656 windows->image.window_changes.height=(int) redo_image->rows;
6657 if (windows->image.crop_geometry != (char *) NULL)
6658 windows->image.crop_geometry=(char *)
6659 RelinquishMagickMemory(windows->image.crop_geometry);
6660 windows->image.crop_geometry=redo_image->geometry;
6661 *image=DestroyImage(*image);
6663 redo_image=NewImageList();
6664 if (IfMagickTrue(windows->image.orphan) )
6666 XConfigureImageColormap(display,resource_info,windows,*image,exception);
6667 (void) XConfigureImage(display,resource_info,windows,*image,exception);
6670 if (command != InfoCommand)
6675 XSetCursorState(display,windows,MagickTrue);
6676 XCheckRefreshWindows(display,windows);
6677 XDisplayImageInfo(display,resource_info,windows,undo_image,*image,exception);
6678 XSetCursorState(display,windows,MagickFalse);
6682 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6686 + X I m a g e W i n d o w C o m m a n d %
6690 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6692 % XImageWindowCommand() makes a transform to the image or Image window as
6693 % specified by a user menu button or keyboard command.
6695 % The format of the XImageWindowCommand method is:
6697 % CommandType XImageWindowCommand(Display *display,
6698 % XResourceInfo *resource_info,XWindows *windows,
6699 % const MagickStatusType state,KeySym key_symbol,Image **image,
6700 % ExceptionInfo *exception)
6702 % A description of each parameter follows:
6704 % o nexus: Method XImageWindowCommand returns an image when the
6705 % user chooses 'Open Image' from the command menu. Otherwise a null
6706 % image is returned.
6708 % o display: Specifies a connection to an X server; returned from
6711 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
6713 % o windows: Specifies a pointer to a XWindows structure.
6715 % o state: key mask.
6717 % o key_symbol: Specifies a command to perform.
6719 % o image: the image; XImageWIndowCommand may transform the image and
6720 % return a new image pointer.
6722 % o exception: return any errors or warnings in this structure.
6725 static CommandType XImageWindowCommand(Display *display,
6726 XResourceInfo *resource_info,XWindows *windows,const MagickStatusType state,
6727 KeySym key_symbol,Image **image,ExceptionInfo *exception)
6730 delta[MaxTextExtent] = "";
6733 Digits[] = "01234567890";
6738 if ((key_symbol >= XK_0) && (key_symbol <= XK_9))
6740 if (((last_symbol < XK_0) || (last_symbol > XK_9)))
6743 resource_info->quantum=1;
6745 last_symbol=key_symbol;
6746 delta[strlen(delta)+1]='\0';
6747 delta[strlen(delta)]=Digits[key_symbol-XK_0];
6748 resource_info->quantum=StringToLong(delta);
6749 return(NullCommand);
6751 last_symbol=key_symbol;
6752 if (resource_info->immutable)
6755 Virtual image window has a restricted command set.
6760 return(InfoCommand);
6763 return(PrintCommand);
6765 return(NextCommand);
6768 return(QuitCommand);
6772 return(NullCommand);
6774 switch ((int) key_symbol)
6778 if ((state & ControlMask) == 0)
6780 return(OpenCommand);
6783 return(NextCommand);
6785 return(FormerCommand);
6788 if ((state & Mod1Mask) != 0)
6789 return(SwirlCommand);
6790 if ((state & ControlMask) == 0)
6791 return(ShearCommand);
6792 return(SaveCommand);
6797 if ((state & Mod1Mask) != 0)
6798 return(OilPaintCommand);
6799 if ((state & Mod4Mask) != 0)
6800 return(ColorCommand);
6801 if ((state & ControlMask) == 0)
6802 return(NullCommand);
6803 return(PrintCommand);
6807 if ((state & Mod4Mask) != 0)
6808 return(DrawCommand);
6809 if ((state & ControlMask) == 0)
6810 return(NullCommand);
6811 return(DeleteCommand);
6815 if ((state & ControlMask) == 0)
6816 return(NullCommand);
6817 return(SelectCommand);
6821 if ((state & ControlMask) == 0)
6822 return(NullCommand);
6827 return(QuitCommand);
6831 if ((state & ControlMask) == 0)
6832 return(NullCommand);
6833 return(UndoCommand);
6838 if ((state & ControlMask) == 0)
6839 return(RollCommand);
6840 return(RedoCommand);
6844 if ((state & ControlMask) == 0)
6845 return(NullCommand);
6850 if ((state & Mod1Mask) != 0)
6851 return(CharcoalDrawCommand);
6852 if ((state & ControlMask) == 0)
6853 return(CropCommand);
6854 return(CopyCommand);
6859 if ((state & Mod4Mask) != 0)
6860 return(CompositeCommand);
6861 if ((state & ControlMask) == 0)
6862 return(FlipCommand);
6863 return(PasteCommand);
6866 return(HalfSizeCommand);
6868 return(OriginalSizeCommand);
6870 return(DoubleSizeCommand);
6872 return(ResizeCommand);
6874 return(RefreshCommand);
6875 case XK_bracketleft:
6876 return(ChopCommand);
6878 return(FlopCommand);
6880 return(RotateRightCommand);
6882 return(RotateLeftCommand);
6884 return(RotateCommand);
6886 return(TrimCommand);
6890 return(SaturationCommand);
6892 return(BrightnessCommand);
6894 return(GammaCommand);
6896 return(SpiffCommand);
6898 return(DullCommand);
6900 return(NormalizeCommand);
6902 return(EqualizeCommand);
6904 return(NegateCommand);
6906 return(GrayscaleCommand);
6908 return(QuantizeCommand);
6910 return(DespeckleCommand);
6912 return(EmbossCommand);
6914 return(ReduceNoiseCommand);
6916 return(AddNoiseCommand);
6918 return(SharpenCommand);
6920 return(BlurCommand);
6922 return(ThresholdCommand);
6924 return(EdgeDetectCommand);
6926 return(SpreadCommand);
6928 return(ShadeCommand);
6930 return(RaiseCommand);
6932 return(SegmentCommand);
6935 if ((state & Mod1Mask) == 0)
6936 return(NullCommand);
6937 return(ImplodeCommand);
6941 if ((state & Mod1Mask) == 0)
6942 return(NullCommand);
6943 return(WaveCommand);
6947 if ((state & Mod4Mask) == 0)
6948 return(NullCommand);
6949 return(MatteCommand);
6953 if ((state & Mod4Mask) == 0)
6954 return(NullCommand);
6955 return(AddBorderCommand);
6959 if ((state & Mod4Mask) == 0)
6960 return(NullCommand);
6961 return(AddFrameCommand);
6965 if ((state & Mod4Mask) == 0)
6966 return(NullCommand);
6967 return(CommentCommand);
6971 if ((state & Mod1Mask) != 0)
6972 return(ApplyCommand);
6973 if ((state & Mod4Mask) != 0)
6974 return(AnnotateCommand);
6975 if ((state & ControlMask) == 0)
6976 return(NullCommand);
6977 return(RegionofInterestCommand);
6980 return(InfoCommand);
6982 return(ZoomCommand);
6985 if ((state & ShiftMask) == 0)
6986 return(NullCommand);
6987 return(ShowPreviewCommand);
6990 return(LaunchCommand);
6992 return(HelpCommand);
6994 return(BrowseDocumentationCommand);
6997 (void) XMapRaised(display,windows->command.id);
6998 return(NullCommand);
7005 XTranslateImage(display,windows,*image,key_symbol);
7006 return(NullCommand);
7017 if ((state & Mod1Mask) != 0)
7023 Trim one pixel from edge of image.
7027 crop_info.width=(size_t) windows->image.ximage->width;
7028 crop_info.height=(size_t) windows->image.ximage->height;
7029 if ((key_symbol == XK_Up) || (key_symbol == XK_KP_Up))
7031 if (resource_info->quantum >= (int) crop_info.height)
7032 resource_info->quantum=(int) crop_info.height-1;
7033 crop_info.height-=resource_info->quantum;
7035 if ((key_symbol == XK_Down) || (key_symbol == XK_KP_Down))
7037 if (resource_info->quantum >= (int) (crop_info.height-crop_info.y))
7038 resource_info->quantum=(int) (crop_info.height-crop_info.y-1);
7039 crop_info.y+=resource_info->quantum;
7040 crop_info.height-=resource_info->quantum;
7042 if ((key_symbol == XK_Left) || (key_symbol == XK_KP_Left))
7044 if (resource_info->quantum >= (int) crop_info.width)
7045 resource_info->quantum=(int) crop_info.width-1;
7046 crop_info.width-=resource_info->quantum;
7048 if ((key_symbol == XK_Right) || (key_symbol == XK_KP_Right))
7050 if (resource_info->quantum >= (int) (crop_info.width-crop_info.x))
7051 resource_info->quantum=(int) (crop_info.width-crop_info.x-1);
7052 crop_info.x+=resource_info->quantum;
7053 crop_info.width-=resource_info->quantum;
7055 if ((int) (windows->image.x+windows->image.width) >
7056 (int) crop_info.width)
7057 windows->image.x=(int) (crop_info.width-windows->image.width);
7058 if ((int) (windows->image.y+windows->image.height) >
7059 (int) crop_info.height)
7060 windows->image.y=(int) (crop_info.height-windows->image.height);
7061 XSetCropGeometry(display,windows,&crop_info,*image);
7062 windows->image.window_changes.width=(int) crop_info.width;
7063 windows->image.window_changes.height=(int) crop_info.height;
7064 (void) XSetWindowBackgroundPixmap(display,windows->image.id,None);
7065 (void) XConfigureImage(display,resource_info,windows,*image,
7067 return(NullCommand);
7069 XTranslateImage(display,windows,*image,key_symbol);
7070 return(NullCommand);
7073 return(NullCommand);
7075 return(NullCommand);
7079 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7083 + X M a g i c k C o m m a n d %
7087 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7089 % XMagickCommand() makes a transform to the image or Image window as
7090 % specified by a user menu button or keyboard command.
7092 % The format of the XMagickCommand method is:
7094 % Image *XMagickCommand(Display *display,XResourceInfo *resource_info,
7095 % XWindows *windows,const CommandType command,Image **image,
7096 % ExceptionInfo *exception)
7098 % A description of each parameter follows:
7100 % o display: Specifies a connection to an X server; returned from
7103 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
7105 % o windows: Specifies a pointer to a XWindows structure.
7107 % o command: Specifies a command to perform.
7109 % o image: the image; XMagickCommand may transform the image and return a
7110 % new image pointer.
7112 % o exception: return any errors or warnings in this structure.
7115 static Image *XMagickCommand(Display *display,XResourceInfo *resource_info,
7116 XWindows *windows,const CommandType command,Image **image,
7117 ExceptionInfo *exception)
7120 filename[MaxTextExtent],
7121 geometry[MaxTextExtent],
7122 modulate_factors[MaxTextExtent];
7151 color[MaxTextExtent] = "gray";
7158 Process user command.
7160 XCheckRefreshWindows(display,windows);
7161 XImageCache(display,resource_info,windows,command,image,exception);
7162 nexus=NewImageList();
7163 windows->image.window_changes.width=windows->image.ximage->width;
7164 windows->image.window_changes.height=windows->image.ximage->height;
7165 image_info=CloneImageInfo(resource_info->image_info);
7166 SetGeometryInfo(&geometry_info);
7167 GetQuantizeInfo(&quantize_info);
7175 nexus=XOpenImage(display,resource_info,windows,MagickFalse);
7183 for (i=0; i < resource_info->quantum; i++)
7184 XClientMessage(display,windows->image.id,windows->im_protocols,
7185 windows->im_next_image,CurrentTime);
7191 Display former image.
7193 for (i=0; i < resource_info->quantum; i++)
7194 XClientMessage(display,windows->image.id,windows->im_protocols,
7195 windows->im_former_image,CurrentTime);
7206 if (*resource_info->home_directory == '\0')
7207 (void) CopyMagickString(resource_info->home_directory,".",
7209 status=chdir(resource_info->home_directory);
7211 (void) ThrowMagickException(exception,GetMagickModule(),FileOpenError,
7212 "UnableToOpenFile","%s",resource_info->home_directory);
7213 nexus=XOpenImage(display,resource_info,windows,MagickTrue);
7221 status=XSaveImage(display,resource_info,windows,*image,exception);
7222 if (IfMagickFalse(status) )
7225 message[MaxTextExtent];
7227 (void) FormatLocaleString(message,MaxTextExtent,"%s:%s",
7228 exception->reason != (char *) NULL ? exception->reason : "",
7229 exception->description != (char *) NULL ? exception->description :
7231 XNoticeWidget(display,windows,"Unable to save file:",message);
7241 status=XPrintImage(display,resource_info,windows,*image,exception);
7242 if (IfMagickFalse(status) )
7245 message[MaxTextExtent];
7247 (void) FormatLocaleString(message,MaxTextExtent,"%s:%s",
7248 exception->reason != (char *) NULL ? exception->reason : "",
7249 exception->description != (char *) NULL ? exception->description :
7251 XNoticeWidget(display,windows,"Unable to print file:",message);
7259 filename[MaxTextExtent] = "\0";
7264 XFileBrowserWidget(display,windows,"Delete",filename);
7265 if (*filename == '\0')
7267 status=ShredFile(filename);
7268 if (IfMagickTrue(status) )
7269 XNoticeWidget(display,windows,"Unable to delete image file:",filename);
7278 color[MaxTextExtent] = "gray",
7279 geometry[MaxTextExtent] = "640x480";
7282 *format = "gradient";
7285 Query user for canvas geometry.
7287 status=XDialogWidget(display,windows,"New","Enter image geometry:",
7289 if (*geometry == '\0')
7293 XColorBrowserWidget(display,windows,"Select",color);
7299 (void) FormatLocaleString(image_info->filename,MaxTextExtent,
7300 "%s:%s",format,color);
7301 (void) CloneString(&image_info->size,geometry);
7302 nexus=ReadImage(image_info,exception);
7303 CatchException(exception);
7304 XClientMessage(display,windows->image.id,windows->im_protocols,
7305 windows->im_next_image,CurrentTime);
7308 case VisualDirectoryCommand:
7311 Visual Image directory.
7313 nexus=XVisualDirectoryImage(display,resource_info,windows,exception);
7321 if (IfMagickFalse(resource_info->confirm_exit) )
7322 XClientMessage(display,windows->image.id,windows->im_protocols,
7323 windows->im_exit,CurrentTime);
7330 Confirm program exit.
7332 status=XConfirmWidget(display,windows,"Do you really want to exit",
7333 resource_info->client_name);
7335 XClientMessage(display,windows->image.id,windows->im_protocols,
7336 windows->im_exit,CurrentTime);
7345 (void) XCropImage(display,resource_info,windows,*image,CutMode,exception);
7353 (void) XCropImage(display,resource_info,windows,*image,CopyMode,
7362 status=XPasteImage(display,resource_info,windows,*image,exception);
7363 if (IfMagickFalse(status) )
7365 XNoticeWidget(display,windows,"Unable to paste X image",
7366 (*image)->filename);
7371 case HalfSizeCommand:
7376 windows->image.window_changes.width=windows->image.ximage->width/2;
7377 windows->image.window_changes.height=windows->image.ximage->height/2;
7378 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7381 case OriginalSizeCommand:
7384 Original image size.
7386 windows->image.window_changes.width=(int) (*image)->columns;
7387 windows->image.window_changes.height=(int) (*image)->rows;
7388 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7391 case DoubleSizeCommand:
7394 Double the image size.
7396 windows->image.window_changes.width=windows->image.ximage->width << 1;
7397 windows->image.window_changes.height=windows->image.ximage->height << 1;
7398 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7417 width=(size_t) windows->image.ximage->width;
7418 height=(size_t) windows->image.ximage->height;
7421 (void) FormatLocaleString(geometry,MaxTextExtent,"%.20gx%.20g+0+0",
7422 (double) width,(double) height);
7423 status=XDialogWidget(display,windows,"Resize",
7424 "Enter resize geometry (e.g. 640x480, 200%):",geometry);
7425 if (*geometry == '\0')
7428 (void) ConcatenateMagickString(geometry,"!",MaxTextExtent);
7429 (void) ParseMetaGeometry(geometry,&x,&y,&width,&height);
7430 windows->image.window_changes.width=(int) width;
7431 windows->image.window_changes.height=(int) height;
7432 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7438 image_geometry[MaxTextExtent];
7440 if ((windows->image.crop_geometry == (char *) NULL) &&
7441 ((int) (*image)->columns == windows->image.ximage->width) &&
7442 ((int) (*image)->rows == windows->image.ximage->height))
7445 Apply size transforms to image.
7447 XSetCursorState(display,windows,MagickTrue);
7448 XCheckRefreshWindows(display,windows);
7450 Crop and/or scale displayed image.
7452 (void) FormatLocaleString(image_geometry,MaxTextExtent,"%dx%d!",
7453 windows->image.ximage->width,windows->image.ximage->height);
7454 (void) TransformImage(image,windows->image.crop_geometry,image_geometry,
7456 if (windows->image.crop_geometry != (char *) NULL)
7457 windows->image.crop_geometry=(char *) RelinquishMagickMemory(
7458 windows->image.crop_geometry);
7461 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7462 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7465 case RefreshCommand:
7467 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7470 case RestoreCommand:
7473 Restore Image window to its original size.
7475 if ((windows->image.width == (unsigned int) (*image)->columns) &&
7476 (windows->image.height == (unsigned int) (*image)->rows) &&
7477 (windows->image.crop_geometry == (char *) NULL))
7479 (void) XBell(display,0);
7482 windows->image.window_changes.width=(int) (*image)->columns;
7483 windows->image.window_changes.height=(int) (*image)->rows;
7484 if (windows->image.crop_geometry != (char *) NULL)
7486 windows->image.crop_geometry=(char *)
7487 RelinquishMagickMemory(windows->image.crop_geometry);
7488 windows->image.crop_geometry=(char *) NULL;
7492 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7493 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7501 (void) XCropImage(display,resource_info,windows,*image,CropMode,
7510 status=XChopImage(display,resource_info,windows,image,exception);
7511 if (IfMagickFalse(status) )
7513 XNoticeWidget(display,windows,"Unable to cut X image",
7514 (*image)->filename);
7525 Flop image scanlines.
7527 XSetCursorState(display,windows,MagickTrue);
7528 XCheckRefreshWindows(display,windows);
7529 flop_image=FlopImage(*image,exception);
7530 if (flop_image != (Image *) NULL)
7532 *image=DestroyImage(*image);
7535 CatchException(exception);
7536 XSetCursorState(display,windows,MagickFalse);
7537 if (windows->image.crop_geometry != (char *) NULL)
7542 width=(unsigned int) (*image)->columns;
7543 height=(unsigned int) (*image)->rows;
7544 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,
7546 (void) FormatLocaleString(windows->image.crop_geometry,MaxTextExtent,
7547 "%ux%u%+d%+d",width,height,(int) (*image)->columns-(int) width-x,y);
7549 if (IfMagickTrue(windows->image.orphan) )
7551 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7560 Flip image scanlines.
7562 XSetCursorState(display,windows,MagickTrue);
7563 XCheckRefreshWindows(display,windows);
7564 flip_image=FlipImage(*image,exception);
7565 if (flip_image != (Image *) NULL)
7567 *image=DestroyImage(*image);
7570 CatchException(exception);
7571 XSetCursorState(display,windows,MagickFalse);
7572 if (windows->image.crop_geometry != (char *) NULL)
7577 width=(unsigned int) (*image)->columns;
7578 height=(unsigned int) (*image)->rows;
7579 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,
7581 (void) FormatLocaleString(windows->image.crop_geometry,MaxTextExtent,
7582 "%ux%u%+d%+d",width,height,x,(int) (*image)->rows-(int) height-y);
7584 if (IfMagickTrue(windows->image.orphan) )
7586 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7589 case RotateRightCommand:
7592 Rotate image 90 degrees clockwise.
7594 status=XRotateImage(display,resource_info,windows,90.0,image,exception);
7595 if (IfMagickFalse(status) )
7597 XNoticeWidget(display,windows,"Unable to rotate X image",
7598 (*image)->filename);
7603 case RotateLeftCommand:
7606 Rotate image 90 degrees counter-clockwise.
7608 status=XRotateImage(display,resource_info,windows,-90.0,image,exception);
7609 if (IfMagickFalse(status) )
7611 XNoticeWidget(display,windows,"Unable to rotate X image",
7612 (*image)->filename);
7622 status=XRotateImage(display,resource_info,windows,0.0,image,exception);
7623 if (IfMagickFalse(status) )
7625 XNoticeWidget(display,windows,"Unable to rotate X image",
7626 (*image)->filename);
7637 geometry[MaxTextExtent] = "45.0x45.0";
7640 Query user for shear color and geometry.
7642 XColorBrowserWidget(display,windows,"Select",color);
7645 (void) XDialogWidget(display,windows,"Shear","Enter shear geometry:",
7647 if (*geometry == '\0')
7652 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image,
7654 XSetCursorState(display,windows,MagickTrue);
7655 XCheckRefreshWindows(display,windows);
7656 (void) QueryColorCompliance(color,AllCompliance,
7657 &(*image)->background_color,exception);
7658 flags=ParseGeometry(geometry,&geometry_info);
7659 if ((flags & SigmaValue) == 0)
7660 geometry_info.sigma=geometry_info.rho;
7661 shear_image=ShearImage(*image,geometry_info.rho,geometry_info.sigma,
7663 if (shear_image != (Image *) NULL)
7665 *image=DestroyImage(*image);
7668 CatchException(exception);
7669 XSetCursorState(display,windows,MagickFalse);
7670 if (IfMagickTrue(windows->image.orphan) )
7672 windows->image.window_changes.width=(int) (*image)->columns;
7673 windows->image.window_changes.height=(int) (*image)->rows;
7674 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7675 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7684 geometry[MaxTextExtent] = "+2+2";
7687 Query user for the roll geometry.
7689 (void) XDialogWidget(display,windows,"Roll","Enter roll geometry:",
7691 if (*geometry == '\0')
7696 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image,
7698 XSetCursorState(display,windows,MagickTrue);
7699 XCheckRefreshWindows(display,windows);
7700 (void) ParsePageGeometry(*image,geometry,&page_geometry,
7702 roll_image=RollImage(*image,page_geometry.x,page_geometry.y,
7704 if (roll_image != (Image *) NULL)
7706 *image=DestroyImage(*image);
7709 CatchException(exception);
7710 XSetCursorState(display,windows,MagickFalse);
7711 if (IfMagickTrue(windows->image.orphan) )
7713 windows->image.window_changes.width=(int) (*image)->columns;
7714 windows->image.window_changes.height=(int) (*image)->rows;
7715 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7716 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7722 fuzz[MaxTextExtent];
7725 Query user for the fuzz factor.
7727 (void) FormatLocaleString(fuzz,MaxTextExtent,"%g%%",100.0*
7728 (*image)->fuzz/(QuantumRange+1.0));
7729 (void) XDialogWidget(display,windows,"Trim","Enter fuzz factor:",fuzz);
7732 (*image)->fuzz=StringToDoubleInterval(fuzz,(double) QuantumRange+1.0);
7736 status=XTrimImage(display,resource_info,windows,*image,exception);
7737 if (IfMagickFalse(status) )
7739 XNoticeWidget(display,windows,"Unable to trim X image",
7740 (*image)->filename);
7748 hue_percent[MaxTextExtent] = "110";
7751 Query user for percent hue change.
7753 (void) XDialogWidget(display,windows,"Apply",
7754 "Enter percent change in image hue (0-200):",hue_percent);
7755 if (*hue_percent == '\0')
7760 XSetCursorState(display,windows,MagickTrue);
7761 XCheckRefreshWindows(display,windows);
7762 (void) CopyMagickString(modulate_factors,"100.0/100.0/",MaxTextExtent);
7763 (void) ConcatenateMagickString(modulate_factors,hue_percent,
7765 (void) ModulateImage(*image,modulate_factors,exception);
7766 XSetCursorState(display,windows,MagickFalse);
7767 if (IfMagickTrue(windows->image.orphan) )
7769 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7770 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7773 case SaturationCommand:
7776 saturation_percent[MaxTextExtent] = "110";
7779 Query user for percent saturation change.
7781 (void) XDialogWidget(display,windows,"Apply",
7782 "Enter percent change in color saturation (0-200):",saturation_percent);
7783 if (*saturation_percent == '\0')
7786 Vary color saturation.
7788 XSetCursorState(display,windows,MagickTrue);
7789 XCheckRefreshWindows(display,windows);
7790 (void) CopyMagickString(modulate_factors,"100.0/",MaxTextExtent);
7791 (void) ConcatenateMagickString(modulate_factors,saturation_percent,
7793 (void) ModulateImage(*image,modulate_factors,exception);
7794 XSetCursorState(display,windows,MagickFalse);
7795 if (IfMagickTrue(windows->image.orphan) )
7797 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7798 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7801 case BrightnessCommand:
7804 brightness_percent[MaxTextExtent] = "110";
7807 Query user for percent brightness change.
7809 (void) XDialogWidget(display,windows,"Apply",
7810 "Enter percent change in color brightness (0-200):",brightness_percent);
7811 if (*brightness_percent == '\0')
7814 Vary the color brightness.
7816 XSetCursorState(display,windows,MagickTrue);
7817 XCheckRefreshWindows(display,windows);
7818 (void) CopyMagickString(modulate_factors,brightness_percent,
7820 (void) ModulateImage(*image,modulate_factors,exception);
7821 XSetCursorState(display,windows,MagickFalse);
7822 if (IfMagickTrue(windows->image.orphan) )
7824 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7825 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7831 factor[MaxTextExtent] = "1.6";
7834 Query user for gamma value.
7836 (void) XDialogWidget(display,windows,"Gamma",
7837 "Enter gamma value (e.g. 1.2):",factor);
7838 if (*factor == '\0')
7841 Gamma correct image.
7843 XSetCursorState(display,windows,MagickTrue);
7844 XCheckRefreshWindows(display,windows);
7845 (void) GammaImage(*image,atof(factor),exception);
7846 XSetCursorState(display,windows,MagickFalse);
7847 if (IfMagickTrue(windows->image.orphan) )
7849 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7850 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7856 Sharpen the image contrast.
7858 XSetCursorState(display,windows,MagickTrue);
7859 XCheckRefreshWindows(display,windows);
7860 (void) ContrastImage(*image,MagickTrue,exception);
7861 XSetCursorState(display,windows,MagickFalse);
7862 if (IfMagickTrue(windows->image.orphan) )
7864 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7865 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7871 Dull the image contrast.
7873 XSetCursorState(display,windows,MagickTrue);
7874 XCheckRefreshWindows(display,windows);
7875 (void) ContrastImage(*image,MagickFalse,exception);
7876 XSetCursorState(display,windows,MagickFalse);
7877 if (IfMagickTrue(windows->image.orphan) )
7879 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7880 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7883 case ContrastStretchCommand:
7890 levels[MaxTextExtent] = "1%";
7893 Query user for gamma value.
7895 (void) XDialogWidget(display,windows,"Contrast Stretch",
7896 "Enter black and white points:",levels);
7897 if (*levels == '\0')
7900 Contrast stretch image.
7902 XSetCursorState(display,windows,MagickTrue);
7903 XCheckRefreshWindows(display,windows);
7904 flags=ParseGeometry(levels,&geometry_info);
7905 black_point=geometry_info.rho;
7906 white_point=(flags & SigmaValue) != 0 ? geometry_info.sigma : black_point;
7907 if ((flags & PercentValue) != 0)
7909 black_point*=(double) (*image)->columns*(*image)->rows/100.0;
7910 white_point*=(double) (*image)->columns*(*image)->rows/100.0;
7912 white_point=(double) (*image)->columns*(*image)->rows-white_point;
7913 (void) ContrastStretchImage(*image,black_point,white_point,
7915 XSetCursorState(display,windows,MagickFalse);
7916 if (IfMagickTrue(windows->image.orphan) )
7918 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7919 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7922 case SigmoidalContrastCommand:
7931 levels[MaxTextExtent] = "3x50%";
7934 Query user for gamma value.
7936 (void) XDialogWidget(display,windows,"Sigmoidal Contrast",
7937 "Enter contrast and midpoint:",levels);
7938 if (*levels == '\0')
7941 Contrast stretch image.
7943 XSetCursorState(display,windows,MagickTrue);
7944 XCheckRefreshWindows(display,windows);
7945 flags=ParseGeometry(levels,&geometry_info);
7946 if ((flags & SigmaValue) == 0)
7947 geometry_info.sigma=1.0*QuantumRange/2.0;
7948 if ((flags & PercentValue) != 0)
7949 geometry_info.sigma=1.0*QuantumRange*geometry_info.sigma/100.0;
7950 (void) SigmoidalContrastImage(*image,MagickTrue,geometry_info.rho,
7951 geometry_info.sigma,exception);
7952 XSetCursorState(display,windows,MagickFalse);
7953 if (IfMagickTrue(windows->image.orphan) )
7955 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7956 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7959 case NormalizeCommand:
7962 Perform histogram normalization on the image.
7964 XSetCursorState(display,windows,MagickTrue);
7965 XCheckRefreshWindows(display,windows);
7966 (void) NormalizeImage(*image,exception);
7967 XSetCursorState(display,windows,MagickFalse);
7968 if (IfMagickTrue(windows->image.orphan) )
7970 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7971 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7974 case EqualizeCommand:
7977 Perform histogram equalization on the image.
7979 XSetCursorState(display,windows,MagickTrue);
7980 XCheckRefreshWindows(display,windows);
7981 (void) EqualizeImage(*image,exception);
7982 XSetCursorState(display,windows,MagickFalse);
7983 if (IfMagickTrue(windows->image.orphan) )
7985 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7986 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7992 Negate colors in image.
7994 XSetCursorState(display,windows,MagickTrue);
7995 XCheckRefreshWindows(display,windows);
7996 (void) NegateImage(*image,MagickFalse,exception);
7997 XSetCursorState(display,windows,MagickFalse);
7998 if (IfMagickTrue(windows->image.orphan) )
8000 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8001 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8004 case GrayscaleCommand:
8007 Convert image to grayscale.
8009 XSetCursorState(display,windows,MagickTrue);
8010 XCheckRefreshWindows(display,windows);
8011 (void) SetImageType(*image,(*image)->alpha_trait != BlendPixelTrait ?
8012 GrayscaleType : GrayscaleMatteType,exception);
8013 XSetCursorState(display,windows,MagickFalse);
8014 if (IfMagickTrue(windows->image.orphan) )
8016 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8017 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8026 filename[MaxTextExtent] = "\0";
8029 Request image file name from user.
8031 XFileBrowserWidget(display,windows,"Map",filename);
8032 if (*filename == '\0')
8037 XSetCursorState(display,windows,MagickTrue);
8038 XCheckRefreshWindows(display,windows);
8039 (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
8040 affinity_image=ReadImage(image_info,exception);
8041 if (affinity_image != (Image *) NULL)
8043 (void) RemapImage(&quantize_info,*image,affinity_image,exception);
8044 affinity_image=DestroyImage(affinity_image);
8046 CatchException(exception);
8047 XSetCursorState(display,windows,MagickFalse);
8048 if (IfMagickTrue(windows->image.orphan) )
8050 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8051 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8054 case QuantizeCommand:
8060 colors[MaxTextExtent] = "256";
8063 Query user for maximum number of colors.
8065 status=XDialogWidget(display,windows,"Quantize",
8066 "Maximum number of colors:",colors);
8067 if (*colors == '\0')
8070 Color reduce the image.
8072 XSetCursorState(display,windows,MagickTrue);
8073 XCheckRefreshWindows(display,windows);
8074 quantize_info.number_colors=StringToUnsignedLong(colors);
8075 quantize_info.dither_method=status != 0 ? RiemersmaDitherMethod :
8077 (void) QuantizeImage(&quantize_info,*image,exception);
8078 XSetCursorState(display,windows,MagickFalse);
8079 if (IfMagickTrue(windows->image.orphan) )
8081 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8082 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8085 case DespeckleCommand:
8093 XSetCursorState(display,windows,MagickTrue);
8094 XCheckRefreshWindows(display,windows);
8095 despeckle_image=DespeckleImage(*image,exception);
8096 if (despeckle_image != (Image *) NULL)
8098 *image=DestroyImage(*image);
8099 *image=despeckle_image;
8101 CatchException(exception);
8102 XSetCursorState(display,windows,MagickFalse);
8103 if (IfMagickTrue(windows->image.orphan) )
8105 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8106 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8115 radius[MaxTextExtent] = "0.0x1.0";
8118 Query user for emboss radius.
8120 (void) XDialogWidget(display,windows,"Emboss",
8121 "Enter the emboss radius and standard deviation:",radius);
8122 if (*radius == '\0')
8125 Reduce noise in the image.
8127 XSetCursorState(display,windows,MagickTrue);
8128 XCheckRefreshWindows(display,windows);
8129 flags=ParseGeometry(radius,&geometry_info);
8130 if ((flags & SigmaValue) == 0)
8131 geometry_info.sigma=1.0;
8132 emboss_image=EmbossImage(*image,geometry_info.rho,geometry_info.sigma,
8134 if (emboss_image != (Image *) NULL)
8136 *image=DestroyImage(*image);
8137 *image=emboss_image;
8139 CatchException(exception);
8140 XSetCursorState(display,windows,MagickFalse);
8141 if (IfMagickTrue(windows->image.orphan) )
8143 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8144 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8147 case ReduceNoiseCommand:
8153 radius[MaxTextExtent] = "0";
8156 Query user for noise radius.
8158 (void) XDialogWidget(display,windows,"Reduce Noise",
8159 "Enter the noise radius:",radius);
8160 if (*radius == '\0')
8163 Reduce noise in the image.
8165 XSetCursorState(display,windows,MagickTrue);
8166 XCheckRefreshWindows(display,windows);
8167 flags=ParseGeometry(radius,&geometry_info);
8168 noise_image=StatisticImage(*image,NonpeakStatistic,(size_t)
8169 geometry_info.rho,(size_t) geometry_info.rho,exception);
8170 if (noise_image != (Image *) NULL)
8172 *image=DestroyImage(*image);
8175 CatchException(exception);
8176 XSetCursorState(display,windows,MagickFalse);
8177 if (IfMagickTrue(windows->image.orphan) )
8179 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8180 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8183 case AddNoiseCommand:
8192 noise_type[MaxTextExtent] = "Gaussian";
8195 Add noise to the image.
8197 noises=GetCommandOptions(MagickNoiseOptions);
8198 if (noises == (char **) NULL)
8200 XListBrowserWidget(display,windows,&windows->widget,
8201 (const char **) noises,"Add Noise",
8202 "Select a type of noise to add to your image:",noise_type);
8203 noises=DestroyStringList(noises);
8204 if (*noise_type == '\0')
8206 XSetCursorState(display,windows,MagickTrue);
8207 XCheckRefreshWindows(display,windows);
8208 noise_image=AddNoiseImage(*image,(NoiseType) ParseCommandOption(
8209 MagickNoiseOptions,MagickFalse,noise_type),1.0,exception);
8210 if (noise_image != (Image *) NULL)
8212 *image=DestroyImage(*image);
8215 CatchException(exception);
8216 XSetCursorState(display,windows,MagickFalse);
8217 if (IfMagickTrue(windows->image.orphan) )
8219 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8220 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8223 case SharpenCommand:
8229 radius[MaxTextExtent] = "0.0x1.0";
8232 Query user for sharpen radius.
8234 (void) XDialogWidget(display,windows,"Sharpen",
8235 "Enter the sharpen radius and standard deviation:",radius);
8236 if (*radius == '\0')
8239 Sharpen image scanlines.
8241 XSetCursorState(display,windows,MagickTrue);
8242 XCheckRefreshWindows(display,windows);
8243 flags=ParseGeometry(radius,&geometry_info);
8244 sharp_image=SharpenImage(*image,geometry_info.rho,geometry_info.sigma,
8246 if (sharp_image != (Image *) NULL)
8248 *image=DestroyImage(*image);
8251 CatchException(exception);
8252 XSetCursorState(display,windows,MagickFalse);
8253 if (IfMagickTrue(windows->image.orphan) )
8255 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8256 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8265 radius[MaxTextExtent] = "0.0x1.0";
8268 Query user for blur radius.
8270 (void) XDialogWidget(display,windows,"Blur",
8271 "Enter the blur radius and standard deviation:",radius);
8272 if (*radius == '\0')
8277 XSetCursorState(display,windows,MagickTrue);
8278 XCheckRefreshWindows(display,windows);
8279 flags=ParseGeometry(radius,&geometry_info);
8280 blur_image=BlurImage(*image,geometry_info.rho,geometry_info.sigma,
8282 if (blur_image != (Image *) NULL)
8284 *image=DestroyImage(*image);
8287 CatchException(exception);
8288 XSetCursorState(display,windows,MagickFalse);
8289 if (IfMagickTrue(windows->image.orphan) )
8291 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8292 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8295 case ThresholdCommand:
8301 factor[MaxTextExtent] = "128";
8304 Query user for threshold value.
8306 (void) XDialogWidget(display,windows,"Threshold",
8307 "Enter threshold value:",factor);
8308 if (*factor == '\0')
8311 Gamma correct image.
8313 XSetCursorState(display,windows,MagickTrue);
8314 XCheckRefreshWindows(display,windows);
8315 threshold=StringToDoubleInterval(factor,(double) QuantumRange+1.0);
8316 (void) BilevelImage(*image,threshold,exception);
8317 XSetCursorState(display,windows,MagickFalse);
8318 if (IfMagickTrue(windows->image.orphan) )
8320 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8321 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8324 case EdgeDetectCommand:
8330 radius[MaxTextExtent] = "0";
8333 Query user for edge factor.
8335 (void) XDialogWidget(display,windows,"Detect Edges",
8336 "Enter the edge detect radius:",radius);
8337 if (*radius == '\0')
8340 Detect edge in image.
8342 XSetCursorState(display,windows,MagickTrue);
8343 XCheckRefreshWindows(display,windows);
8344 flags=ParseGeometry(radius,&geometry_info);
8345 edge_image=EdgeImage(*image,geometry_info.rho,exception);
8346 if (edge_image != (Image *) NULL)
8348 *image=DestroyImage(*image);
8351 CatchException(exception);
8352 XSetCursorState(display,windows,MagickFalse);
8353 if (IfMagickTrue(windows->image.orphan) )
8355 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8356 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8365 amount[MaxTextExtent] = "2";
8368 Query user for spread amount.
8370 (void) XDialogWidget(display,windows,"Spread",
8371 "Enter the displacement amount:",amount);
8372 if (*amount == '\0')
8375 Displace image pixels by a random amount.
8377 XSetCursorState(display,windows,MagickTrue);
8378 XCheckRefreshWindows(display,windows);
8379 flags=ParseGeometry(amount,&geometry_info);
8380 spread_image=EdgeImage(*image,geometry_info.rho,exception);
8381 if (spread_image != (Image *) NULL)
8383 *image=DestroyImage(*image);
8384 *image=spread_image;
8386 CatchException(exception);
8387 XSetCursorState(display,windows,MagickFalse);
8388 if (IfMagickTrue(windows->image.orphan) )
8390 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8391 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8403 geometry[MaxTextExtent] = "30x30";
8406 Query user for the shade geometry.
8408 status=XDialogWidget(display,windows,"Shade",
8409 "Enter the azimuth and elevation of the light source:",geometry);
8410 if (*geometry == '\0')
8415 XSetCursorState(display,windows,MagickTrue);
8416 XCheckRefreshWindows(display,windows);
8417 flags=ParseGeometry(geometry,&geometry_info);
8418 if ((flags & SigmaValue) == 0)
8419 geometry_info.sigma=1.0;
8420 shade_image=ShadeImage(*image,IsMagickTrue(status),
8421 geometry_info.rho,geometry_info.sigma,exception);
8422 if (shade_image != (Image *) NULL)
8424 *image=DestroyImage(*image);
8427 CatchException(exception);
8428 XSetCursorState(display,windows,MagickFalse);
8429 if (IfMagickTrue(windows->image.orphan) )
8431 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8432 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8438 bevel_width[MaxTextExtent] = "10";
8441 Query user for bevel width.
8443 (void) XDialogWidget(display,windows,"Raise","Bevel width:",bevel_width);
8444 if (*bevel_width == '\0')
8449 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image,
8451 XSetCursorState(display,windows,MagickTrue);
8452 XCheckRefreshWindows(display,windows);
8453 (void) ParsePageGeometry(*image,bevel_width,&page_geometry,
8455 (void) RaiseImage(*image,&page_geometry,MagickTrue,exception);
8456 XSetCursorState(display,windows,MagickFalse);
8457 if (IfMagickTrue(windows->image.orphan) )
8459 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8460 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8463 case SegmentCommand:
8466 threshold[MaxTextExtent] = "1.0x1.5";
8469 Query user for smoothing threshold.
8471 (void) XDialogWidget(display,windows,"Segment","Smooth threshold:",
8473 if (*threshold == '\0')
8478 XSetCursorState(display,windows,MagickTrue);
8479 XCheckRefreshWindows(display,windows);
8480 flags=ParseGeometry(threshold,&geometry_info);
8481 if ((flags & SigmaValue) == 0)
8482 geometry_info.sigma=1.0;
8483 (void) SegmentImage(*image,sRGBColorspace,MagickFalse,geometry_info.rho,
8484 geometry_info.sigma,exception);
8485 XSetCursorState(display,windows,MagickFalse);
8486 if (IfMagickTrue(windows->image.orphan) )
8488 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8489 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8492 case SepiaToneCommand:
8501 factor[MaxTextExtent] = "80%";
8504 Query user for sepia-tone factor.
8506 (void) XDialogWidget(display,windows,"Sepia Tone",
8507 "Enter the sepia tone factor (0 - 99.9%):",factor);
8508 if (*factor == '\0')
8511 Sepia tone image pixels.
8513 XSetCursorState(display,windows,MagickTrue);
8514 XCheckRefreshWindows(display,windows);
8515 threshold=StringToDoubleInterval(factor,(double) QuantumRange+1.0);
8516 sepia_image=SepiaToneImage(*image,threshold,exception);
8517 if (sepia_image != (Image *) NULL)
8519 *image=DestroyImage(*image);
8522 CatchException(exception);
8523 XSetCursorState(display,windows,MagickFalse);
8524 if (IfMagickTrue(windows->image.orphan) )
8526 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8527 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8530 case SolarizeCommand:
8536 factor[MaxTextExtent] = "60%";
8539 Query user for solarize factor.
8541 (void) XDialogWidget(display,windows,"Solarize",
8542 "Enter the solarize factor (0 - 99.9%):",factor);
8543 if (*factor == '\0')
8546 Solarize image pixels.
8548 XSetCursorState(display,windows,MagickTrue);
8549 XCheckRefreshWindows(display,windows);
8550 threshold=StringToDoubleInterval(factor,(double) QuantumRange+1.0);
8551 (void) SolarizeImage(*image,threshold,exception);
8552 XSetCursorState(display,windows,MagickFalse);
8553 if (IfMagickTrue(windows->image.orphan) )
8555 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8556 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8565 degrees[MaxTextExtent] = "60";
8568 Query user for swirl angle.
8570 (void) XDialogWidget(display,windows,"Swirl","Enter the swirl angle:",
8572 if (*degrees == '\0')
8575 Swirl image pixels about the center.
8577 XSetCursorState(display,windows,MagickTrue);
8578 XCheckRefreshWindows(display,windows);
8579 flags=ParseGeometry(degrees,&geometry_info);
8580 swirl_image=SwirlImage(*image,geometry_info.rho,(*image)->interpolate,
8582 if (swirl_image != (Image *) NULL)
8584 *image=DestroyImage(*image);
8587 CatchException(exception);
8588 XSetCursorState(display,windows,MagickFalse);
8589 if (IfMagickTrue(windows->image.orphan) )
8591 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8592 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8595 case ImplodeCommand:
8601 factor[MaxTextExtent] = "0.3";
8604 Query user for implode factor.
8606 (void) XDialogWidget(display,windows,"Implode",
8607 "Enter the implosion/explosion factor (-1.0 - 1.0):",factor);
8608 if (*factor == '\0')
8611 Implode image pixels about the center.
8613 XSetCursorState(display,windows,MagickTrue);
8614 XCheckRefreshWindows(display,windows);
8615 flags=ParseGeometry(factor,&geometry_info);
8616 implode_image=ImplodeImage(*image,geometry_info.rho,(*image)->interpolate,
8618 if (implode_image != (Image *) NULL)
8620 *image=DestroyImage(*image);
8621 *image=implode_image;
8623 CatchException(exception);
8624 XSetCursorState(display,windows,MagickFalse);
8625 if (IfMagickTrue(windows->image.orphan) )
8627 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8628 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8631 case VignetteCommand:
8637 geometry[MaxTextExtent] = "0x20";
8640 Query user for the vignette geometry.
8642 (void) XDialogWidget(display,windows,"Vignette",
8643 "Enter the radius, sigma, and x and y offsets:",geometry);
8644 if (*geometry == '\0')
8647 Soften the edges of the image in vignette style
8649 XSetCursorState(display,windows,MagickTrue);
8650 XCheckRefreshWindows(display,windows);
8651 flags=ParseGeometry(geometry,&geometry_info);
8652 if ((flags & SigmaValue) == 0)
8653 geometry_info.sigma=1.0;
8654 if ((flags & XiValue) == 0)
8655 geometry_info.xi=0.1*(*image)->columns;
8656 if ((flags & PsiValue) == 0)
8657 geometry_info.psi=0.1*(*image)->rows;
8658 vignette_image=VignetteImage(*image,geometry_info.rho,0.0,(ssize_t)
8659 ceil(geometry_info.xi-0.5),(ssize_t) ceil(geometry_info.psi-0.5),
8661 if (vignette_image != (Image *) NULL)
8663 *image=DestroyImage(*image);
8664 *image=vignette_image;
8666 CatchException(exception);
8667 XSetCursorState(display,windows,MagickFalse);
8668 if (IfMagickTrue(windows->image.orphan) )
8670 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8671 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8680 geometry[MaxTextExtent] = "25x150";
8683 Query user for the wave geometry.
8685 (void) XDialogWidget(display,windows,"Wave",
8686 "Enter the amplitude and length of the wave:",geometry);
8687 if (*geometry == '\0')
8690 Alter an image along a sine wave.
8692 XSetCursorState(display,windows,MagickTrue);
8693 XCheckRefreshWindows(display,windows);
8694 flags=ParseGeometry(geometry,&geometry_info);
8695 if ((flags & SigmaValue) == 0)
8696 geometry_info.sigma=1.0;
8697 wave_image=WaveImage(*image,geometry_info.rho,geometry_info.sigma,
8698 (*image)->interpolate,exception);
8699 if (wave_image != (Image *) NULL)
8701 *image=DestroyImage(*image);
8704 CatchException(exception);
8705 XSetCursorState(display,windows,MagickFalse);
8706 if (IfMagickTrue(windows->image.orphan) )
8708 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8709 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8712 case OilPaintCommand:
8718 radius[MaxTextExtent] = "0";
8721 Query user for circular neighborhood radius.
8723 (void) XDialogWidget(display,windows,"Oil Paint",
8724 "Enter the mask radius:",radius);
8725 if (*radius == '\0')
8728 OilPaint image scanlines.
8730 XSetCursorState(display,windows,MagickTrue);
8731 XCheckRefreshWindows(display,windows);
8732 flags=ParseGeometry(radius,&geometry_info);
8733 paint_image=OilPaintImage(*image,geometry_info.rho,geometry_info.sigma,
8735 if (paint_image != (Image *) NULL)
8737 *image=DestroyImage(*image);
8740 CatchException(exception);
8741 XSetCursorState(display,windows,MagickFalse);
8742 if (IfMagickTrue(windows->image.orphan) )
8744 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8745 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8748 case CharcoalDrawCommand:
8754 radius[MaxTextExtent] = "0x1";
8757 Query user for charcoal radius.
8759 (void) XDialogWidget(display,windows,"Charcoal Draw",
8760 "Enter the charcoal radius and sigma:",radius);
8761 if (*radius == '\0')
8766 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image,
8768 XSetCursorState(display,windows,MagickTrue);
8769 XCheckRefreshWindows(display,windows);
8770 flags=ParseGeometry(radius,&geometry_info);
8771 if ((flags & SigmaValue) == 0)
8772 geometry_info.sigma=geometry_info.rho;
8773 charcoal_image=CharcoalImage(*image,geometry_info.rho,geometry_info.sigma,
8775 if (charcoal_image != (Image *) NULL)
8777 *image=DestroyImage(*image);
8778 *image=charcoal_image;
8780 CatchException(exception);
8781 XSetCursorState(display,windows,MagickFalse);
8782 if (IfMagickTrue(windows->image.orphan) )
8784 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8785 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8788 case AnnotateCommand:
8791 Annotate the image with text.
8793 status=XAnnotateEditImage(display,resource_info,windows,*image,exception);
8794 if (IfMagickFalse(status) )
8796 XNoticeWidget(display,windows,"Unable to annotate X image",
8797 (*image)->filename);
8807 status=XDrawEditImage(display,resource_info,windows,image,exception);
8808 if (IfMagickFalse(status) )
8810 XNoticeWidget(display,windows,"Unable to draw on the X image",
8811 (*image)->filename);
8821 status=XColorEditImage(display,resource_info,windows,image,exception);
8822 if (IfMagickFalse(status) )
8824 XNoticeWidget(display,windows,"Unable to pixel edit X image",
8825 (*image)->filename);
8835 status=XMatteEditImage(display,resource_info,windows,image,exception);
8836 if (IfMagickFalse(status) )
8838 XNoticeWidget(display,windows,"Unable to matte edit X image",
8839 (*image)->filename);
8844 case CompositeCommand:
8849 status=XCompositeImage(display,resource_info,windows,*image,
8851 if (IfMagickFalse(status) )
8853 XNoticeWidget(display,windows,"Unable to composite X image",
8854 (*image)->filename);
8859 case AddBorderCommand:
8865 geometry[MaxTextExtent] = "6x6";
8868 Query user for border color and geometry.
8870 XColorBrowserWidget(display,windows,"Select",color);
8873 (void) XDialogWidget(display,windows,"Add Border",
8874 "Enter border geometry:",geometry);
8875 if (*geometry == '\0')
8878 Add a border to the image.
8880 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image,
8882 XSetCursorState(display,windows,MagickTrue);
8883 XCheckRefreshWindows(display,windows);
8884 (void) QueryColorCompliance(color,AllCompliance,&(*image)->border_color,
8886 (void) ParsePageGeometry(*image,geometry,&page_geometry,
8888 border_image=BorderImage(*image,&page_geometry,(*image)->compose,
8890 if (border_image != (Image *) NULL)
8892 *image=DestroyImage(*image);
8893 *image=border_image;
8895 CatchException(exception);
8896 XSetCursorState(display,windows,MagickFalse);
8897 if (IfMagickTrue(windows->image.orphan) )
8899 windows->image.window_changes.width=(int) (*image)->columns;
8900 windows->image.window_changes.height=(int) (*image)->rows;
8901 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8902 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8905 case AddFrameCommand:
8914 geometry[MaxTextExtent] = "6x6";
8917 Query user for frame color and geometry.
8919 XColorBrowserWidget(display,windows,"Select",color);
8922 (void) XDialogWidget(display,windows,"Add Frame","Enter frame geometry:",
8924 if (*geometry == '\0')
8927 Surround image with an ornamental border.
8929 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image,
8931 XSetCursorState(display,windows,MagickTrue);
8932 XCheckRefreshWindows(display,windows);
8933 (void) QueryColorCompliance(color,AllCompliance,&(*image)->matte_color,
8935 (void) ParsePageGeometry(*image,geometry,&page_geometry,
8937 frame_info.width=page_geometry.width;
8938 frame_info.height=page_geometry.height;
8939 frame_info.outer_bevel=page_geometry.x;
8940 frame_info.inner_bevel=page_geometry.y;
8941 frame_info.x=(ssize_t) frame_info.width;
8942 frame_info.y=(ssize_t) frame_info.height;
8943 frame_info.width=(*image)->columns+2*frame_info.width;
8944 frame_info.height=(*image)->rows+2*frame_info.height;
8945 frame_image=FrameImage(*image,&frame_info,(*image)->compose,exception);
8946 if (frame_image != (Image *) NULL)
8948 *image=DestroyImage(*image);
8951 CatchException(exception);
8952 XSetCursorState(display,windows,MagickFalse);
8953 if (IfMagickTrue(windows->image.orphan) )
8955 windows->image.window_changes.width=(int) (*image)->columns;
8956 windows->image.window_changes.height=(int) (*image)->rows;
8957 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8958 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8961 case CommentCommand:
8975 unique_file=AcquireUniqueFileResource(image_info->filename);
8976 if (unique_file == -1)
8977 XNoticeWidget(display,windows,"Unable to edit image comment",
8978 image_info->filename);
8979 value=GetImageProperty(*image,"comment",exception);
8980 if (value == (char *) NULL)
8981 unique_file=close(unique_file)-1;
8987 file=fdopen(unique_file,"w");
8988 if (file == (FILE *) NULL)
8990 XNoticeWidget(display,windows,"Unable to edit image comment",
8991 image_info->filename);
8994 for (p=value; *p != '\0'; p++)
8995 (void) fputc((int) *p,file);
8996 (void) fputc('\n',file);
8997 (void) fclose(file);
8999 XSetCursorState(display,windows,MagickTrue);
9000 XCheckRefreshWindows(display,windows);
9001 status=InvokeDelegate(image_info,*image,"edit",(char *) NULL,
9003 if (IfMagickFalse(status) )
9004 XNoticeWidget(display,windows,"Unable to edit image comment",
9011 comment=FileToString(image_info->filename,~0UL,exception);
9012 if (comment != (char *) NULL)
9014 (void) SetImageProperty(*image,"comment",comment,exception);
9015 (*image)->taint=MagickTrue;
9018 (void) RelinquishUniqueFileResource(image_info->filename);
9019 XSetCursorState(display,windows,MagickFalse);
9027 XSetCursorState(display,windows,MagickTrue);
9028 XCheckRefreshWindows(display,windows);
9029 (void) AcquireUniqueFilename(filename);
9030 (void) FormatLocaleString((*image)->filename,MaxTextExtent,"launch:%s",
9032 status=WriteImage(image_info,*image,exception);
9033 if (IfMagickFalse(status) )
9034 XNoticeWidget(display,windows,"Unable to launch image editor",
9038 nexus=ReadImage(resource_info->image_info,exception);
9039 CatchException(exception);
9040 XClientMessage(display,windows->image.id,windows->im_protocols,
9041 windows->im_next_image,CurrentTime);
9043 (void) RelinquishUniqueFileResource(filename);
9044 XSetCursorState(display,windows,MagickFalse);
9047 case RegionofInterestCommand:
9050 Apply an image processing technique to a region of interest.
9052 (void) XROIImage(display,resource_info,windows,image,exception);
9062 if (IfMagickTrue(windows->magnify.mapped) )
9063 (void) XRaiseWindow(display,windows->magnify.id);
9069 XSetCursorState(display,windows,MagickTrue);
9070 (void) XMapRaised(display,windows->magnify.id);
9071 XSetCursorState(display,windows,MagickFalse);
9075 case ShowPreviewCommand:
9084 preview_type[MaxTextExtent] = "Gamma";
9087 Select preview type from menu.
9089 previews=GetCommandOptions(MagickPreviewOptions);
9090 if (previews == (char **) NULL)
9092 XListBrowserWidget(display,windows,&windows->widget,
9093 (const char **) previews,"Preview",
9094 "Select an enhancement, effect, or F/X:",preview_type);
9095 previews=DestroyStringList(previews);
9096 if (*preview_type == '\0')
9101 XSetCursorState(display,windows,MagickTrue);
9102 XCheckRefreshWindows(display,windows);
9103 image_info->preview_type=(PreviewType)
9104 ParseCommandOption(MagickPreviewOptions,MagickFalse,preview_type);
9105 image_info->group=(ssize_t) windows->image.id;
9106 (void) DeleteImageProperty(*image,"label");
9107 (void) SetImageProperty(*image,"label","Preview",exception);
9108 (void) AcquireUniqueFilename(filename);
9109 (void) FormatLocaleString((*image)->filename,MaxTextExtent,"preview:%s",
9111 status=WriteImage(image_info,*image,exception);
9112 (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
9113 preview_image=ReadImage(image_info,exception);
9114 (void) RelinquishUniqueFileResource(filename);
9115 if (preview_image == (Image *) NULL)
9117 (void) FormatLocaleString(preview_image->filename,MaxTextExtent,"show:%s",
9119 status=WriteImage(image_info,preview_image,exception);
9120 preview_image=DestroyImage(preview_image);
9121 if (IfMagickFalse(status) )
9122 XNoticeWidget(display,windows,"Unable to show image preview",
9123 (*image)->filename);
9124 XDelay(display,1500);
9125 XSetCursorState(display,windows,MagickFalse);
9128 case ShowHistogramCommand:
9134 Show image histogram.
9136 XSetCursorState(display,windows,MagickTrue);
9137 XCheckRefreshWindows(display,windows);
9138 image_info->group=(ssize_t) windows->image.id;
9139 (void) DeleteImageProperty(*image,"label");
9140 (void) SetImageProperty(*image,"label","Histogram",exception);
9141 (void) AcquireUniqueFilename(filename);
9142 (void) FormatLocaleString((*image)->filename,MaxTextExtent,"histogram:%s",
9144 status=WriteImage(image_info,*image,exception);
9145 (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
9146 histogram_image=ReadImage(image_info,exception);
9147 (void) RelinquishUniqueFileResource(filename);
9148 if (histogram_image == (Image *) NULL)
9150 (void) FormatLocaleString(histogram_image->filename,MaxTextExtent,
9151 "show:%s",filename);
9152 status=WriteImage(image_info,histogram_image,exception);
9153 histogram_image=DestroyImage(histogram_image);
9154 if (IfMagickFalse(status) )
9155 XNoticeWidget(display,windows,"Unable to show histogram",
9156 (*image)->filename);
9157 XDelay(display,1500);
9158 XSetCursorState(display,windows,MagickFalse);
9161 case ShowMatteCommand:
9166 if ((*image)->alpha_trait != BlendPixelTrait)
9168 XNoticeWidget(display,windows,
9169 "Image does not have any matte information",(*image)->filename);
9175 XSetCursorState(display,windows,MagickTrue);
9176 XCheckRefreshWindows(display,windows);
9177 image_info->group=(ssize_t) windows->image.id;
9178 (void) DeleteImageProperty(*image,"label");
9179 (void) SetImageProperty(*image,"label","Matte",exception);
9180 (void) AcquireUniqueFilename(filename);
9181 (void) FormatLocaleString((*image)->filename,MaxTextExtent,"matte:%s",
9183 status=WriteImage(image_info,*image,exception);
9184 (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
9185 matte_image=ReadImage(image_info,exception);
9186 (void) RelinquishUniqueFileResource(filename);
9187 if (matte_image == (Image *) NULL)
9189 (void) FormatLocaleString(matte_image->filename,MaxTextExtent,"show:%s",
9191 status=WriteImage(image_info,matte_image,exception);
9192 matte_image=DestroyImage(matte_image);
9193 if (IfMagickFalse(status) )
9194 XNoticeWidget(display,windows,"Unable to show matte",
9195 (*image)->filename);
9196 XDelay(display,1500);
9197 XSetCursorState(display,windows,MagickFalse);
9200 case BackgroundCommand:
9205 status=XBackgroundImage(display,resource_info,windows,image,exception);
9206 if (IfMagickFalse(status) )
9208 nexus=CloneImage(*image,0,0,MagickTrue,exception);
9209 if (nexus != (Image *) NULL)
9210 XClientMessage(display,windows->image.id,windows->im_protocols,
9211 windows->im_next_image,CurrentTime);
9214 case SlideShowCommand:
9217 delay[MaxTextExtent] = "5";
9220 Display next image after pausing.
9222 (void) XDialogWidget(display,windows,"Slide Show",
9223 "Pause how many 1/100ths of a second between images:",delay);
9226 resource_info->delay=StringToUnsignedLong(delay);
9227 XClientMessage(display,windows->image.id,windows->im_protocols,
9228 windows->im_next_image,CurrentTime);
9231 case PreferencesCommand:
9234 Set user preferences.
9236 status=XPreferencesWidget(display,resource_info,windows);
9237 if (IfMagickFalse(status) )
9239 nexus=CloneImage(*image,0,0,MagickTrue,exception);
9240 if (nexus != (Image *) NULL)
9241 XClientMessage(display,windows->image.id,windows->im_protocols,
9242 windows->im_next_image,CurrentTime);
9248 User requested help.
9250 XTextViewWidget(display,resource_info,windows,MagickFalse,
9251 "Help Viewer - Display",DisplayHelp);
9254 case BrowseDocumentationCommand:
9264 Browse the ImageMagick documentation.
9266 root_window=XRootWindow(display,XDefaultScreen(display));
9267 mozilla_atom=XInternAtom(display,"_MOZILLA_VERSION",MagickFalse);
9268 mozilla_window=XWindowByProperty(display,root_window,mozilla_atom);
9269 if (mozilla_window != (Window) NULL)
9272 command[MaxTextExtent],
9276 Display documentation using Netscape remote control.
9278 url=GetMagickHomeURL();
9279 (void) FormatLocaleString(command,MaxTextExtent,
9280 "openurl(%s,new-tab)",url);
9281 url=DestroyString(url);
9282 mozilla_atom=XInternAtom(display,"_MOZILLA_COMMAND",MagickFalse);
9283 (void) XChangeProperty(display,mozilla_window,mozilla_atom,XA_STRING,
9284 8,PropModeReplace,(unsigned char *) command,(int) strlen(command));
9285 XSetCursorState(display,windows,MagickFalse);
9288 XSetCursorState(display,windows,MagickTrue);
9289 XCheckRefreshWindows(display,windows);
9290 status=InvokeDelegate(image_info,*image,"browse",(char *) NULL,
9292 if (IfMagickFalse(status) )
9293 XNoticeWidget(display,windows,"Unable to browse documentation",
9295 XDelay(display,1500);
9296 XSetCursorState(display,windows,MagickFalse);
9299 case VersionCommand:
9301 XNoticeWidget(display,windows,GetMagickVersion((size_t *) NULL),
9302 GetMagickCopyright());
9305 case SaveToUndoBufferCommand:
9309 (void) XBell(display,0);
9313 image_info=DestroyImageInfo(image_info);
9318 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9322 + X M a g n i f y I m a g e %
9326 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9328 % XMagnifyImage() magnifies portions of the image as indicated by the pointer.
9329 % The magnified portion is displayed in a separate window.
9331 % The format of the XMagnifyImage method is:
9333 % void XMagnifyImage(Display *display,XWindows *windows,XEvent *event,
9334 % ExceptionInfo *exception)
9336 % A description of each parameter follows:
9338 % o display: Specifies a connection to an X server; returned from
9341 % o windows: Specifies a pointer to a XWindows structure.
9343 % o event: Specifies a pointer to a XEvent structure. If it is NULL,
9344 % the entire image is refreshed.
9346 % o exception: return any errors or warnings in this structure.
9349 static void XMagnifyImage(Display *display,XWindows *windows,XEvent *event,
9350 ExceptionInfo *exception)
9353 text[MaxTextExtent];
9363 Update magnified image until the mouse button is released.
9365 (void) XCheckDefineCursor(display,windows->image.id,windows->magnify.cursor);
9369 windows->magnify.x=(int) windows->image.x+x;
9370 windows->magnify.y=(int) windows->image.y+y;
9374 Map and unmap Info widget as text cursor crosses its boundaries.
9376 if (IfMagickTrue(windows->info.mapped) )
9378 if ((x < (int) (windows->info.x+windows->info.width)) &&
9379 (y < (int) (windows->info.y+windows->info.height)))
9380 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
9383 if ((x > (int) (windows->info.x+windows->info.width)) ||
9384 (y > (int) (windows->info.y+windows->info.height)))
9385 (void) XMapWindow(display,windows->info.id);
9386 if (IfMagickTrue(windows->info.mapped) )
9389 Display pointer position.
9391 (void) FormatLocaleString(text,MaxTextExtent," %+d%+d ",
9392 windows->magnify.x,windows->magnify.y);
9393 XInfoWidget(display,windows,text);
9396 Wait for next event.
9398 XScreenEvent(display,windows,event,exception);
9399 switch (event->type)
9406 User has finished magnifying image.
9425 Check boundary conditions.
9430 if (x >= (int) windows->image.width)
9431 x=(int) windows->image.width-1;
9435 if (y >= (int) windows->image.height)
9436 y=(int) windows->image.height-1;
9437 } while ((state & ExitState) == 0);
9439 Display magnified image.
9441 XSetCursorState(display,windows,MagickFalse);
9445 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9449 + X M a g n i f y W i n d o w C o m m a n d %
9453 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9455 % XMagnifyWindowCommand() moves the image within an Magnify window by one
9456 % pixel as specified by the key symbol.
9458 % The format of the XMagnifyWindowCommand method is:
9460 % void XMagnifyWindowCommand(Display *display,XWindows *windows,
9461 % const MagickStatusType state,const KeySym key_symbol,
9462 % ExceptionInfo *exception)
9464 % A description of each parameter follows:
9466 % o display: Specifies a connection to an X server; returned from
9469 % o windows: Specifies a pointer to a XWindows structure.
9471 % o state: key mask.
9473 % o key_symbol: Specifies a KeySym which indicates which side of the image
9476 % o exception: return any errors or warnings in this structure.
9479 static void XMagnifyWindowCommand(Display *display,XWindows *windows,
9480 const MagickStatusType state,const KeySym key_symbol,ExceptionInfo *exception)
9486 User specified a magnify factor or position.
9489 if ((state & Mod1Mask) != 0)
9491 switch ((int) key_symbol)
9495 (void) XWithdrawWindow(display,windows->magnify.id,
9496 windows->magnify.screen);
9502 windows->magnify.x=(int) windows->image.width/2;
9503 windows->magnify.y=(int) windows->image.height/2;
9509 if (windows->magnify.x > 0)
9510 windows->magnify.x-=quantum;
9516 if (windows->magnify.y > 0)
9517 windows->magnify.y-=quantum;
9523 if (windows->magnify.x < (int) (windows->image.ximage->width-1))
9524 windows->magnify.x+=quantum;
9530 if (windows->magnify.y < (int) (windows->image.ximage->height-1))
9531 windows->magnify.y+=quantum;
9545 windows->magnify.data=(key_symbol-XK_0);
9559 windows->magnify.data=(key_symbol-XK_KP_0);
9565 XMakeMagnifyImage(display,windows,exception);
9569 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9573 + X M a k e P a n I m a g e %
9577 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9579 % XMakePanImage() creates a thumbnail of the image and displays it in the Pan
9582 % The format of the XMakePanImage method is:
9584 % void XMakePanImage(Display *display,XResourceInfo *resource_info,
9585 % XWindows *windows,Image *image,ExceptionInfo *exception)
9587 % A description of each parameter follows:
9589 % o display: Specifies a connection to an X server; returned from
9592 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
9594 % o windows: Specifies a pointer to a XWindows structure.
9596 % o image: the image.
9598 % o exception: return any errors or warnings in this structure.
9601 static void XMakePanImage(Display *display,XResourceInfo *resource_info,
9602 XWindows *windows,Image *image,ExceptionInfo *exception)
9608 Create and display image for panning icon.
9610 XSetCursorState(display,windows,MagickTrue);
9611 XCheckRefreshWindows(display,windows);
9612 windows->pan.x=(int) windows->image.x;
9613 windows->pan.y=(int) windows->image.y;
9614 status=XMakeImage(display,resource_info,&windows->pan,image,
9615 windows->pan.width,windows->pan.height,exception);
9616 if (IfMagickFalse(status) )
9617 ThrowXWindowException(ResourceLimitError,
9618 "MemoryAllocationFailed",image->filename);
9619 (void) XSetWindowBackgroundPixmap(display,windows->pan.id,
9620 windows->pan.pixmap);
9621 (void) XClearWindow(display,windows->pan.id);
9622 XDrawPanRectangle(display,windows);
9623 XSetCursorState(display,windows,MagickFalse);
9627 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9631 + X M a t t a E d i t I m a g e %
9635 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9637 % XMatteEditImage() allows the user to interactively change the Matte channel
9638 % of an image. If the image is PseudoClass it is promoted to DirectClass
9639 % before the matte information is stored.
9641 % The format of the XMatteEditImage method is:
9643 % MagickBooleanType XMatteEditImage(Display *display,
9644 % XResourceInfo *resource_info,XWindows *windows,Image **image,
9645 % ExceptionInfo *exception)
9647 % A description of each parameter follows:
9649 % o display: Specifies a connection to an X server; returned from
9652 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
9654 % o windows: Specifies a pointer to a XWindows structure.
9656 % o image: the image; returned from ReadImage.
9658 % o exception: return any errors or warnings in this structure.
9661 static MagickBooleanType XMatteEditImage(Display *display,
9662 XResourceInfo *resource_info,XWindows *windows,Image **image,
9663 ExceptionInfo *exception)
9666 matte[MaxTextExtent] = "0";
9681 static const ModeType
9682 MatteEditCommands[] =
9685 MatteEditBorderCommand,
9686 MatteEditFuzzCommand,
9687 MatteEditValueCommand,
9688 MatteEditUndoCommand,
9689 MatteEditHelpCommand,
9690 MatteEditDismissCommand
9694 method = PointMethod;
9697 border_color = { 0, 0, 0, 0, 0, 0 };
9700 command[MaxTextExtent],
9701 text[MaxTextExtent];
9733 (void) CloneString(&windows->command.name,"Matte Edit");
9734 windows->command.data=4;
9735 (void) XCommandWidget(display,windows,MatteEditMenu,(XEvent *) NULL);
9736 (void) XMapRaised(display,windows->command.id);
9737 XClientMessage(display,windows->image.id,windows->im_protocols,
9738 windows->im_update_widget,CurrentTime);
9742 cursor=XMakeCursor(display,windows->image.id,windows->map_info->colormap,
9743 resource_info->background_color,resource_info->foreground_color);
9744 (void) XCheckDefineCursor(display,windows->image.id,cursor);
9746 Track pointer until button 1 is pressed.
9748 XQueryPosition(display,windows->image.id,&x,&y);
9749 (void) XSelectInput(display,windows->image.id,
9750 windows->image.attributes.event_mask | PointerMotionMask);
9754 if (IfMagickTrue(windows->info.mapped) )
9757 Display pointer position.
9759 (void) FormatLocaleString(text,MaxTextExtent," %+d%+d ",
9760 x+windows->image.x,y+windows->image.y);
9761 XInfoWidget(display,windows,text);
9764 Wait for next event.
9766 XScreenEvent(display,windows,&event,exception);
9767 if (event.xany.window == windows->command.id)
9770 Select a command from the Command widget.
9772 id=XCommandWidget(display,windows,MatteEditMenu,&event);
9775 (void) XCheckDefineCursor(display,windows->image.id,cursor);
9778 switch (MatteEditCommands[id])
9780 case MatteEditMethod:
9786 Select a method from the pop-up menu.
9788 methods=GetCommandOptions(MagickMethodOptions);
9789 if (methods == (char **) NULL)
9791 entry=XMenuWidget(display,windows,MatteEditMenu[id],
9792 (const char **) methods,command);
9794 method=(PaintMethod) ParseCommandOption(MagickMethodOptions,
9795 MagickFalse,methods[entry]);
9796 methods=DestroyStringList(methods);
9799 case MatteEditBorderCommand:
9802 *ColorMenu[MaxNumberPens];
9808 Initialize menu selections.
9810 for (i=0; i < (int) (MaxNumberPens-2); i++)
9811 ColorMenu[i]=resource_info->pen_colors[i];
9812 ColorMenu[MaxNumberPens-2]="Browser...";
9813 ColorMenu[MaxNumberPens-1]=(const char *) NULL;
9815 Select a pen color from the pop-up menu.
9817 pen_number=XMenuWidget(display,windows,MatteEditMenu[id],
9818 (const char **) ColorMenu,command);
9821 if (pen_number == (MaxNumberPens-2))
9824 color_name[MaxTextExtent] = "gray";
9827 Select a pen color from a dialog.
9829 resource_info->pen_colors[pen_number]=color_name;
9830 XColorBrowserWidget(display,windows,"Select",color_name);
9831 if (*color_name == '\0')
9837 (void) XParseColor(display,windows->map_info->colormap,
9838 resource_info->pen_colors[pen_number],&border_color);
9841 case MatteEditFuzzCommand:
9844 fuzz[MaxTextExtent];
9859 Select a command from the pop-up menu.
9861 entry=XMenuWidget(display,windows,MatteEditMenu[id],FuzzMenu,
9867 (*image)->fuzz=StringToDoubleInterval(FuzzMenu[entry],(double)
9871 (void) CopyMagickString(fuzz,"20%",MaxTextExtent);
9872 (void) XDialogWidget(display,windows,"Ok",
9873 "Enter fuzz factor (0.0 - 99.9%):",fuzz);
9876 (void) ConcatenateMagickString(fuzz,"%",MaxTextExtent);
9877 (*image)->fuzz=StringToDoubleInterval(fuzz,(double) QuantumRange+
9881 case MatteEditValueCommand:
9884 message[MaxTextExtent];
9896 Select a command from the pop-up menu.
9898 entry=XMenuWidget(display,windows,MatteEditMenu[id],MatteMenu,
9904 (void) FormatLocaleString(matte,MaxTextExtent,QuantumFormat,
9906 if (LocaleCompare(MatteMenu[entry],"Transparent") == 0)
9907 (void) FormatLocaleString(matte,MaxTextExtent,QuantumFormat,
9908 (Quantum) TransparentAlpha);
9911 (void) FormatLocaleString(message,MaxTextExtent,
9912 "Enter matte value (0 - " QuantumFormat "):",(Quantum)
9914 (void) XDialogWidget(display,windows,"Matte",message,matte);
9919 case MatteEditUndoCommand:
9921 (void) XMagickCommand(display,resource_info,windows,UndoCommand,
9925 case MatteEditHelpCommand:
9927 XTextViewWidget(display,resource_info,windows,MagickFalse,
9928 "Help Viewer - Matte Edit",ImageMatteEditHelp);
9931 case MatteEditDismissCommand:
9943 (void) XCheckDefineCursor(display,windows->image.id,cursor);
9950 if (event.xbutton.button != Button1)
9952 if ((event.xbutton.window != windows->image.id) &&
9953 (event.xbutton.window != windows->magnify.id))
9960 (void) XMagickCommand(display,resource_info,windows,
9961 SaveToUndoBufferCommand,image,exception);
9962 state|=UpdateConfigurationState;
9967 if (event.xbutton.button != Button1)
9969 if ((event.xbutton.window != windows->image.id) &&
9970 (event.xbutton.window != windows->magnify.id))
9973 Update colormap information.
9977 XConfigureImageColormap(display,resource_info,windows,*image,exception);
9978 (void) XConfigureImage(display,resource_info,windows,*image,exception);
9979 XInfoWidget(display,windows,text);
9980 (void) XCheckDefineCursor(display,windows->image.id,cursor);
9981 state&=(~UpdateConfigurationState);
9989 command[MaxTextExtent];
9994 if (event.xkey.window == windows->magnify.id)
9999 window=windows->magnify.id;
10000 while (XCheckWindowEvent(display,window,KeyPressMask,&event)) ;
10002 if (event.xkey.window != windows->image.id)
10005 Respond to a user key press.
10007 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
10008 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
10009 switch ((int) key_symbol)
10023 XTextViewWidget(display,resource_info,windows,MagickFalse,
10024 "Help Viewer - Matte Edit",ImageMatteEditHelp);
10029 (void) XBell(display,0);
10038 Map and unmap Info widget as cursor crosses its boundaries.
10042 if (IfMagickTrue(windows->info.mapped) )
10044 if ((x < (int) (windows->info.x+windows->info.width)) &&
10045 (y < (int) (windows->info.y+windows->info.height)))
10046 (void) XWithdrawWindow(display,windows->info.id,
10047 windows->info.screen);
10050 if ((x > (int) (windows->info.x+windows->info.width)) ||
10051 (y > (int) (windows->info.y+windows->info.height)))
10052 (void) XMapWindow(display,windows->info.id);
10058 if (event.xany.window == windows->magnify.id)
10060 x=windows->magnify.x-windows->image.x;
10061 y=windows->magnify.y-windows->image.y;
10065 if ((state & UpdateConfigurationState) != 0)
10075 Matte edit is relative to image configuration.
10077 (void) XClearArea(display,windows->image.id,x_offset,y_offset,1,1,
10079 XPutPixel(windows->image.ximage,x_offset,y_offset,
10080 windows->pixel_info->background_color.pixel);
10081 width=(unsigned int) (*image)->columns;
10082 height=(unsigned int) (*image)->rows;
10085 if (windows->image.crop_geometry != (char *) NULL)
10086 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,
10088 x_offset=(int) (width*(windows->image.x+x_offset)/
10089 windows->image.ximage->width+x);
10090 y_offset=(int) (height*(windows->image.y+y_offset)/
10091 windows->image.ximage->height+y);
10092 if ((x_offset < 0) || (y_offset < 0))
10094 if ((x_offset >= (int) (*image)->columns) ||
10095 (y_offset >= (int) (*image)->rows))
10097 if (IfMagickFalse(SetImageStorageClass(*image,DirectClass,exception)) )
10098 return(MagickFalse);
10099 if ((*image)->alpha_trait != BlendPixelTrait)
10100 (void) SetImageAlphaChannel(*image,OpaqueAlphaChannel,exception);
10101 image_view=AcquireAuthenticCacheView(*image,exception);
10108 Update matte information using point algorithm.
10110 q=GetCacheViewAuthenticPixels(image_view,(ssize_t) x_offset,
10111 (ssize_t) y_offset,1,1,exception);
10112 if (q == (Quantum *) NULL)
10114 SetPixelAlpha(*image,(Quantum) StringToLong(matte),q);
10115 (void) SyncCacheViewAuthenticPixels(image_view,exception);
10118 case ReplaceMethod:
10125 Update matte information using replace algorithm.
10127 (void) GetOneCacheViewVirtualPixelInfo(image_view,(ssize_t)
10128 x_offset,(ssize_t) y_offset,&target,exception);
10129 for (y=0; y < (int) (*image)->rows; y++)
10131 q=GetCacheViewAuthenticPixels(image_view,0,(ssize_t) y,
10132 (*image)->columns,1,exception);
10133 if (q == (Quantum *) NULL)
10135 for (x=0; x < (int) (*image)->columns; x++)
10137 GetPixelInfoPixel(*image,q,&pixel);
10138 if (IsFuzzyEquivalencePixelInfo(&pixel,&target))
10139 SetPixelAlpha(*image,(Quantum) StringToLong(matte),q);
10140 q+=GetPixelChannels(*image);
10142 if (IfMagickFalse(SyncCacheViewAuthenticPixels(image_view,exception)) )
10147 case FloodfillMethod:
10148 case FillToBorderMethod:
10160 Update matte information using floodfill algorithm.
10162 (void) GetOneVirtualPixelInfo(*image,
10163 GetPixelCacheVirtualMethod(*image),(ssize_t) x_offset,(ssize_t)
10164 y_offset,&target,exception);
10165 if (method == FillToBorderMethod)
10167 target.red=(double) ScaleShortToQuantum(
10169 target.green=(double) ScaleShortToQuantum(
10170 border_color.green);
10171 target.blue=(double) ScaleShortToQuantum(
10172 border_color.blue);
10174 draw_info=CloneDrawInfo(resource_info->image_info,
10175 (DrawInfo *) NULL);
10176 draw_info->fill.alpha=(double) ClampToQuantum(
10177 StringToDouble(matte,(char **) NULL));
10178 channel_mask=SetImageChannelMask(*image,AlphaChannel);
10179 (void) FloodfillPaintImage(*image,draw_info,&target,(ssize_t)
10180 x_offset,(ssize_t) y_offset,
10181 IsMagickFalse(method == FloodfillMethod),exception);
10182 (void) SetPixelChannelMask(*image,channel_mask);
10183 draw_info=DestroyDrawInfo(draw_info);
10189 Update matte information using reset algorithm.
10191 if (IfMagickFalse(SetImageStorageClass(*image,DirectClass,exception)) )
10192 return(MagickFalse);
10193 for (y=0; y < (int) (*image)->rows; y++)
10195 q=QueueCacheViewAuthenticPixels(image_view,0,(ssize_t) y,
10196 (*image)->columns,1,exception);
10197 if (q == (Quantum *) NULL)
10199 for (x=0; x < (int) (*image)->columns; x++)
10201 SetPixelAlpha(*image,(Quantum) StringToLong(matte),q);
10202 q+=GetPixelChannels(*image);
10204 if (IfMagickFalse(SyncCacheViewAuthenticPixels(image_view,exception)) )
10207 if (StringToLong(matte) == (long) OpaqueAlpha)
10208 (*image)->alpha_trait=UndefinedPixelTrait;
10212 image_view=DestroyCacheView(image_view);
10213 state&=(~UpdateConfigurationState);
10215 } while ((state & ExitState) == 0);
10216 (void) XSelectInput(display,windows->image.id,
10217 windows->image.attributes.event_mask);
10218 XSetCursorState(display,windows,MagickFalse);
10219 (void) XFreeCursor(display,cursor);
10220 return(MagickTrue);
10224 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10228 + X O p e n I m a g e %
10232 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10234 % XOpenImage() loads an image from a file.
10236 % The format of the XOpenImage method is:
10238 % Image *XOpenImage(Display *display,XResourceInfo *resource_info,
10239 % XWindows *windows,const unsigned int command)
10241 % A description of each parameter follows:
10243 % o display: Specifies a connection to an X server; returned from
10246 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
10248 % o windows: Specifies a pointer to a XWindows structure.
10250 % o command: A value other than zero indicates that the file is selected
10251 % from the command line argument list.
10254 static Image *XOpenImage(Display *display,XResourceInfo *resource_info,
10255 XWindows *windows,const MagickBooleanType command)
10270 filename[MaxTextExtent] = "\0";
10273 Request file name from user.
10275 if (IfMagickFalse(command) )
10276 XFileBrowserWidget(display,windows,"Open",filename);
10292 Select next image from the command line.
10294 status=XGetCommand(display,windows->image.id,&files,&count);
10297 ThrowXWindowException(XServerError,"UnableToGetProperty","...");
10298 return((Image *) NULL);
10300 filelist=(char **) AcquireQuantumMemory((size_t) count,sizeof(*filelist));
10301 if (filelist == (char **) NULL)
10303 ThrowXWindowException(ResourceLimitError,
10304 "MemoryAllocationFailed","...");
10305 (void) XFreeStringList(files);
10306 return((Image *) NULL);
10309 for (i=1; i < count; i++)
10310 if (*files[i] != '-')
10311 filelist[j++]=files[i];
10312 filelist[j]=(char *) NULL;
10313 XListBrowserWidget(display,windows,&windows->widget,
10314 (const char **) filelist,"Load","Select Image to Load:",filename);
10315 filelist=(char **) RelinquishMagickMemory(filelist);
10316 (void) XFreeStringList(files);
10318 if (*filename == '\0')
10319 return((Image *) NULL);
10320 image_info=CloneImageInfo(resource_info->image_info);
10321 (void) SetImageInfoProgressMonitor(image_info,(MagickProgressMonitor) NULL,
10323 (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
10324 exception=AcquireExceptionInfo();
10325 (void) SetImageInfo(image_info,0,exception);
10326 if (LocaleCompare(image_info->magick,"X") == 0)
10329 seconds[MaxTextExtent];
10332 User may want to delay the X server screen grab.
10334 (void) CopyMagickString(seconds,"0",MaxTextExtent);
10335 (void) XDialogWidget(display,windows,"Grab","Enter any delay in seconds:",
10337 if (*seconds == '\0')
10338 return((Image *) NULL);
10339 XDelay(display,(size_t) (1000*StringToLong(seconds)));
10341 magick_info=GetMagickInfo(image_info->magick,exception);
10342 if ((magick_info != (const MagickInfo *) NULL) &&
10343 IfMagickTrue(magick_info->raw))
10346 geometry[MaxTextExtent];
10349 Request image size from the user.
10351 (void) CopyMagickString(geometry,"512x512",MaxTextExtent);
10352 if (image_info->size != (char *) NULL)
10353 (void) CopyMagickString(geometry,image_info->size,MaxTextExtent);
10354 (void) XDialogWidget(display,windows,"Load","Enter the image geometry:",
10356 (void) CloneString(&image_info->size,geometry);
10361 XSetCursorState(display,windows,MagickTrue);
10362 XCheckRefreshWindows(display,windows);
10363 (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
10364 nexus=ReadImage(image_info,exception);
10365 CatchException(exception);
10366 XSetCursorState(display,windows,MagickFalse);
10367 if (nexus != (Image *) NULL)
10368 XClientMessage(display,windows->image.id,windows->im_protocols,
10369 windows->im_next_image,CurrentTime);
10377 Unknown image format.
10379 text=FileToString(filename,~0UL,exception);
10380 if (text == (char *) NULL)
10381 return((Image *) NULL);
10382 textlist=StringToList(text);
10383 if (textlist != (char **) NULL)
10386 title[MaxTextExtent];
10391 (void) FormatLocaleString(title,MaxTextExtent,
10392 "Unknown format: %s",filename);
10393 XTextViewWidget(display,resource_info,windows,MagickTrue,title,
10394 (const char **) textlist);
10395 for (i=0; textlist[i] != (char *) NULL; i++)
10396 textlist[i]=DestroyString(textlist[i]);
10397 textlist=(char **) RelinquishMagickMemory(textlist);
10399 text=DestroyString(text);
10401 exception=DestroyExceptionInfo(exception);
10402 image_info=DestroyImageInfo(image_info);
10407 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10411 + X P a n I m a g e %
10415 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10417 % XPanImage() pans the image until the mouse button is released.
10419 % The format of the XPanImage method is:
10421 % void XPanImage(Display *display,XWindows *windows,XEvent *event,
10422 % ExceptionInfo *exception)
10424 % A description of each parameter follows:
10426 % o display: Specifies a connection to an X server; returned from
10429 % o windows: Specifies a pointer to a XWindows structure.
10431 % o event: Specifies a pointer to a XEvent structure. If it is NULL,
10432 % the entire image is refreshed.
10434 % o exception: return any errors or warnings in this structure.
10437 static void XPanImage(Display *display,XWindows *windows,XEvent *event,
10438 ExceptionInfo *exception)
10441 text[MaxTextExtent];
10459 if ((windows->image.ximage->width > (int) windows->image.width) &&
10460 (windows->image.ximage->height > (int) windows->image.height))
10461 cursor=XCreateFontCursor(display,XC_fleur);
10463 if (windows->image.ximage->width > (int) windows->image.width)
10464 cursor=XCreateFontCursor(display,XC_sb_h_double_arrow);
10466 if (windows->image.ximage->height > (int) windows->image.height)
10467 cursor=XCreateFontCursor(display,XC_sb_v_double_arrow);
10469 cursor=XCreateFontCursor(display,XC_arrow);
10470 (void) XCheckDefineCursor(display,windows->pan.id,cursor);
10472 Pan image as pointer moves until the mouse button is released.
10474 x_factor=(double) windows->image.ximage->width/windows->pan.width;
10475 y_factor=(double) windows->image.ximage->height/windows->pan.height;
10476 pan_info.width=windows->pan.width*windows->image.width/
10477 windows->image.ximage->width;
10478 pan_info.height=windows->pan.height*windows->image.height/
10479 windows->image.ximage->height;
10482 state=UpdateConfigurationState;
10485 switch (event->type)
10490 User choose an initial pan location.
10492 pan_info.x=(ssize_t) event->xbutton.x;
10493 pan_info.y=(ssize_t) event->xbutton.y;
10494 state|=UpdateConfigurationState;
10497 case ButtonRelease:
10500 User has finished panning the image.
10502 pan_info.x=(ssize_t) event->xbutton.x;
10503 pan_info.y=(ssize_t) event->xbutton.y;
10504 state|=UpdateConfigurationState | ExitState;
10509 pan_info.x=(ssize_t) event->xmotion.x;
10510 pan_info.y=(ssize_t) event->xmotion.y;
10511 state|=UpdateConfigurationState;
10516 if ((state & UpdateConfigurationState) != 0)
10519 Check boundary conditions.
10521 if (pan_info.x < (ssize_t) (pan_info.width/2))
10524 pan_info.x=(ssize_t) (x_factor*(pan_info.x-(pan_info.width/2)));
10525 if (pan_info.x < 0)
10528 if ((int) (pan_info.x+windows->image.width) >
10529 windows->image.ximage->width)
10530 pan_info.x=(ssize_t)
10531 (windows->image.ximage->width-windows->image.width);
10532 if (pan_info.y < (ssize_t) (pan_info.height/2))
10535 pan_info.y=(ssize_t) (y_factor*(pan_info.y-(pan_info.height/2)));
10536 if (pan_info.y < 0)
10539 if ((int) (pan_info.y+windows->image.height) >
10540 windows->image.ximage->height)
10541 pan_info.y=(ssize_t)
10542 (windows->image.ximage->height-windows->image.height);
10543 if ((windows->image.x != (int) pan_info.x) ||
10544 (windows->image.y != (int) pan_info.y))
10547 Display image pan offset.
10549 windows->image.x=(int) pan_info.x;
10550 windows->image.y=(int) pan_info.y;
10551 (void) FormatLocaleString(text,MaxTextExtent," %ux%u%+d%+d ",
10552 windows->image.width,windows->image.height,windows->image.x,
10554 XInfoWidget(display,windows,text);
10556 Refresh Image window.
10558 XDrawPanRectangle(display,windows);
10559 XRefreshWindow(display,&windows->image,(XEvent *) NULL);
10561 state&=(~UpdateConfigurationState);
10564 Wait for next event.
10566 if ((state & ExitState) == 0)
10567 XScreenEvent(display,windows,event,exception);
10568 } while ((state & ExitState) == 0);
10572 (void) XCheckDefineCursor(display,windows->pan.id,windows->pan.cursor);
10573 (void) XFreeCursor(display,cursor);
10574 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
10578 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10582 + X P a s t e I m a g e %
10586 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10588 % XPasteImage() pastes an image previously saved with XCropImage in the X
10589 % window image at a location the user chooses with the pointer.
10591 % The format of the XPasteImage method is:
10593 % MagickBooleanType XPasteImage(Display *display,
10594 % XResourceInfo *resource_info,XWindows *windows,Image *image,
10595 % ExceptionInfo *exception)
10597 % A description of each parameter follows:
10599 % o display: Specifies a connection to an X server; returned from
10602 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
10604 % o windows: Specifies a pointer to a XWindows structure.
10606 % o image: the image; returned from ReadImage.
10608 % o exception: return any errors or warnings in this structure.
10611 static MagickBooleanType XPasteImage(Display *display,
10612 XResourceInfo *resource_info,XWindows *windows,Image *image,
10613 ExceptionInfo *exception)
10624 static const ModeType
10627 PasteOperatorsCommand,
10629 PasteDismissCommand
10632 static CompositeOperator
10633 compose = CopyCompositeOp;
10636 text[MaxTextExtent];
10670 if (resource_info->copy_image == (Image *) NULL)
10671 return(MagickFalse);
10672 paste_image=CloneImage(resource_info->copy_image,0,0,MagickTrue,exception);
10674 Map Command widget.
10676 (void) CloneString(&windows->command.name,"Paste");
10677 windows->command.data=1;
10678 (void) XCommandWidget(display,windows,PasteMenu,(XEvent *) NULL);
10679 (void) XMapRaised(display,windows->command.id);
10680 XClientMessage(display,windows->image.id,windows->im_protocols,
10681 windows->im_update_widget,CurrentTime);
10683 Track pointer until button 1 is pressed.
10685 XSetCursorState(display,windows,MagickFalse);
10686 XQueryPosition(display,windows->image.id,&x,&y);
10687 (void) XSelectInput(display,windows->image.id,
10688 windows->image.attributes.event_mask | PointerMotionMask);
10689 paste_info.x=(ssize_t) windows->image.x+x;
10690 paste_info.y=(ssize_t) windows->image.y+y;
10691 paste_info.width=0;
10692 paste_info.height=0;
10693 cursor=XCreateFontCursor(display,XC_ul_angle);
10694 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
10695 state=DefaultState;
10698 if (IfMagickTrue(windows->info.mapped) )
10701 Display pointer position.
10703 (void) FormatLocaleString(text,MaxTextExtent," %+ld%+ld ",
10704 (long) paste_info.x,(long) paste_info.y);
10705 XInfoWidget(display,windows,text);
10707 highlight_info=paste_info;
10708 highlight_info.x=paste_info.x-windows->image.x;
10709 highlight_info.y=paste_info.y-windows->image.y;
10710 XHighlightRectangle(display,windows->image.id,
10711 windows->image.highlight_context,&highlight_info);
10713 Wait for next event.
10715 XScreenEvent(display,windows,&event,exception);
10716 XHighlightRectangle(display,windows->image.id,
10717 windows->image.highlight_context,&highlight_info);
10718 if (event.xany.window == windows->command.id)
10721 Select a command from the Command widget.
10723 id=XCommandWidget(display,windows,PasteMenu,&event);
10726 switch (PasteCommands[id])
10728 case PasteOperatorsCommand:
10731 command[MaxTextExtent],
10735 Select a command from the pop-up menu.
10737 operators=GetCommandOptions(MagickComposeOptions);
10738 if (operators == (char **) NULL)
10740 entry=XMenuWidget(display,windows,PasteMenu[id],
10741 (const char **) operators,command);
10743 compose=(CompositeOperator) ParseCommandOption(
10744 MagickComposeOptions,MagickFalse,operators[entry]);
10745 operators=DestroyStringList(operators);
10748 case PasteHelpCommand:
10750 XTextViewWidget(display,resource_info,windows,MagickFalse,
10751 "Help Viewer - Image Composite",ImagePasteHelp);
10754 case PasteDismissCommand:
10759 state|=EscapeState;
10768 switch (event.type)
10772 if (IfMagickTrue(image->debug) )
10773 (void) LogMagickEvent(X11Event,GetMagickModule(),
10774 "Button Press: 0x%lx %u +%d+%d",event.xbutton.window,
10775 event.xbutton.button,event.xbutton.x,event.xbutton.y);
10776 if (event.xbutton.button != Button1)
10778 if (event.xbutton.window != windows->image.id)
10781 Paste rectangle is relative to image configuration.
10783 width=(unsigned int) image->columns;
10784 height=(unsigned int) image->rows;
10787 if (windows->image.crop_geometry != (char *) NULL)
10788 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,
10790 scale_factor=(double) windows->image.ximage->width/width;
10791 paste_info.width=(unsigned int) (scale_factor*paste_image->columns+0.5);
10792 scale_factor=(double) windows->image.ximage->height/height;
10793 paste_info.height=(unsigned int) (scale_factor*paste_image->rows+0.5);
10794 (void) XCheckDefineCursor(display,windows->image.id,cursor);
10795 paste_info.x=(ssize_t) windows->image.x+event.xbutton.x;
10796 paste_info.y=(ssize_t) windows->image.y+event.xbutton.y;
10799 case ButtonRelease:
10801 if (IfMagickTrue(image->debug) )
10802 (void) LogMagickEvent(X11Event,GetMagickModule(),
10803 "Button Release: 0x%lx %u +%d+%d",event.xbutton.window,
10804 event.xbutton.button,event.xbutton.x,event.xbutton.y);
10805 if (event.xbutton.button != Button1)
10807 if (event.xbutton.window != windows->image.id)
10809 if ((paste_info.width != 0) && (paste_info.height != 0))
10812 User has selected the location of the paste image.
10814 paste_info.x=(ssize_t) windows->image.x+event.xbutton.x;
10815 paste_info.y=(ssize_t) windows->image.y+event.xbutton.y;
10825 command[MaxTextExtent];
10833 if (event.xkey.window != windows->image.id)
10836 Respond to a user key press.
10838 length=XLookupString((XKeyEvent *) &event.xkey,command,(int)
10839 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
10840 *(command+length)='\0';
10841 if (IfMagickTrue(image->debug) )
10842 (void) LogMagickEvent(X11Event,GetMagickModule(),
10843 "Key press: 0x%lx (%s)",(long) key_symbol,command);
10844 switch ((int) key_symbol)
10852 paste_image=DestroyImage(paste_image);
10853 state|=EscapeState;
10860 (void) XSetFunction(display,windows->image.highlight_context,
10862 XTextViewWidget(display,resource_info,windows,MagickFalse,
10863 "Help Viewer - Image Composite",ImagePasteHelp);
10864 (void) XSetFunction(display,windows->image.highlight_context,
10870 (void) XBell(display,0);
10879 Map and unmap Info widget as text cursor crosses its boundaries.
10883 if (IfMagickTrue(windows->info.mapped) )
10885 if ((x < (int) (windows->info.x+windows->info.width)) &&
10886 (y < (int) (windows->info.y+windows->info.height)))
10887 (void) XWithdrawWindow(display,windows->info.id,
10888 windows->info.screen);
10891 if ((x > (int) (windows->info.x+windows->info.width)) ||
10892 (y > (int) (windows->info.y+windows->info.height)))
10893 (void) XMapWindow(display,windows->info.id);
10894 paste_info.x=(ssize_t) windows->image.x+x;
10895 paste_info.y=(ssize_t) windows->image.y+y;
10900 if (IfMagickTrue(image->debug) )
10901 (void) LogMagickEvent(X11Event,GetMagickModule(),"Event type: %d",
10906 } while ((state & ExitState) == 0);
10907 (void) XSelectInput(display,windows->image.id,
10908 windows->image.attributes.event_mask);
10909 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
10910 XSetCursorState(display,windows,MagickFalse);
10911 (void) XFreeCursor(display,cursor);
10912 if ((state & EscapeState) != 0)
10913 return(MagickTrue);
10915 Image pasting is relative to image configuration.
10917 XSetCursorState(display,windows,MagickTrue);
10918 XCheckRefreshWindows(display,windows);
10919 width=(unsigned int) image->columns;
10920 height=(unsigned int) image->rows;
10923 if (windows->image.crop_geometry != (char *) NULL)
10924 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
10925 scale_factor=(double) width/windows->image.ximage->width;
10927 paste_info.x=(ssize_t) (scale_factor*paste_info.x+0.5);
10928 paste_info.width=(unsigned int) (scale_factor*paste_info.width+0.5);
10929 scale_factor=(double) height/windows->image.ximage->height;
10931 paste_info.y=(ssize_t) (scale_factor*paste_info.y*scale_factor+0.5);
10932 paste_info.height=(unsigned int) (scale_factor*paste_info.height+0.5);
10934 Paste image with X Image window.
10936 (void) CompositeImage(image,paste_image,compose,MagickTrue,paste_info.x,
10937 paste_info.y,exception);
10938 paste_image=DestroyImage(paste_image);
10939 XSetCursorState(display,windows,MagickFalse);
10941 Update image colormap.
10943 XConfigureImageColormap(display,resource_info,windows,image,exception);
10944 (void) XConfigureImage(display,resource_info,windows,image,exception);
10945 return(MagickTrue);
10949 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10953 + X P r i n t I m a g e %
10957 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10959 % XPrintImage() prints an image to a Postscript printer.
10961 % The format of the XPrintImage method is:
10963 % MagickBooleanType XPrintImage(Display *display,
10964 % XResourceInfo *resource_info,XWindows *windows,Image *image,
10965 % ExceptionInfo *exception)
10967 % A description of each parameter follows:
10969 % o display: Specifies a connection to an X server; returned from
10972 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
10974 % o windows: Specifies a pointer to a XWindows structure.
10976 % o image: the image.
10978 % o exception: return any errors or warnings in this structure.
10981 static MagickBooleanType XPrintImage(Display *display,
10982 XResourceInfo *resource_info,XWindows *windows,Image *image,
10983 ExceptionInfo *exception)
10986 filename[MaxTextExtent],
10987 geometry[MaxTextExtent];
10999 Request Postscript page geometry from user.
11001 image_info=CloneImageInfo(resource_info->image_info);
11002 (void) FormatLocaleString(geometry,MaxTextExtent,"Letter");
11003 if (image_info->page != (char *) NULL)
11004 (void) CopyMagickString(geometry,image_info->page,MaxTextExtent);
11005 XListBrowserWidget(display,windows,&windows->widget,PageSizes,"Select",
11006 "Select Postscript Page Geometry:",geometry);
11007 if (*geometry == '\0')
11008 return(MagickTrue);
11009 image_info->page=GetPageGeometry(geometry);
11011 Apply image transforms.
11013 XSetCursorState(display,windows,MagickTrue);
11014 XCheckRefreshWindows(display,windows);
11015 print_image=CloneImage(image,0,0,MagickTrue,exception);
11016 if (print_image == (Image *) NULL)
11017 return(MagickFalse);
11018 (void) FormatLocaleString(geometry,MaxTextExtent,"%dx%d!",
11019 windows->image.ximage->width,windows->image.ximage->height);
11020 (void) TransformImage(&print_image,windows->image.crop_geometry,geometry,
11025 (void) AcquireUniqueFilename(filename);
11026 (void) FormatLocaleString(print_image->filename,MaxTextExtent,"print:%s",
11028 status=WriteImage(image_info,print_image,exception);
11029 (void) RelinquishUniqueFileResource(filename);
11030 print_image=DestroyImage(print_image);
11031 image_info=DestroyImageInfo(image_info);
11032 XSetCursorState(display,windows,MagickFalse);
11033 return(IsMagickTrue(status));
11037 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
11041 + X R O I I m a g e %
11045 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
11047 % XROIImage() applies an image processing technique to a region of interest.
11049 % The format of the XROIImage method is:
11051 % MagickBooleanType XROIImage(Display *display,
11052 % XResourceInfo *resource_info,XWindows *windows,Image **image,
11053 % ExceptionInfo *exception)
11055 % A description of each parameter follows:
11057 % o display: Specifies a connection to an X server; returned from
11060 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
11062 % o windows: Specifies a pointer to a XWindows structure.
11064 % o image: the image; returned from ReadImage.
11066 % o exception: return any errors or warnings in this structure.
11069 static MagickBooleanType XROIImage(Display *display,
11070 XResourceInfo *resource_info,XWindows *windows,Image **image,
11071 ExceptionInfo *exception)
11073 #define ApplyMenus 7
11123 "Contrast Stretch...",
11124 "Sigmoidal Contrast...",
11158 "Charcoal Draw...",
11161 *MiscellanyMenu[] =
11172 **Menus[ApplyMenus] =
11183 static const CommandType
11206 TransformCommands[] =
11210 RotateRightCommand,
11213 EnhanceCommands[] =
11221 ContrastStretchCommand,
11222 SigmoidalContrastCommand,
11230 EffectsCommands[] =
11234 ReduceNoiseCommand,
11253 CharcoalDrawCommand
11255 MiscellanyCommands[] =
11259 ShowPreviewCommand,
11260 ShowHistogramCommand,
11269 static const CommandType
11270 *Commands[ApplyMenus] =
11282 command[MaxTextExtent],
11283 text[MaxTextExtent];
11303 MagickProgressMonitor
11322 Map Command widget.
11324 (void) CloneString(&windows->command.name,"ROI");
11325 windows->command.data=0;
11326 (void) XCommandWidget(display,windows,ROIMenu,(XEvent *) NULL);
11327 (void) XMapRaised(display,windows->command.id);
11328 XClientMessage(display,windows->image.id,windows->im_protocols,
11329 windows->im_update_widget,CurrentTime);
11331 Track pointer until button 1 is pressed.
11333 XQueryPosition(display,windows->image.id,&x,&y);
11334 (void) XSelectInput(display,windows->image.id,
11335 windows->image.attributes.event_mask | PointerMotionMask);
11336 roi_info.x=(ssize_t) windows->image.x+x;
11337 roi_info.y=(ssize_t) windows->image.y+y;
11340 cursor=XCreateFontCursor(display,XC_fleur);
11341 state=DefaultState;
11344 if (IfMagickTrue(windows->info.mapped) )
11347 Display pointer position.
11349 (void) FormatLocaleString(text,MaxTextExtent," %+ld%+ld ",
11350 (long) roi_info.x,(long) roi_info.y);
11351 XInfoWidget(display,windows,text);
11354 Wait for next event.
11356 XScreenEvent(display,windows,&event,exception);
11357 if (event.xany.window == windows->command.id)
11360 Select a command from the Command widget.
11362 id=XCommandWidget(display,windows,ROIMenu,&event);
11365 switch (ROICommands[id])
11367 case ROIHelpCommand:
11369 XTextViewWidget(display,resource_info,windows,MagickFalse,
11370 "Help Viewer - Region of Interest",ImageROIHelp);
11373 case ROIDismissCommand:
11378 state|=EscapeState;
11387 switch (event.type)
11391 if (event.xbutton.button != Button1)
11393 if (event.xbutton.window != windows->image.id)
11396 Note first corner of region of interest rectangle-- exit loop.
11398 (void) XCheckDefineCursor(display,windows->image.id,cursor);
11399 roi_info.x=(ssize_t) windows->image.x+event.xbutton.x;
11400 roi_info.y=(ssize_t) windows->image.y+event.xbutton.y;
11404 case ButtonRelease:
11413 if (event.xkey.window != windows->image.id)
11416 Respond to a user key press.
11418 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
11419 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
11420 switch ((int) key_symbol)
11428 state|=EscapeState;
11435 XTextViewWidget(display,resource_info,windows,MagickFalse,
11436 "Help Viewer - Region of Interest",ImageROIHelp);
11441 (void) XBell(display,0);
11450 Map and unmap Info widget as text cursor crosses its boundaries.
11454 if (IfMagickTrue(windows->info.mapped) )
11456 if ((x < (int) (windows->info.x+windows->info.width)) &&
11457 (y < (int) (windows->info.y+windows->info.height)))
11458 (void) XWithdrawWindow(display,windows->info.id,
11459 windows->info.screen);
11462 if ((x > (int) (windows->info.x+windows->info.width)) ||
11463 (y > (int) (windows->info.y+windows->info.height)))
11464 (void) XMapWindow(display,windows->info.id);
11465 roi_info.x=(ssize_t) windows->image.x+x;
11466 roi_info.y=(ssize_t) windows->image.y+y;
11472 } while ((state & ExitState) == 0);
11473 (void) XSelectInput(display,windows->image.id,
11474 windows->image.attributes.event_mask);
11475 if ((state & EscapeState) != 0)
11478 User want to exit without region of interest.
11480 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
11481 (void) XFreeCursor(display,cursor);
11482 return(MagickTrue);
11484 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
11488 Size rectangle as pointer moves until the mouse button is released.
11490 x=(int) roi_info.x;
11491 y=(int) roi_info.y;
11494 state=DefaultState;
11497 highlight_info=roi_info;
11498 highlight_info.x=roi_info.x-windows->image.x;
11499 highlight_info.y=roi_info.y-windows->image.y;
11500 if ((highlight_info.width > 3) && (highlight_info.height > 3))
11503 Display info and draw region of interest rectangle.
11505 if (IfMagickFalse(windows->info.mapped) )
11506 (void) XMapWindow(display,windows->info.id);
11507 (void) FormatLocaleString(text,MaxTextExtent,
11508 " %.20gx%.20g%+.20g%+.20g",(double) roi_info.width,(double)
11509 roi_info.height,(double) roi_info.x,(double) roi_info.y);
11510 XInfoWidget(display,windows,text);
11511 XHighlightRectangle(display,windows->image.id,
11512 windows->image.highlight_context,&highlight_info);
11515 if (IfMagickTrue(windows->info.mapped) )
11516 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
11518 Wait for next event.
11520 XScreenEvent(display,windows,&event,exception);
11521 if ((highlight_info.width > 3) && (highlight_info.height > 3))
11522 XHighlightRectangle(display,windows->image.id,
11523 windows->image.highlight_context,&highlight_info);
11524 switch (event.type)
11528 roi_info.x=(ssize_t) windows->image.x+event.xbutton.x;
11529 roi_info.y=(ssize_t) windows->image.y+event.xbutton.y;
11532 case ButtonRelease:
11535 User has committed to region of interest rectangle.
11537 roi_info.x=(ssize_t) windows->image.x+event.xbutton.x;
11538 roi_info.y=(ssize_t) windows->image.y+event.xbutton.y;
11539 XSetCursorState(display,windows,MagickFalse);
11541 if (LocaleCompare(windows->command.name,"Apply") == 0)
11543 (void) CloneString(&windows->command.name,"Apply");
11544 windows->command.data=ApplyMenus;
11545 (void) XCommandWidget(display,windows,ApplyMenu,(XEvent *) NULL);
11552 roi_info.x=(ssize_t) windows->image.x+event.xmotion.x;
11553 roi_info.y=(ssize_t) windows->image.y+event.xmotion.y;
11558 if ((((int) roi_info.x != x) && ((int) roi_info.y != y)) ||
11559 ((state & ExitState) != 0))
11562 Check boundary conditions.
11564 if (roi_info.x < 0)
11567 if (roi_info.x > (ssize_t) windows->image.ximage->width)
11568 roi_info.x=(ssize_t) windows->image.ximage->width;
11569 if ((int) roi_info.x < x)
11570 roi_info.width=(unsigned int) (x-roi_info.x);
11573 roi_info.width=(unsigned int) (roi_info.x-x);
11574 roi_info.x=(ssize_t) x;
11576 if (roi_info.y < 0)
11579 if (roi_info.y > (ssize_t) windows->image.ximage->height)
11580 roi_info.y=(ssize_t) windows->image.ximage->height;
11581 if ((int) roi_info.y < y)
11582 roi_info.height=(unsigned int) (y-roi_info.y);
11585 roi_info.height=(unsigned int) (roi_info.y-y);
11586 roi_info.y=(ssize_t) y;
11589 } while ((state & ExitState) == 0);
11591 Wait for user to grab a corner of the rectangle or press return.
11593 state=DefaultState;
11594 command_type=NullCommand;
11597 (void) XMapWindow(display,windows->info.id);
11600 if (IfMagickTrue(windows->info.mapped) )
11603 Display pointer position.
11605 (void) FormatLocaleString(text,MaxTextExtent,
11606 " %.20gx%.20g%+.20g%+.20g",(double) roi_info.width,(double)
11607 roi_info.height,(double) roi_info.x,(double) roi_info.y);
11608 XInfoWidget(display,windows,text);
11610 highlight_info=roi_info;
11611 highlight_info.x=roi_info.x-windows->image.x;
11612 highlight_info.y=roi_info.y-windows->image.y;
11613 if ((highlight_info.width <= 3) || (highlight_info.height <= 3))
11615 state|=EscapeState;
11619 if ((state & UpdateRegionState) != 0)
11621 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
11622 switch (command_type)
11627 (void) XMagickCommand(display,resource_info,windows,command_type,
11634 Region of interest is relative to image configuration.
11636 progress_monitor=SetImageProgressMonitor(*image,
11637 (MagickProgressMonitor) NULL,(*image)->client_data);
11638 crop_info=roi_info;
11639 width=(unsigned int) (*image)->columns;
11640 height=(unsigned int) (*image)->rows;
11643 if (windows->image.crop_geometry != (char *) NULL)
11644 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,
11646 scale_factor=(double) width/windows->image.ximage->width;
11648 crop_info.x=(ssize_t) (scale_factor*crop_info.x+0.5);
11649 crop_info.width=(unsigned int) (scale_factor*crop_info.width+0.5);
11650 scale_factor=(double)
11651 height/windows->image.ximage->height;
11653 crop_info.y=(ssize_t) (scale_factor*crop_info.y+0.5);
11654 crop_info.height=(unsigned int)
11655 (scale_factor*crop_info.height+0.5);
11656 roi_image=CropImage(*image,&crop_info,exception);
11657 (void) SetImageProgressMonitor(*image,progress_monitor,
11658 (*image)->client_data);
11659 if (roi_image == (Image *) NULL)
11662 Apply image processing technique to the region of interest.
11664 windows->image.orphan=MagickTrue;
11665 (void) XMagickCommand(display,resource_info,windows,command_type,
11666 &roi_image,exception);
11667 progress_monitor=SetImageProgressMonitor(*image,
11668 (MagickProgressMonitor) NULL,(*image)->client_data);
11669 (void) XMagickCommand(display,resource_info,windows,
11670 SaveToUndoBufferCommand,image,exception);
11671 windows->image.orphan=MagickFalse;
11672 (void) CompositeImage(*image,roi_image,CopyCompositeOp,
11673 MagickTrue,crop_info.x,crop_info.y,exception);
11674 roi_image=DestroyImage(roi_image);
11675 (void) SetImageProgressMonitor(*image,progress_monitor,
11676 (*image)->client_data);
11680 if (command_type != InfoCommand)
11682 XConfigureImageColormap(display,resource_info,windows,*image,
11684 (void) XConfigureImage(display,resource_info,windows,*image,
11687 XCheckRefreshWindows(display,windows);
11688 XInfoWidget(display,windows,text);
11689 (void) XSetFunction(display,windows->image.highlight_context,
11691 state&=(~UpdateRegionState);
11693 XHighlightRectangle(display,windows->image.id,
11694 windows->image.highlight_context,&highlight_info);
11695 XScreenEvent(display,windows,&event,exception);
11696 if (event.xany.window == windows->command.id)
11699 Select a command from the Command widget.
11701 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
11702 command_type=NullCommand;
11703 id=XCommandWidget(display,windows,ApplyMenu,&event);
11706 (void) CopyMagickString(command,ApplyMenu[id],MaxTextExtent);
11707 command_type=ApplyCommands[id];
11708 if (id < ApplyMenus)
11711 Select a command from a pop-up menu.
11713 entry=XMenuWidget(display,windows,ApplyMenu[id],
11714 (const char **) Menus[id],command);
11717 (void) CopyMagickString(command,Menus[id][entry],
11719 command_type=Commands[id][entry];
11723 (void) XSetFunction(display,windows->image.highlight_context,
11725 XHighlightRectangle(display,windows->image.id,
11726 windows->image.highlight_context,&highlight_info);
11727 if (command_type == HelpCommand)
11729 (void) XSetFunction(display,windows->image.highlight_context,
11731 XTextViewWidget(display,resource_info,windows,MagickFalse,
11732 "Help Viewer - Region of Interest",ImageROIHelp);
11733 (void) XSetFunction(display,windows->image.highlight_context,
11737 if (command_type == QuitCommand)
11742 state|=EscapeState;
11746 if (command_type != NullCommand)
11747 state|=UpdateRegionState;
11750 XHighlightRectangle(display,windows->image.id,
11751 windows->image.highlight_context,&highlight_info);
11752 switch (event.type)
11756 x=windows->image.x;
11757 y=windows->image.y;
11758 if (event.xbutton.button != Button1)
11760 if (event.xbutton.window != windows->image.id)
11762 x=windows->image.x+event.xbutton.x;
11763 y=windows->image.y+event.xbutton.y;
11764 if ((x < (int) (roi_info.x+RoiDelta)) &&
11765 (x > (int) (roi_info.x-RoiDelta)) &&
11766 (y < (int) (roi_info.y+RoiDelta)) &&
11767 (y > (int) (roi_info.y-RoiDelta)))
11769 roi_info.x=(ssize_t) (roi_info.x+roi_info.width);
11770 roi_info.y=(ssize_t) (roi_info.y+roi_info.height);
11771 state|=UpdateConfigurationState;
11774 if ((x < (int) (roi_info.x+RoiDelta)) &&
11775 (x > (int) (roi_info.x-RoiDelta)) &&
11776 (y < (int) (roi_info.y+roi_info.height+RoiDelta)) &&
11777 (y > (int) (roi_info.y+roi_info.height-RoiDelta)))
11779 roi_info.x=(ssize_t) (roi_info.x+roi_info.width);
11780 state|=UpdateConfigurationState;
11783 if ((x < (int) (roi_info.x+roi_info.width+RoiDelta)) &&
11784 (x > (int) (roi_info.x+roi_info.width-RoiDelta)) &&
11785 (y < (int) (roi_info.y+RoiDelta)) &&
11786 (y > (int) (roi_info.y-RoiDelta)))
11788 roi_info.y=(ssize_t) (roi_info.y+roi_info.height);
11789 state|=UpdateConfigurationState;
11792 if ((x < (int) (roi_info.x+roi_info.width+RoiDelta)) &&
11793 (x > (int) (roi_info.x+roi_info.width-RoiDelta)) &&
11794 (y < (int) (roi_info.y+roi_info.height+RoiDelta)) &&
11795 (y > (int) (roi_info.y+roi_info.height-RoiDelta)))
11797 state|=UpdateConfigurationState;
11801 case ButtonRelease:
11803 if (event.xbutton.window == windows->pan.id)
11804 if ((highlight_info.x != crop_info.x-windows->image.x) ||
11805 (highlight_info.y != crop_info.y-windows->image.y))
11806 XHighlightRectangle(display,windows->image.id,
11807 windows->image.highlight_context,&highlight_info);
11808 (void) XSetSelectionOwner(display,XA_PRIMARY,windows->image.id,
11809 event.xbutton.time);
11814 if (event.xexpose.window == windows->image.id)
11815 if (event.xexpose.count == 0)
11817 event.xexpose.x=(int) highlight_info.x;
11818 event.xexpose.y=(int) highlight_info.y;
11819 event.xexpose.width=(int) highlight_info.width;
11820 event.xexpose.height=(int) highlight_info.height;
11821 XRefreshWindow(display,&windows->image,&event);
11823 if (event.xexpose.window == windows->info.id)
11824 if (event.xexpose.count == 0)
11825 XInfoWidget(display,windows,text);
11833 if (event.xkey.window != windows->image.id)
11836 Respond to a user key press.
11838 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
11839 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
11840 switch ((int) key_symbol)
11847 state|=EscapeState;
11856 roi_info.x=(ssize_t) (windows->image.width/2L-roi_info.width/2L);
11857 roi_info.y=(ssize_t) (windows->image.height/2L-
11858 roi_info.height/2L);
11890 (void) XSetFunction(display,windows->image.highlight_context,
11892 XTextViewWidget(display,resource_info,windows,MagickFalse,
11893 "Help Viewer - Region of Interest",ImageROIHelp);
11894 (void) XSetFunction(display,windows->image.highlight_context,
11900 command_type=XImageWindowCommand(display,resource_info,windows,
11901 event.xkey.state,key_symbol,image,exception);
11902 if (command_type != NullCommand)
11903 state|=UpdateRegionState;
11907 (void) XSetSelectionOwner(display,XA_PRIMARY,windows->image.id,
11915 if (event.xbutton.window != windows->image.id)
11918 Map and unmap Info widget as text cursor crosses its boundaries.
11922 if (IfMagickTrue(windows->info.mapped) )
11924 if ((x < (int) (windows->info.x+windows->info.width)) &&
11925 (y < (int) (windows->info.y+windows->info.height)))
11926 (void) XWithdrawWindow(display,windows->info.id,
11927 windows->info.screen);
11930 if ((x > (int) (windows->info.x+windows->info.width)) ||
11931 (y > (int) (windows->info.y+windows->info.height)))
11932 (void) XMapWindow(display,windows->info.id);
11933 roi_info.x=(ssize_t) windows->image.x+event.xmotion.x;
11934 roi_info.y=(ssize_t) windows->image.y+event.xmotion.y;
11937 case SelectionRequest:
11942 XSelectionRequestEvent
11946 Set primary selection.
11948 (void) FormatLocaleString(text,MaxTextExtent,
11949 "%.20gx%.20g%+.20g%+.20g",(double) roi_info.width,(double)
11950 roi_info.height,(double) roi_info.x,(double) roi_info.y);
11951 request=(&(event.xselectionrequest));
11952 (void) XChangeProperty(request->display,request->requestor,
11953 request->property,request->target,8,PropModeReplace,
11954 (unsigned char *) text,(int) strlen(text));
11955 notify.type=SelectionNotify;
11956 notify.display=request->display;
11957 notify.requestor=request->requestor;
11958 notify.selection=request->selection;
11959 notify.target=request->target;
11960 notify.time=request->time;
11961 if (request->property == None)
11962 notify.property=request->target;
11964 notify.property=request->property;
11965 (void) XSendEvent(request->display,request->requestor,False,0,
11966 (XEvent *) ¬ify);
11971 if ((state & UpdateConfigurationState) != 0)
11973 (void) XPutBackEvent(display,&event);
11974 (void) XCheckDefineCursor(display,windows->image.id,cursor);
11977 } while ((state & ExitState) == 0);
11978 } while ((state & ExitState) == 0);
11979 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
11980 XSetCursorState(display,windows,MagickFalse);
11981 if ((state & EscapeState) != 0)
11982 return(MagickTrue);
11983 return(MagickTrue);
11987 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
11991 + X R o t a t e I m a g e %
11995 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
11997 % XRotateImage() rotates the X image. If the degrees parameter if zero, the
11998 % rotation angle is computed from the slope of a line drawn by the user.
12000 % The format of the XRotateImage method is:
12002 % MagickBooleanType XRotateImage(Display *display,
12003 % XResourceInfo *resource_info,XWindows *windows,double degrees,
12004 % Image **image,ExceptionInfo *exception)
12006 % A description of each parameter follows:
12008 % o display: Specifies a connection to an X server; returned from
12011 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
12013 % o windows: Specifies a pointer to a XWindows structure.
12015 % o degrees: Specifies the number of degrees to rotate the image.
12017 % o image: the image.
12019 % o exception: return any errors or warnings in this structure.
12022 static MagickBooleanType XRotateImage(Display *display,
12023 XResourceInfo *resource_info,XWindows *windows,double degrees,Image **image,
12024 ExceptionInfo *exception)
12037 direction = HorizontalRotateCommand;
12039 static const ModeType
12040 DirectionCommands[] =
12042 HorizontalRotateCommand,
12043 VerticalRotateCommand
12047 RotateColorCommand,
12048 RotateDirectionCommand,
12050 RotateDismissCommand
12053 static unsigned int
12057 command[MaxTextExtent],
12058 text[MaxTextExtent];
12069 normalized_degrees;
12079 if (degrees == 0.0)
12094 Map Command widget.
12096 (void) CloneString(&windows->command.name,"Rotate");
12097 windows->command.data=2;
12098 (void) XCommandWidget(display,windows,RotateMenu,(XEvent *) NULL);
12099 (void) XMapRaised(display,windows->command.id);
12100 XClientMessage(display,windows->image.id,windows->im_protocols,
12101 windows->im_update_widget,CurrentTime);
12103 Wait for first button press.
12105 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
12106 XQueryPosition(display,windows->image.id,&x,&y);
12111 state=DefaultState;
12114 XHighlightLine(display,windows->image.id,
12115 windows->image.highlight_context,&rotate_info);
12117 Wait for next event.
12119 XScreenEvent(display,windows,&event,exception);
12120 XHighlightLine(display,windows->image.id,
12121 windows->image.highlight_context,&rotate_info);
12122 if (event.xany.window == windows->command.id)
12125 Select a command from the Command widget.
12127 id=XCommandWidget(display,windows,RotateMenu,&event);
12130 (void) XSetFunction(display,windows->image.highlight_context,
12132 switch (RotateCommands[id])
12134 case RotateColorCommand:
12137 *ColorMenu[MaxNumberPens];
12146 Initialize menu selections.
12148 for (i=0; i < (int) (MaxNumberPens-2); i++)
12149 ColorMenu[i]=resource_info->pen_colors[i];
12150 ColorMenu[MaxNumberPens-2]="Browser...";
12151 ColorMenu[MaxNumberPens-1]=(const char *) NULL;
12153 Select a pen color from the pop-up menu.
12155 pen_number=XMenuWidget(display,windows,RotateMenu[id],
12156 (const char **) ColorMenu,command);
12157 if (pen_number < 0)
12159 if (pen_number == (MaxNumberPens-2))
12162 color_name[MaxTextExtent] = "gray";
12165 Select a pen color from a dialog.
12167 resource_info->pen_colors[pen_number]=color_name;
12168 XColorBrowserWidget(display,windows,"Select",color_name);
12169 if (*color_name == '\0')
12175 (void) XParseColor(display,windows->map_info->colormap,
12176 resource_info->pen_colors[pen_number],&color);
12177 XBestPixel(display,windows->map_info->colormap,(XColor *) NULL,
12178 (unsigned int) MaxColors,&color);
12179 windows->pixel_info->pen_colors[pen_number]=color;
12180 pen_id=(unsigned int) pen_number;
12183 case RotateDirectionCommand:
12194 Select a command from the pop-up menu.
12196 id=XMenuWidget(display,windows,RotateMenu[id],
12197 Directions,command);
12199 direction=DirectionCommands[id];
12202 case RotateHelpCommand:
12204 XTextViewWidget(display,resource_info,windows,MagickFalse,
12205 "Help Viewer - Image Rotation",ImageRotateHelp);
12208 case RotateDismissCommand:
12213 state|=EscapeState;
12220 (void) XSetFunction(display,windows->image.highlight_context,
12224 switch (event.type)
12228 if (event.xbutton.button != Button1)
12230 if (event.xbutton.window != windows->image.id)
12235 (void) XSetFunction(display,windows->image.highlight_context,
12237 rotate_info.x1=event.xbutton.x;
12238 rotate_info.y1=event.xbutton.y;
12242 case ButtonRelease:
12249 command[MaxTextExtent];
12254 if (event.xkey.window != windows->image.id)
12257 Respond to a user key press.
12259 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
12260 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
12261 switch ((int) key_symbol)
12269 state|=EscapeState;
12276 (void) XSetFunction(display,windows->image.highlight_context,
12278 XTextViewWidget(display,resource_info,windows,MagickFalse,
12279 "Help Viewer - Image Rotation",ImageRotateHelp);
12280 (void) XSetFunction(display,windows->image.highlight_context,
12286 (void) XBell(display,0);
12294 rotate_info.x1=event.xmotion.x;
12295 rotate_info.y1=event.xmotion.y;
12298 rotate_info.x2=rotate_info.x1;
12299 rotate_info.y2=rotate_info.y1;
12300 if (direction == HorizontalRotateCommand)
12301 rotate_info.x2+=32;
12303 rotate_info.y2-=32;
12304 } while ((state & ExitState) == 0);
12305 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
12306 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
12307 if ((state & EscapeState) != 0)
12308 return(MagickTrue);
12310 Draw line as pointer moves until the mouse button is released.
12313 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
12314 state=DefaultState;
12320 Display info and draw rotation line.
12322 if (IfMagickFalse(windows->info.mapped) )
12323 (void) XMapWindow(display,windows->info.id);
12324 (void) FormatLocaleString(text,MaxTextExtent," %g",
12325 direction == VerticalRotateCommand ? degrees-90.0 : degrees);
12326 XInfoWidget(display,windows,text);
12327 XHighlightLine(display,windows->image.id,
12328 windows->image.highlight_context,&rotate_info);
12331 if (IfMagickTrue(windows->info.mapped) )
12332 (void) XWithdrawWindow(display,windows->info.id,
12333 windows->info.screen);
12335 Wait for next event.
12337 XScreenEvent(display,windows,&event,exception);
12339 XHighlightLine(display,windows->image.id,
12340 windows->image.highlight_context,&rotate_info);
12341 switch (event.type)
12345 case ButtonRelease:
12348 User has committed to rotation line.
12350 rotate_info.x2=event.xbutton.x;
12351 rotate_info.y2=event.xbutton.y;
12359 rotate_info.x2=event.xmotion.x;
12360 rotate_info.y2=event.xmotion.y;
12366 Check boundary conditions.
12368 if (rotate_info.x2 < 0)
12371 if (rotate_info.x2 > (int) windows->image.width)
12372 rotate_info.x2=(short) windows->image.width;
12373 if (rotate_info.y2 < 0)
12376 if (rotate_info.y2 > (int) windows->image.height)
12377 rotate_info.y2=(short) windows->image.height;
12379 Compute rotation angle from the slope of the line.
12382 distance=(unsigned int)
12383 ((rotate_info.x2-rotate_info.x1+1)*(rotate_info.x2-rotate_info.x1+1))+
12384 ((rotate_info.y2-rotate_info.y1+1)*(rotate_info.y2-rotate_info.y1+1));
12386 degrees=RadiansToDegrees(-atan2((double) (rotate_info.y2-
12387 rotate_info.y1),(double) (rotate_info.x2-rotate_info.x1)));
12388 } while ((state & ExitState) == 0);
12389 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
12390 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
12392 return(MagickTrue);
12394 if (direction == VerticalRotateCommand)
12396 if (degrees == 0.0)
12397 return(MagickTrue);
12401 normalized_degrees=degrees;
12402 while (normalized_degrees < -45.0)
12403 normalized_degrees+=360.0;
12404 for (rotations=0; normalized_degrees > 45.0; rotations++)
12405 normalized_degrees-=90.0;
12406 if (normalized_degrees != 0.0)
12407 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image,
12409 XSetCursorState(display,windows,MagickTrue);
12410 XCheckRefreshWindows(display,windows);
12411 (*image)->background_color.red=(double) ScaleShortToQuantum(
12412 windows->pixel_info->pen_colors[pen_id].red);
12413 (*image)->background_color.green=(double) ScaleShortToQuantum(
12414 windows->pixel_info->pen_colors[pen_id].green);
12415 (*image)->background_color.blue=(double) ScaleShortToQuantum(
12416 windows->pixel_info->pen_colors[pen_id].blue);
12417 rotate_image=RotateImage(*image,degrees,exception);
12418 XSetCursorState(display,windows,MagickFalse);
12419 if (rotate_image == (Image *) NULL)
12420 return(MagickFalse);
12421 *image=DestroyImage(*image);
12422 *image=rotate_image;
12423 if (windows->image.crop_geometry != (char *) NULL)
12426 Rotate crop geometry.
12428 width=(unsigned int) (*image)->columns;
12429 height=(unsigned int) (*image)->rows;
12430 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
12431 switch (rotations % 4)
12441 (void) FormatLocaleString(windows->image.crop_geometry,MaxTextExtent,
12442 "%ux%u%+d%+d",height,width,(int) (*image)->columns-
12449 Rotate 180 degrees.
12451 (void) FormatLocaleString(windows->image.crop_geometry,MaxTextExtent,
12452 "%ux%u%+d%+d",width,height,(int) width-x,(int) height-y);
12458 Rotate 270 degrees.
12460 (void) FormatLocaleString(windows->image.crop_geometry,MaxTextExtent,
12461 "%ux%u%+d%+d",height,width,y,(int) (*image)->rows-(int) width-x);
12466 if (IfMagickTrue(windows->image.orphan) )
12467 return(MagickTrue);
12468 if (normalized_degrees != 0.0)
12471 Update image colormap.
12473 windows->image.window_changes.width=(int) (*image)->columns;
12474 windows->image.window_changes.height=(int) (*image)->rows;
12475 if (windows->image.crop_geometry != (char *) NULL)
12478 Obtain dimensions of image from crop geometry.
12480 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,
12482 windows->image.window_changes.width=(int) width;
12483 windows->image.window_changes.height=(int) height;
12485 XConfigureImageColormap(display,resource_info,windows,*image,exception);
12488 if (((rotations % 4) == 1) || ((rotations % 4) == 3))
12490 windows->image.window_changes.width=windows->image.ximage->height;
12491 windows->image.window_changes.height=windows->image.ximage->width;
12494 Update image configuration.
12496 (void) XConfigureImage(display,resource_info,windows,*image,exception);
12497 return(MagickTrue);
12501 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12505 + X S a v e I m a g e %
12509 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12511 % XSaveImage() saves an image to a file.
12513 % The format of the XSaveImage method is:
12515 % MagickBooleanType XSaveImage(Display *display,
12516 % XResourceInfo *resource_info,XWindows *windows,Image *image,
12517 % ExceptionInfo *exception)
12519 % A description of each parameter follows:
12521 % o display: Specifies a connection to an X server; returned from
12524 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
12526 % o windows: Specifies a pointer to a XWindows structure.
12528 % o image: the image.
12530 % o exception: return any errors or warnings in this structure.
12533 static MagickBooleanType XSaveImage(Display *display,
12534 XResourceInfo *resource_info,XWindows *windows,Image *image,
12535 ExceptionInfo *exception)
12538 filename[MaxTextExtent],
12539 geometry[MaxTextExtent];
12551 Request file name from user.
12553 if (resource_info->write_filename != (char *) NULL)
12554 (void) CopyMagickString(filename,resource_info->write_filename,
12559 path[MaxTextExtent];
12564 GetPathComponent(image->filename,HeadPath,path);
12565 GetPathComponent(image->filename,TailPath,filename);
12568 status=chdir(path);
12570 (void) ThrowMagickException(exception,GetMagickModule(),
12571 FileOpenError,"UnableToOpenFile","%s",path);
12574 XFileBrowserWidget(display,windows,"Save",filename);
12575 if (*filename == '\0')
12576 return(MagickTrue);
12577 if (IfMagickTrue(IsPathAccessible(filename)) )
12583 File exists-- seek user's permission before overwriting.
12585 status=XConfirmWidget(display,windows,"Overwrite",filename);
12587 return(MagickTrue);
12589 image_info=CloneImageInfo(resource_info->image_info);
12590 (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
12591 (void) SetImageInfo(image_info,1,exception);
12592 if ((LocaleCompare(image_info->magick,"JPEG") == 0) ||
12593 (LocaleCompare(image_info->magick,"JPG") == 0))
12596 quality[MaxTextExtent];
12602 Request JPEG quality from user.
12604 (void) FormatLocaleString(quality,MaxTextExtent,"%.20g",(double)
12606 status=XDialogWidget(display,windows,"Save","Enter JPEG quality:",
12608 if (*quality == '\0')
12609 return(MagickTrue);
12610 image->quality=StringToUnsignedLong(quality);
12611 image_info->interlace=status != 0 ? NoInterlace : PlaneInterlace;
12613 if ((LocaleCompare(image_info->magick,"EPS") == 0) ||
12614 (LocaleCompare(image_info->magick,"PDF") == 0) ||
12615 (LocaleCompare(image_info->magick,"PS") == 0) ||
12616 (LocaleCompare(image_info->magick,"PS2") == 0))
12619 geometry[MaxTextExtent];
12622 Request page geometry from user.
12624 (void) CopyMagickString(geometry,PSPageGeometry,MaxTextExtent);
12625 if (LocaleCompare(image_info->magick,"PDF") == 0)
12626 (void) CopyMagickString(geometry,PSPageGeometry,MaxTextExtent);
12627 if (image_info->page != (char *) NULL)
12628 (void) CopyMagickString(geometry,image_info->page,MaxTextExtent);
12629 XListBrowserWidget(display,windows,&windows->widget,PageSizes,"Select",
12630 "Select page geometry:",geometry);
12631 if (*geometry != '\0')
12632 image_info->page=GetPageGeometry(geometry);
12635 Apply image transforms.
12637 XSetCursorState(display,windows,MagickTrue);
12638 XCheckRefreshWindows(display,windows);
12639 save_image=CloneImage(image,0,0,MagickTrue,exception);
12640 if (save_image == (Image *) NULL)
12641 return(MagickFalse);
12642 (void) FormatLocaleString(geometry,MaxTextExtent,"%dx%d!",
12643 windows->image.ximage->width,windows->image.ximage->height);
12644 (void) TransformImage(&save_image,windows->image.crop_geometry,geometry,
12649 (void) CopyMagickString(save_image->filename,filename,MaxTextExtent);
12650 status=WriteImage(image_info,save_image,exception);
12651 if (IfMagickTrue(status) )
12652 image->taint=MagickFalse;
12653 save_image=DestroyImage(save_image);
12654 image_info=DestroyImageInfo(image_info);
12655 XSetCursorState(display,windows,MagickFalse);
12656 return(IsMagickTrue(status));
12660 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12664 + X S c r e e n E v e n t %
12668 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12670 % XScreenEvent() handles global events associated with the Pan and Magnify
12673 % The format of the XScreenEvent function is:
12675 % void XScreenEvent(Display *display,XWindows *windows,XEvent *event,
12676 % ExceptionInfo *exception)
12678 % A description of each parameter follows:
12680 % o display: Specifies a pointer to the Display structure; returned from
12683 % o windows: Specifies a pointer to a XWindows structure.
12685 % o event: Specifies a pointer to a X11 XEvent structure.
12687 % o exception: return any errors or warnings in this structure.
12691 #if defined(__cplusplus) || defined(c_plusplus)
12695 static int XPredicate(Display *magick_unused(display),XEvent *event,char *data)
12700 windows=(XWindows *) data;
12701 if ((event->type == ClientMessage) &&
12702 (event->xclient.window == windows->image.id))
12703 return(MagickFalse);
12704 return(MagickTrue);
12707 #if defined(__cplusplus) || defined(c_plusplus)
12711 static void XScreenEvent(Display *display,XWindows *windows,XEvent *event,
12712 ExceptionInfo *exception)
12718 (void) XIfEvent(display,event,XPredicate,(char *) windows);
12719 if (event->xany.window == windows->command.id)
12721 switch (event->type)
12724 case ButtonRelease:
12726 if ((event->xbutton.button == Button3) &&
12727 (event->xbutton.state & Mod1Mask))
12730 Convert Alt-Button3 to Button2.
12732 event->xbutton.button=Button2;
12733 event->xbutton.state&=(~Mod1Mask);
12735 if (event->xbutton.window == windows->backdrop.id)
12737 (void) XSetInputFocus(display,event->xbutton.window,RevertToParent,
12738 event->xbutton.time);
12741 if (event->xbutton.window == windows->pan.id)
12743 XPanImage(display,windows,event,exception);
12746 if (event->xbutton.window == windows->image.id)
12747 if (event->xbutton.button == Button2)
12750 Update magnified image.
12752 x=event->xbutton.x;
12753 y=event->xbutton.y;
12757 if (x >= (int) windows->image.width)
12758 x=(int) (windows->image.width-1);
12759 windows->magnify.x=(int) windows->image.x+x;
12763 if (y >= (int) windows->image.height)
12764 y=(int) (windows->image.height-1);
12765 windows->magnify.y=windows->image.y+y;
12766 if (IfMagickFalse(windows->magnify.mapped) )
12767 (void) XMapRaised(display,windows->magnify.id);
12768 XMakeMagnifyImage(display,windows,exception);
12769 if (event->type == ButtonRelease)
12770 (void) XWithdrawWindow(display,windows->info.id,
12771 windows->info.screen);
12776 case ClientMessage:
12779 If client window delete message, exit.
12781 if (event->xclient.message_type != windows->wm_protocols)
12783 if (*event->xclient.data.l != (long) windows->wm_delete_window)
12785 if (event->xclient.window == windows->magnify.id)
12787 (void) XWithdrawWindow(display,windows->magnify.id,
12788 windows->magnify.screen);
12793 case ConfigureNotify:
12795 if (event->xconfigure.window == windows->magnify.id)
12801 Magnify window has a new configuration.
12803 windows->magnify.width=(unsigned int) event->xconfigure.width;
12804 windows->magnify.height=(unsigned int) event->xconfigure.height;
12805 if (IfMagickFalse(windows->magnify.mapped) )
12808 while ((int) magnify <= event->xconfigure.width)
12810 while ((int) magnify <= event->xconfigure.height)
12813 if (((int) magnify != event->xconfigure.width) ||
12814 ((int) magnify != event->xconfigure.height))
12819 window_changes.width=(int) magnify;
12820 window_changes.height=(int) magnify;
12821 (void) XReconfigureWMWindow(display,windows->magnify.id,
12822 windows->magnify.screen,(unsigned int) (CWWidth | CWHeight),
12826 XMakeMagnifyImage(display,windows,exception);
12833 if (event->xexpose.window == windows->image.id)
12835 XRefreshWindow(display,&windows->image,event);
12838 if (event->xexpose.window == windows->pan.id)
12839 if (event->xexpose.count == 0)
12841 XDrawPanRectangle(display,windows);
12844 if (event->xexpose.window == windows->magnify.id)
12845 if (event->xexpose.count == 0)
12847 XMakeMagnifyImage(display,windows,exception);
12855 command[MaxTextExtent];
12860 if (event->xkey.window != windows->magnify.id)
12863 Respond to a user key press.
12865 (void) XLookupString((XKeyEvent *) &event->xkey,command,(int)
12866 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
12867 XMagnifyWindowCommand(display,windows,event->xkey.state,key_symbol,
12873 if (event->xmap.window == windows->magnify.id)
12875 windows->magnify.mapped=MagickTrue;
12876 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
12879 if (event->xmap.window == windows->info.id)
12881 windows->info.mapped=MagickTrue;
12888 while (XCheckMaskEvent(display,ButtonMotionMask,event)) ;
12889 if (event->xmotion.window == windows->image.id)
12890 if (IfMagickTrue(windows->magnify.mapped) )
12893 Update magnified image.
12895 x=event->xmotion.x;
12896 y=event->xmotion.y;
12900 if (x >= (int) windows->image.width)
12901 x=(int) (windows->image.width-1);
12902 windows->magnify.x=(int) windows->image.x+x;
12906 if (y >= (int) windows->image.height)
12907 y=(int) (windows->image.height-1);
12908 windows->magnify.y=windows->image.y+y;
12909 XMakeMagnifyImage(display,windows,exception);
12915 if (event->xunmap.window == windows->magnify.id)
12917 windows->magnify.mapped=MagickFalse;
12920 if (event->xunmap.window == windows->info.id)
12922 windows->info.mapped=MagickFalse;
12933 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12937 + X S e t C r o p G e o m e t r y %
12941 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12943 % XSetCropGeometry() accepts a cropping geometry relative to the Image window
12944 % and translates it to a cropping geometry relative to the image.
12946 % The format of the XSetCropGeometry method is:
12948 % void XSetCropGeometry(Display *display,XWindows *windows,
12949 % RectangleInfo *crop_info,Image *image)
12951 % A description of each parameter follows:
12953 % o display: Specifies a connection to an X server; returned from
12956 % o windows: Specifies a pointer to a XWindows structure.
12958 % o crop_info: A pointer to a RectangleInfo that defines a region of the
12959 % Image window to crop.
12961 % o image: the image.
12964 static void XSetCropGeometry(Display *display,XWindows *windows,
12965 RectangleInfo *crop_info,Image *image)
12968 text[MaxTextExtent];
12981 if (IfMagickTrue(windows->info.mapped) )
12984 Display info on cropping rectangle.
12986 (void) FormatLocaleString(text,MaxTextExtent," %.20gx%.20g%+.20g%+.20g",
12987 (double) crop_info->width,(double) crop_info->height,(double)
12988 crop_info->x,(double) crop_info->y);
12989 XInfoWidget(display,windows,text);
12992 Cropping geometry is relative to any previous crop geometry.
12996 width=(unsigned int) image->columns;
12997 height=(unsigned int) image->rows;
12998 if (windows->image.crop_geometry != (char *) NULL)
12999 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
13001 windows->image.crop_geometry=AcquireString((char *) NULL);
13003 Define the crop geometry string from the cropping rectangle.
13005 scale_factor=(double) width/windows->image.ximage->width;
13006 if (crop_info->x > 0)
13007 x+=(int) (scale_factor*crop_info->x+0.5);
13008 width=(unsigned int) (scale_factor*crop_info->width+0.5);
13011 scale_factor=(double) height/windows->image.ximage->height;
13012 if (crop_info->y > 0)
13013 y+=(int) (scale_factor*crop_info->y+0.5);
13014 height=(unsigned int) (scale_factor*crop_info->height+0.5);
13017 (void) FormatLocaleString(windows->image.crop_geometry,MaxTextExtent,
13018 "%ux%u%+d%+d",width,height,x,y);
13022 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13026 + X T i l e I m a g e %
13030 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13032 % XTileImage() loads or deletes a selected tile from a visual image directory.
13033 % The load or delete command is chosen from a menu.
13035 % The format of the XTileImage method is:
13037 % Image *XTileImage(Display *display,XResourceInfo *resource_info,
13038 % XWindows *windows,Image *image,XEvent *event,ExceptionInfo *exception)
13040 % A description of each parameter follows:
13042 % o tile_image: XTileImage reads or deletes the tile image
13043 % and returns it. A null image is returned if an error occurs.
13045 % o display: Specifies a connection to an X server; returned from
13048 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
13050 % o windows: Specifies a pointer to a XWindows structure.
13052 % o image: the image; returned from ReadImage.
13054 % o event: Specifies a pointer to a XEvent structure. If it is NULL,
13055 % the entire image is refreshed.
13057 % o exception: return any errors or warnings in this structure.
13060 static Image *XTileImage(Display *display,XResourceInfo *resource_info,
13061 XWindows *windows,Image *image,XEvent *event,ExceptionInfo *exception)
13074 static const ModeType
13085 command[MaxTextExtent],
13086 filename[MaxTextExtent];
13113 Tile image is relative to montage image configuration.
13117 width=(unsigned int) image->columns;
13118 height=(unsigned int) image->rows;
13119 if (windows->image.crop_geometry != (char *) NULL)
13120 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
13121 scale_factor=(double) width/windows->image.ximage->width;
13122 event->xbutton.x+=windows->image.x;
13123 event->xbutton.x=(int) (scale_factor*event->xbutton.x+x+0.5);
13124 scale_factor=(double) height/windows->image.ximage->height;
13125 event->xbutton.y+=windows->image.y;
13126 event->xbutton.y=(int) (scale_factor*event->xbutton.y+y+0.5);
13128 Determine size and location of each tile in the visual image directory.
13130 width=(unsigned int) image->columns;
13131 height=(unsigned int) image->rows;
13134 (void) XParseGeometry(image->montage,&x,&y,&width,&height);
13135 tile=((event->xbutton.y-y)/height)*(((int) image->columns-x)/width)+
13136 (event->xbutton.x-x)/width;
13140 Button press is outside any tile.
13142 (void) XBell(display,0);
13143 return((Image *) NULL);
13146 Determine file name from the tile directory.
13148 p=image->directory;
13149 for (i=tile; (i != 0) && (*p != '\0'); )
13158 Button press is outside any tile.
13160 (void) XBell(display,0);
13161 return((Image *) NULL);
13164 Select a command from the pop-up menu.
13166 id=XMenuWidget(display,windows,"Tile Verb",VerbMenu,command);
13168 return((Image *) NULL);
13170 while ((*q != '\n') && (*q != '\0'))
13172 (void) CopyMagickString(filename,p,(size_t) (q-p+1));
13174 Perform command for the selected tile.
13176 XSetCursorState(display,windows,MagickTrue);
13177 XCheckRefreshWindows(display,windows);
13178 tile_image=NewImageList();
13179 switch (TileCommands[id])
13181 case TileLoadCommand:
13186 XCheckRefreshWindows(display,windows);
13187 (void) CopyMagickString(resource_info->image_info->magick,"MIFF",
13189 (void) CopyMagickString(resource_info->image_info->filename,filename,
13191 tile_image=ReadImage(resource_info->image_info,exception);
13192 CatchException(exception);
13193 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
13196 case TileNextCommand:
13199 Display next image.
13201 XClientMessage(display,windows->image.id,windows->im_protocols,
13202 windows->im_next_image,CurrentTime);
13205 case TileFormerCommand:
13208 Display former image.
13210 XClientMessage(display,windows->image.id,windows->im_protocols,
13211 windows->im_former_image,CurrentTime);
13214 case TileDeleteCommand:
13219 if (IfMagickFalse(IsPathAccessible(filename)) )
13221 XNoticeWidget(display,windows,"Image file does not exist:",filename);
13224 status=XConfirmWidget(display,windows,"Really delete tile",filename);
13227 status=ShredFile(filename);
13228 if (IfMagickTrue(status) )
13230 XNoticeWidget(display,windows,"Unable to delete image file:",
13235 case TileUpdateCommand:
13251 Ensure all the images exist.
13254 GetPixelInfo(image,&pixel);
13255 for (p=image->directory; *p != '\0'; p++)
13261 while ((*q != '\n') && (*q != '\0'))
13263 (void) CopyMagickString(filename,p,(size_t) (q-p+1));
13265 if (IfMagickTrue(IsPathAccessible(filename)) )
13271 Overwrite tile with background color.
13273 x_offset=(int) (width*(tile % (((int) image->columns-x)/width))+x);
13274 y_offset=(int) (height*(tile/(((int) image->columns-x)/width))+y);
13275 image_view=AcquireAuthenticCacheView(image,exception);
13276 (void) GetOneCacheViewVirtualPixelInfo(image_view,0,0,&pixel,exception);
13277 for (i=0; i < (int) height; i++)
13279 s=GetCacheViewAuthenticPixels(image_view,(ssize_t) x_offset,(ssize_t)
13280 y_offset+i,width,1,exception);
13281 if (s == (Quantum *) NULL)
13283 for (j=0; j < (int) width; j++)
13285 SetPixelInfoPixel(image,&pixel,s);
13286 s+=GetPixelChannels(image);
13288 if (IfMagickFalse(SyncCacheViewAuthenticPixels(image_view,exception)) )
13291 image_view=DestroyCacheView(image_view);
13294 windows->image.window_changes.width=(int) image->columns;
13295 windows->image.window_changes.height=(int) image->rows;
13296 XConfigureImageColormap(display,resource_info,windows,image,exception);
13297 (void) XConfigureImage(display,resource_info,windows,image,exception);
13303 XSetCursorState(display,windows,MagickFalse);
13304 return(tile_image);
13308 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13312 + X T r a n s l a t e I m a g e %
13316 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13318 % XTranslateImage() translates the image within an Image window by one pixel
13319 % as specified by the key symbol. If the image has a montage string the
13320 % translation is respect to the width and height contained within the string.
13322 % The format of the XTranslateImage method is:
13324 % void XTranslateImage(Display *display,XWindows *windows,
13325 % Image *image,const KeySym key_symbol)
13327 % A description of each parameter follows:
13329 % o display: Specifies a connection to an X server; returned from
13332 % o windows: Specifies a pointer to a XWindows structure.
13334 % o image: the image.
13336 % o key_symbol: Specifies a KeySym which indicates which side of the image
13340 static void XTranslateImage(Display *display,XWindows *windows,
13341 Image *image,const KeySym key_symbol)
13344 text[MaxTextExtent];
13355 User specified a pan position offset.
13357 x_offset=windows->image.width;
13358 y_offset=windows->image.height;
13359 if (image->montage != (char *) NULL)
13360 (void) XParseGeometry(image->montage,&x,&y,&x_offset,&y_offset);
13361 switch ((int) key_symbol)
13366 windows->image.x=(int) windows->image.width/2;
13367 windows->image.y=(int) windows->image.height/2;
13373 windows->image.x-=x_offset;
13380 windows->image.y-=y_offset;
13386 windows->image.x+=x_offset;
13393 windows->image.y+=y_offset;
13400 Check boundary conditions.
13402 if (windows->image.x < 0)
13403 windows->image.x=0;
13405 if ((int) (windows->image.x+windows->image.width) >
13406 windows->image.ximage->width)
13407 windows->image.x=(int) windows->image.ximage->width-windows->image.width;
13408 if (windows->image.y < 0)
13409 windows->image.y=0;
13411 if ((int) (windows->image.y+windows->image.height) >
13412 windows->image.ximage->height)
13413 windows->image.y=(int) windows->image.ximage->height-windows->image.height;
13415 Refresh Image window.
13417 (void) FormatLocaleString(text,MaxTextExtent," %ux%u%+d%+d ",
13418 windows->image.width,windows->image.height,windows->image.x,
13420 XInfoWidget(display,windows,text);
13421 XCheckRefreshWindows(display,windows);
13422 XDrawPanRectangle(display,windows);
13423 XRefreshWindow(display,&windows->image,(XEvent *) NULL);
13424 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
13428 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13432 + X T r i m I m a g e %
13436 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13438 % XTrimImage() trims the edges from the Image window.
13440 % The format of the XTrimImage method is:
13442 % MagickBooleanType XTrimImage(Display *display,
13443 % XResourceInfo *resource_info,XWindows *windows,Image *image,
13444 % ExceptionInfo *exception)
13446 % A description of each parameter follows:
13448 % o display: Specifies a connection to an X server; returned from
13451 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
13453 % o windows: Specifies a pointer to a XWindows structure.
13455 % o image: the image.
13457 % o exception: return any errors or warnings in this structure.
13460 static MagickBooleanType XTrimImage(Display *display,
13461 XResourceInfo *resource_info,XWindows *windows,Image *image,
13462 ExceptionInfo *exception)
13476 Trim edges from image.
13478 XSetCursorState(display,windows,MagickTrue);
13479 XCheckRefreshWindows(display,windows);
13481 Crop the left edge.
13483 background=XGetPixel(windows->image.ximage,0,0);
13484 trim_info.width=(size_t) windows->image.ximage->width;
13485 for (x=0; x < windows->image.ximage->width; x++)
13487 for (y=0; y < windows->image.ximage->height; y++)
13489 pixel=XGetPixel(windows->image.ximage,x,y);
13490 if (pixel != background)
13493 if (y < windows->image.ximage->height)
13496 trim_info.x=(ssize_t) x;
13497 if (trim_info.x == (ssize_t) windows->image.ximage->width)
13499 XSetCursorState(display,windows,MagickFalse);
13500 return(MagickFalse);
13503 Crop the right edge.
13505 background=XGetPixel(windows->image.ximage,windows->image.ximage->width-1,0);
13506 for (x=windows->image.ximage->width-1; x != 0; x--)
13508 for (y=0; y < windows->image.ximage->height; y++)
13510 pixel=XGetPixel(windows->image.ximage,x,y);
13511 if (pixel != background)
13514 if (y < windows->image.ximage->height)
13517 trim_info.width=(size_t) (x-trim_info.x+1);
13521 background=XGetPixel(windows->image.ximage,0,0);
13522 trim_info.height=(size_t) windows->image.ximage->height;
13523 for (y=0; y < windows->image.ximage->height; y++)
13525 for (x=0; x < windows->image.ximage->width; x++)
13527 pixel=XGetPixel(windows->image.ximage,x,y);
13528 if (pixel != background)
13531 if (x < windows->image.ximage->width)
13534 trim_info.y=(ssize_t) y;
13536 Crop the bottom edge.
13538 background=XGetPixel(windows->image.ximage,0,windows->image.ximage->height-1);
13539 for (y=windows->image.ximage->height-1; y != 0; y--)
13541 for (x=0; x < windows->image.ximage->width; x++)
13543 pixel=XGetPixel(windows->image.ximage,x,y);
13544 if (pixel != background)
13547 if (x < windows->image.ximage->width)
13550 trim_info.height=(size_t) y-trim_info.y+1;
13551 if (((unsigned int) trim_info.width != windows->image.width) ||
13552 ((unsigned int) trim_info.height != windows->image.height))
13555 Reconfigure Image window as defined by the trimming rectangle.
13557 XSetCropGeometry(display,windows,&trim_info,image);
13558 windows->image.window_changes.width=(int) trim_info.width;
13559 windows->image.window_changes.height=(int) trim_info.height;
13560 (void) XConfigureImage(display,resource_info,windows,image,exception);
13562 XSetCursorState(display,windows,MagickFalse);
13563 return(MagickTrue);
13567 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13571 + X V i s u a l D i r e c t o r y I m a g e %
13575 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13577 % XVisualDirectoryImage() creates a Visual Image Directory.
13579 % The format of the XVisualDirectoryImage method is:
13581 % Image *XVisualDirectoryImage(Display *display,
13582 % XResourceInfo *resource_info,XWindows *windows,
13583 % ExceptionInfo *exception)
13585 % A description of each parameter follows:
13587 % o display: Specifies a connection to an X server; returned from
13590 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
13592 % o windows: Specifies a pointer to a XWindows structure.
13594 % o exception: return any errors or warnings in this structure.
13597 static Image *XVisualDirectoryImage(Display *display,
13598 XResourceInfo *resource_info,XWindows *windows,ExceptionInfo *exception)
13600 #define TileImageTag "Scale/Image"
13601 #define XClientName "montage"
13634 filename[MaxTextExtent] = "\0",
13635 filenames[MaxTextExtent] = "*";
13638 background_resources;
13641 Request file name from user.
13643 XFileBrowserWidget(display,windows,"Directory",filenames);
13644 if (*filenames == '\0')
13645 return((Image *) NULL);
13647 Expand the filenames.
13649 filelist=(char **) AcquireMagickMemory(sizeof(*filelist));
13650 if (filelist == (char **) NULL)
13652 ThrowXWindowException(ResourceLimitError,"MemoryAllocationFailed",
13654 return((Image *) NULL);
13657 filelist[0]=filenames;
13658 status=ExpandFilenames(&number_files,&filelist);
13659 if (IfMagickFalse(status) || (number_files == 0))
13661 if (number_files == 0)
13662 ThrowXWindowException(ImageError,"NoImagesWereFound",filenames)
13664 ThrowXWindowException(ResourceLimitError,"MemoryAllocationFailed",
13666 return((Image *) NULL);
13669 Set image background resources.
13671 background_resources=(*resource_info);
13672 background_resources.window_id=AcquireString("");
13673 (void) FormatLocaleString(background_resources.window_id,MaxTextExtent,
13674 "0x%lx",windows->image.id);
13675 background_resources.backdrop=MagickTrue;
13677 Read each image and convert them to a tile.
13679 backdrop=IsMagickTrue( (windows->visual_info->klass == TrueColor) ||
13680 (windows->visual_info->klass == DirectColor) );
13681 read_info=CloneImageInfo(resource_info->image_info);
13682 (void) SetImageOption(read_info,"jpeg:size","120x120");
13683 (void) CloneString(&read_info->size,DefaultTileGeometry);
13684 (void) SetImageInfoProgressMonitor(read_info,(MagickProgressMonitor) NULL,
13686 images=NewImageList();
13687 XSetCursorState(display,windows,MagickTrue);
13688 XCheckRefreshWindows(display,windows);
13689 for (i=0; i < (int) number_files; i++)
13691 (void) CopyMagickString(read_info->filename,filelist[i],MaxTextExtent);
13692 filelist[i]=DestroyString(filelist[i]);
13693 *read_info->magick='\0';
13694 next_image=ReadImage(read_info,exception);
13695 CatchException(exception);
13696 if (next_image != (Image *) NULL)
13698 (void) DeleteImageProperty(next_image,"label");
13699 (void) SetImageProperty(next_image,"label",InterpretImageProperties(
13700 read_info,next_image,DefaultTileLabel,exception),exception);
13701 (void) ParseRegionGeometry(next_image,read_info->size,&geometry,
13703 thumbnail_image=ThumbnailImage(next_image,geometry.width,
13704 geometry.height,exception);
13705 if (thumbnail_image != (Image *) NULL)
13707 next_image=DestroyImage(next_image);
13708 next_image=thumbnail_image;
13712 (void) XDisplayBackgroundImage(display,&background_resources,
13713 next_image,exception);
13714 XSetCursorState(display,windows,MagickTrue);
13716 AppendImageToList(&images,next_image);
13717 if (images->progress_monitor != (MagickProgressMonitor) NULL)
13722 proceed=SetImageProgress(images,LoadImageTag,(MagickOffsetType) i,
13723 (MagickSizeType) number_files);
13724 if (IfMagickFalse(proceed) )
13729 filelist=(char **) RelinquishMagickMemory(filelist);
13730 if (images == (Image *) NULL)
13732 read_info=DestroyImageInfo(read_info);
13733 XSetCursorState(display,windows,MagickFalse);
13734 ThrowXWindowException(ImageError,"NoImagesWereLoaded",filenames);
13735 return((Image *) NULL);
13738 Create the Visual Image Directory.
13740 montage_info=CloneMontageInfo(read_info,(MontageInfo *) NULL);
13741 montage_info->pointsize=10;
13742 if (resource_info->font != (char *) NULL)
13743 (void) CloneString(&montage_info->font,resource_info->font);
13744 (void) CopyMagickString(montage_info->filename,filename,MaxTextExtent);
13745 montage_image=MontageImageList(read_info,montage_info,GetFirstImageInList(
13746 images),exception);
13747 images=DestroyImageList(images);
13748 montage_info=DestroyMontageInfo(montage_info);
13749 read_info=DestroyImageInfo(read_info);
13750 XSetCursorState(display,windows,MagickFalse);
13751 if (montage_image == (Image *) NULL)
13752 return(montage_image);
13753 XClientMessage(display,windows->image.id,windows->im_protocols,
13754 windows->im_next_image,CurrentTime);
13755 return(montage_image);
13759 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13763 % X D i s p l a y B a c k g r o u n d I m a g e %
13767 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13769 % XDisplayBackgroundImage() displays an image in the background of a window.
13771 % The format of the XDisplayBackgroundImage method is:
13773 % MagickBooleanType XDisplayBackgroundImage(Display *display,
13774 % XResourceInfo *resource_info,Image *image,ExceptionInfo *exception)
13776 % A description of each parameter follows:
13778 % o display: Specifies a connection to an X server; returned from
13781 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
13783 % o image: the image.
13785 % o exception: return any errors or warnings in this structure.
13788 MagickExport MagickBooleanType XDisplayBackgroundImage(Display *display,
13789 XResourceInfo *resource_info,Image *image,ExceptionInfo *exception)
13792 geometry[MaxTextExtent],
13793 visual_type[MaxTextExtent];
13806 static XStandardColormap
13810 *visual_info = (XVisualInfo *) NULL;
13831 Determine target window.
13833 assert(image != (Image *) NULL);
13834 assert(image->signature == MagickSignature);
13835 if (IfMagickTrue(image->debug) )
13836 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
13837 resources=(*resource_info);
13838 window_info.id=(Window) NULL;
13839 root_window=XRootWindow(display,XDefaultScreen(display));
13840 if (LocaleCompare(resources.window_id,"root") == 0)
13841 window_info.id=root_window;
13844 if (isdigit((int) ((unsigned char) *resources.window_id)) != 0)
13845 window_info.id=XWindowByID(display,root_window,
13846 (Window) strtol((char *) resources.window_id,(char **) NULL,0));
13847 if (window_info.id == (Window) NULL)
13848 window_info.id=XWindowByName(display,root_window,resources.window_id);
13850 if (window_info.id == (Window) NULL)
13852 ThrowXWindowException(XServerError,"NoWindowWithSpecifiedIDExists",
13853 resources.window_id);
13854 return(MagickFalse);
13857 Determine window visual id.
13859 window_attributes.width=XDisplayWidth(display,XDefaultScreen(display));
13860 window_attributes.height=XDisplayHeight(display,XDefaultScreen(display));
13861 (void) CopyMagickString(visual_type,"default",MaxTextExtent);
13862 status=XGetWindowAttributes(display,window_info.id,&window_attributes);
13864 (void) FormatLocaleString(visual_type,MaxTextExtent,"0x%lx",
13865 XVisualIDFromVisual(window_attributes.visual));
13866 if (visual_info == (XVisualInfo *) NULL)
13869 Allocate standard colormap.
13871 map_info=XAllocStandardColormap();
13872 if (map_info == (XStandardColormap *) NULL)
13873 ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
13875 map_info->colormap=(Colormap) NULL;
13876 pixel.pixels=(unsigned long *) NULL;
13878 Initialize visual info.
13880 resources.map_type=(char *) NULL;
13881 resources.visual_type=visual_type;
13882 visual_info=XBestVisualInfo(display,map_info,&resources);
13883 if (visual_info == (XVisualInfo *) NULL)
13884 ThrowXWindowFatalException(XServerFatalError,"UnableToGetVisual",
13885 resources.visual_type);
13887 Initialize window info.
13889 window_info.ximage=(XImage *) NULL;
13890 window_info.matte_image=(XImage *) NULL;
13891 window_info.pixmap=(Pixmap) NULL;
13892 window_info.matte_pixmap=(Pixmap) NULL;
13895 Free previous root colors.
13897 if (window_info.id == root_window)
13898 (void) XDestroyWindowColors(display,root_window);
13900 Initialize Standard Colormap.
13902 resources.colormap=SharedColormap;
13903 XMakeStandardColormap(display,visual_info,&resources,image,map_info,&pixel,
13906 Graphic context superclass.
13908 context_values.background=pixel.background_color.pixel;
13909 context_values.foreground=pixel.foreground_color.pixel;
13910 pixel.annotate_context=XCreateGC(display,window_info.id,
13911 (size_t) (GCBackground | GCForeground),&context_values);
13912 if (pixel.annotate_context == (GC) NULL)
13913 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
13916 Initialize Image window attributes.
13918 window_info.name=AcquireString("\0");
13919 window_info.icon_name=AcquireString("\0");
13920 XGetWindowInfo(display,visual_info,map_info,&pixel,(XFontStruct *) NULL,
13921 &resources,&window_info);
13923 Create the X image.
13925 window_info.width=(unsigned int) image->columns;
13926 window_info.height=(unsigned int) image->rows;
13927 if ((image->columns != window_info.width) ||
13928 (image->rows != window_info.height))
13929 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
13931 (void) FormatLocaleString(geometry,MaxTextExtent,"%ux%u+0+0>",
13932 window_attributes.width,window_attributes.height);
13933 geometry_info.width=window_info.width;
13934 geometry_info.height=window_info.height;
13935 geometry_info.x=(ssize_t) window_info.x;
13936 geometry_info.y=(ssize_t) window_info.y;
13937 (void) ParseMetaGeometry(geometry,&geometry_info.x,&geometry_info.y,
13938 &geometry_info.width,&geometry_info.height);
13939 window_info.width=(unsigned int) geometry_info.width;
13940 window_info.height=(unsigned int) geometry_info.height;
13941 window_info.x=(int) geometry_info.x;
13942 window_info.y=(int) geometry_info.y;
13943 status=XMakeImage(display,&resources,&window_info,image,window_info.width,
13944 window_info.height,exception);
13945 if (IfMagickFalse(status) )
13946 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
13950 if (IfMagickTrue(image->debug) )
13952 (void) LogMagickEvent(X11Event,GetMagickModule(),
13953 "Image: %s[%.20g] %.20gx%.20g ",image->filename,(double) image->scene,
13954 (double) image->columns,(double) image->rows);
13955 if (image->colors != 0)
13956 (void) LogMagickEvent(X11Event,GetMagickModule(),"%.20gc ",(double)
13958 (void) LogMagickEvent(X11Event,GetMagickModule(),"%s",image->magick);
13961 Adjust image dimensions as specified by backdrop or geometry options.
13963 width=(int) window_info.width;
13964 height=(int) window_info.height;
13965 if (IfMagickTrue(resources.backdrop) )
13968 Center image on window.
13970 window_info.x=(window_attributes.width/2)-
13971 (window_info.ximage->width/2);
13972 window_info.y=(window_attributes.height/2)-
13973 (window_info.ximage->height/2);
13974 width=window_attributes.width;
13975 height=window_attributes.height;
13977 if ((resources.image_geometry != (char *) NULL) &&
13978 (*resources.image_geometry != '\0'))
13981 default_geometry[MaxTextExtent];
13991 User specified geometry.
13993 size_hints=XAllocSizeHints();
13994 if (size_hints == (XSizeHints *) NULL)
13995 ThrowXWindowFatalException(ResourceLimitFatalError,
13996 "MemoryAllocationFailed",image->filename);
13997 size_hints->flags=0L;
13998 (void) FormatLocaleString(default_geometry,MaxTextExtent,"%dx%d",
14000 flags=XWMGeometry(display,visual_info->screen,resources.image_geometry,
14001 default_geometry,window_info.border_width,size_hints,&window_info.x,
14002 &window_info.y,&width,&height,&gravity);
14003 if (flags & (XValue | YValue))
14005 width=window_attributes.width;
14006 height=window_attributes.height;
14008 (void) XFree((void *) size_hints);
14011 Create the X pixmap.
14013 window_info.pixmap=XCreatePixmap(display,window_info.id,(unsigned int) width,
14014 (unsigned int) height,window_info.depth);
14015 if (window_info.pixmap == (Pixmap) NULL)
14016 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXPixmap",
14019 Display pixmap on the window.
14021 if (((unsigned int) width > window_info.width) ||
14022 ((unsigned int) height > window_info.height))
14023 (void) XFillRectangle(display,window_info.pixmap,
14024 window_info.annotate_context,0,0,(unsigned int) width,
14025 (unsigned int) height);
14026 (void) XPutImage(display,window_info.pixmap,window_info.annotate_context,
14027 window_info.ximage,0,0,window_info.x,window_info.y,(unsigned int)
14028 window_info.width,(unsigned int) window_info.height);
14029 (void) XSetWindowBackgroundPixmap(display,window_info.id,window_info.pixmap);
14030 (void) XClearWindow(display,window_info.id);
14031 delay=1000*image->delay/MagickMax(image->ticks_per_second,1L);
14032 XDelay(display,delay == 0UL ? 10UL : delay);
14033 (void) XSync(display,MagickFalse);
14034 return(IsMagickTrue(window_info.id == root_window));
14038 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
14042 + X D i s p l a y I m a g e %
14046 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
14048 % XDisplayImage() displays an image via X11. A new image is created and
14049 % returned if the user interactively transforms the displayed image.
14051 % The format of the XDisplayImage method is:
14053 % Image *XDisplayImage(Display *display,XResourceInfo *resource_info,
14054 % char **argv,int argc,Image **image,size_t *state,
14055 % ExceptionInfo *exception)
14057 % A description of each parameter follows:
14059 % o nexus: Method XDisplayImage returns an image when the
14060 % user chooses 'Open Image' from the command menu or picks a tile
14061 % from the image directory. Otherwise a null image is returned.
14063 % o display: Specifies a connection to an X server; returned from
14066 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
14068 % o argv: Specifies the application's argument list.
14070 % o argc: Specifies the number of arguments.
14072 % o image: Specifies an address to an address of an Image structure;
14074 % o exception: return any errors or warnings in this structure.
14077 MagickExport Image *XDisplayImage(Display *display,XResourceInfo *resource_info,
14078 char **argv,int argc,Image **image,size_t *state,ExceptionInfo *exception)
14080 #define MagnifySize 256 /* must be a power of 2 */
14081 #define MagickMenus 10
14082 #define MagickTitle "Commands"
14109 "Visual Directory...",
14155 "Contrast Stretch...",
14156 "Sigmoidal Contrast...",
14190 "Charcoal Draw...",
14204 "Region of Interest...",
14207 *MiscellanyMenu[] =
14222 "Browse Documentation",
14249 **Menus[MagickMenus] =
14287 VisualDirectoryCommand,
14301 OriginalSizeCommand,
14308 TransformCommands[] =
14314 RotateRightCommand,
14321 EnhanceCommands[] =
14329 ContrastStretchCommand,
14330 SigmoidalContrastCommand,
14338 EffectsCommands[] =
14342 ReduceNoiseCommand,
14362 CharcoalDrawCommand
14364 ImageEditCommands[] =
14375 RegionofInterestCommand
14377 MiscellanyCommands[] =
14381 ShowPreviewCommand,
14382 ShowHistogramCommand,
14391 BrowseDocumentationCommand,
14394 ShortCutsCommands[] =
14406 VirtualCommands[] =
14415 *Commands[MagickMenus] =
14425 MiscellanyCommands,
14430 command[MaxTextExtent],
14432 geometry[MaxTextExtent],
14433 resource_name[MaxTextExtent];
14460 working_directory[MaxTextExtent];
14466 *magick_windows[MaxXWindows];
14468 static unsigned int
14528 assert(image != (Image **) NULL);
14529 assert((*image)->signature == MagickSignature);
14530 if (IfMagickTrue((*image)->debug) )
14531 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",(*image)->filename);
14532 display_image=(*image);
14533 warning_handler=(WarningHandler) NULL;
14534 windows=XSetWindows((XWindows *) ~0);
14535 if (windows != (XWindows *) NULL)
14540 if (*working_directory == '\0')
14541 (void) CopyMagickString(working_directory,".",MaxTextExtent);
14542 status=chdir(working_directory);
14544 (void) ThrowMagickException(exception,GetMagickModule(),FileOpenError,
14545 "UnableToOpenFile","%s",working_directory);
14546 warning_handler=resource_info->display_warnings ?
14547 SetErrorHandler(XWarning) : SetErrorHandler((ErrorHandler) NULL);
14548 warning_handler=resource_info->display_warnings ?
14549 SetWarningHandler(XWarning) : SetWarningHandler((WarningHandler) NULL);
14554 Allocate windows structure.
14556 resource_info->colors=display_image->colors;
14557 windows=XSetWindows(XInitializeWindows(display,resource_info));
14558 if (windows == (XWindows *) NULL)
14559 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateWindow",
14560 (*image)->filename);
14562 Initialize window id's.
14565 magick_windows[number_windows++]=(&windows->icon);
14566 magick_windows[number_windows++]=(&windows->backdrop);
14567 magick_windows[number_windows++]=(&windows->image);
14568 magick_windows[number_windows++]=(&windows->info);
14569 magick_windows[number_windows++]=(&windows->command);
14570 magick_windows[number_windows++]=(&windows->widget);
14571 magick_windows[number_windows++]=(&windows->popup);
14572 magick_windows[number_windows++]=(&windows->magnify);
14573 magick_windows[number_windows++]=(&windows->pan);
14574 for (i=0; i < (int) number_windows; i++)
14575 magick_windows[i]->id=(Window) NULL;
14580 Initialize font info.
14582 if (windows->font_info != (XFontStruct *) NULL)
14583 (void) XFreeFont(display,windows->font_info);
14584 windows->font_info=XBestFont(display,resource_info,MagickFalse);
14585 if (windows->font_info == (XFontStruct *) NULL)
14586 ThrowXWindowFatalException(XServerFatalError,"UnableToLoadFont",
14587 resource_info->font);
14589 Initialize Standard Colormap.
14591 map_info=windows->map_info;
14592 icon_map=windows->icon_map;
14593 visual_info=windows->visual_info;
14594 icon_visual=windows->icon_visual;
14595 pixel=windows->pixel_info;
14596 icon_pixel=windows->icon_pixel;
14597 font_info=windows->font_info;
14598 icon_resources=windows->icon_resources;
14599 class_hints=windows->class_hints;
14600 manager_hints=windows->manager_hints;
14601 root_window=XRootWindow(display,visual_info->screen);
14602 nexus=NewImageList();
14603 if (IfMagickTrue(display_image->debug) )
14605 (void) LogMagickEvent(X11Event,GetMagickModule(),
14606 "Image: %s[%.20g] %.20gx%.20g ",display_image->filename,
14607 (double) display_image->scene,(double) display_image->columns,
14608 (double) display_image->rows);
14609 if (display_image->colors != 0)
14610 (void) LogMagickEvent(X11Event,GetMagickModule(),"%.20gc ",(double)
14611 display_image->colors);
14612 (void) LogMagickEvent(X11Event,GetMagickModule(),"%s",
14613 display_image->magick);
14615 XMakeStandardColormap(display,visual_info,resource_info,display_image,
14616 map_info,pixel,exception);
14617 display_image->taint=MagickFalse;
14619 Initialize graphic context.
14621 windows->context.id=(Window) NULL;
14622 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
14623 resource_info,&windows->context);
14624 (void) CloneString(&class_hints->res_name,resource_info->client_name);
14625 (void) CloneString(&class_hints->res_class,resource_info->client_name);
14626 class_hints->res_class[0]=(char) toupper((int) class_hints->res_class[0]);
14627 manager_hints->flags=InputHint | StateHint;
14628 manager_hints->input=MagickFalse;
14629 manager_hints->initial_state=WithdrawnState;
14630 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14631 &windows->context);
14632 if (IfMagickTrue(display_image->debug) )
14633 (void) LogMagickEvent(X11Event,GetMagickModule(),
14634 "Window id: 0x%lx (context)",windows->context.id);
14635 context_values.background=pixel->background_color.pixel;
14636 context_values.font=font_info->fid;
14637 context_values.foreground=pixel->foreground_color.pixel;
14638 context_values.graphics_exposures=MagickFalse;
14639 context_mask=(MagickStatusType)
14640 (GCBackground | GCFont | GCForeground | GCGraphicsExposures);
14641 if (pixel->annotate_context != (GC) NULL)
14642 (void) XFreeGC(display,pixel->annotate_context);
14643 pixel->annotate_context=XCreateGC(display,windows->context.id,
14644 context_mask,&context_values);
14645 if (pixel->annotate_context == (GC) NULL)
14646 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
14647 display_image->filename);
14648 context_values.background=pixel->depth_color.pixel;
14649 if (pixel->widget_context != (GC) NULL)
14650 (void) XFreeGC(display,pixel->widget_context);
14651 pixel->widget_context=XCreateGC(display,windows->context.id,context_mask,
14653 if (pixel->widget_context == (GC) NULL)
14654 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
14655 display_image->filename);
14656 context_values.background=pixel->foreground_color.pixel;
14657 context_values.foreground=pixel->background_color.pixel;
14658 context_values.plane_mask=context_values.background ^
14659 context_values.foreground;
14660 if (pixel->highlight_context != (GC) NULL)
14661 (void) XFreeGC(display,pixel->highlight_context);
14662 pixel->highlight_context=XCreateGC(display,windows->context.id,
14663 (size_t) (context_mask | GCPlaneMask),&context_values);
14664 if (pixel->highlight_context == (GC) NULL)
14665 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
14666 display_image->filename);
14667 (void) XDestroyWindow(display,windows->context.id);
14669 Initialize icon window.
14671 XGetWindowInfo(display,icon_visual,icon_map,icon_pixel,(XFontStruct *) NULL,
14672 icon_resources,&windows->icon);
14673 windows->icon.geometry=resource_info->icon_geometry;
14674 XBestIconSize(display,&windows->icon,display_image);
14675 windows->icon.attributes.colormap=XDefaultColormap(display,
14676 icon_visual->screen);
14677 windows->icon.attributes.event_mask=ExposureMask | StructureNotifyMask;
14678 manager_hints->flags=InputHint | StateHint;
14679 manager_hints->input=MagickFalse;
14680 manager_hints->initial_state=IconicState;
14681 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14683 if (IfMagickTrue(display_image->debug) )
14684 (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (icon)",
14687 Initialize graphic context for icon window.
14689 if (icon_pixel->annotate_context != (GC) NULL)
14690 (void) XFreeGC(display,icon_pixel->annotate_context);
14691 context_values.background=icon_pixel->background_color.pixel;
14692 context_values.foreground=icon_pixel->foreground_color.pixel;
14693 icon_pixel->annotate_context=XCreateGC(display,windows->icon.id,
14694 (size_t) (GCBackground | GCForeground),&context_values);
14695 if (icon_pixel->annotate_context == (GC) NULL)
14696 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
14697 display_image->filename);
14698 windows->icon.annotate_context=icon_pixel->annotate_context;
14700 Initialize Image window.
14702 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,resource_info,
14704 windows->image.shape=MagickTrue; /* non-rectangular shape hint */
14705 if (IfMagickFalse(resource_info->use_shared_memory) )
14706 windows->image.shared_memory=MagickFalse;
14707 if ((resource_info->title != (char *) NULL) && !(*state & MontageImageState))
14712 title=InterpretImageProperties(resource_info->image_info,display_image,
14713 resource_info->title,exception);
14714 (void) CopyMagickString(windows->image.name,title,MaxTextExtent);
14715 (void) CopyMagickString(windows->image.icon_name,title,MaxTextExtent);
14716 title=DestroyString(title);
14721 filename[MaxTextExtent];
14724 Window name is the base of the filename.
14726 GetPathComponent(display_image->magick_filename,TailPath,filename);
14727 if (display_image->scene == 0)
14728 (void) FormatLocaleString(windows->image.name,MaxTextExtent,
14729 "%s: %s",MagickPackageName,filename);
14731 (void) FormatLocaleString(windows->image.name,MaxTextExtent,
14732 "%s: %s[scene: %.20g frames: %.20g]",MagickPackageName,filename,
14733 (double) display_image->scene,(double) GetImageListLength(
14735 (void) CopyMagickString(windows->image.icon_name,filename,MaxTextExtent);
14737 if (resource_info->immutable)
14738 windows->image.immutable=MagickTrue;
14739 windows->image.use_pixmap=resource_info->use_pixmap;
14740 windows->image.geometry=resource_info->image_geometry;
14741 (void) FormatLocaleString(geometry,MaxTextExtent,"%ux%u+0+0>!",
14742 XDisplayWidth(display,visual_info->screen),
14743 XDisplayHeight(display,visual_info->screen));
14744 geometry_info.width=display_image->columns;
14745 geometry_info.height=display_image->rows;
14748 (void) ParseMetaGeometry(geometry,&geometry_info.x,&geometry_info.y,
14749 &geometry_info.width,&geometry_info.height);
14750 windows->image.width=(unsigned int) geometry_info.width;
14751 windows->image.height=(unsigned int) geometry_info.height;
14752 windows->image.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
14753 ButtonReleaseMask | EnterWindowMask | ExposureMask | KeyPressMask |
14754 KeyReleaseMask | LeaveWindowMask | OwnerGrabButtonMask |
14755 PropertyChangeMask | StructureNotifyMask | SubstructureNotifyMask;
14756 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
14757 resource_info,&windows->backdrop);
14758 if ((resource_info->backdrop) || (windows->backdrop.id != (Window) NULL))
14761 Initialize backdrop window.
14763 windows->backdrop.x=0;
14764 windows->backdrop.y=0;
14765 (void) CloneString(&windows->backdrop.name,"Backdrop");
14766 windows->backdrop.flags=(size_t) (USSize | USPosition);
14767 windows->backdrop.width=(unsigned int)
14768 XDisplayWidth(display,visual_info->screen);
14769 windows->backdrop.height=(unsigned int)
14770 XDisplayHeight(display,visual_info->screen);
14771 windows->backdrop.border_width=0;
14772 windows->backdrop.immutable=MagickTrue;
14773 windows->backdrop.attributes.do_not_propagate_mask=ButtonPressMask |
14775 windows->backdrop.attributes.event_mask=ButtonPressMask | KeyPressMask |
14776 StructureNotifyMask;
14777 manager_hints->flags=IconWindowHint | InputHint | StateHint;
14778 manager_hints->icon_window=windows->icon.id;
14779 manager_hints->input=MagickTrue;
14780 manager_hints->initial_state=resource_info->iconic ? IconicState :
14782 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14783 &windows->backdrop);
14784 if (IfMagickTrue(display_image->debug) )
14785 (void) LogMagickEvent(X11Event,GetMagickModule(),
14786 "Window id: 0x%lx (backdrop)",windows->backdrop.id);
14787 (void) XMapWindow(display,windows->backdrop.id);
14788 (void) XClearWindow(display,windows->backdrop.id);
14789 if (windows->image.id != (Window) NULL)
14791 (void) XDestroyWindow(display,windows->image.id);
14792 windows->image.id=(Window) NULL;
14795 Position image in the center the backdrop.
14797 windows->image.flags|=USPosition;
14798 windows->image.x=(XDisplayWidth(display,visual_info->screen)/2)-
14799 (windows->image.width/2);
14800 windows->image.y=(XDisplayHeight(display,visual_info->screen)/2)-
14801 (windows->image.height/2);
14803 manager_hints->flags=IconWindowHint | InputHint | StateHint;
14804 manager_hints->icon_window=windows->icon.id;
14805 manager_hints->input=MagickTrue;
14806 manager_hints->initial_state=resource_info->iconic ? IconicState :
14808 if (windows->group_leader.id != (Window) NULL)
14813 manager_hints->flags|=WindowGroupHint;
14814 manager_hints->window_group=windows->group_leader.id;
14815 (void) XSelectInput(display,windows->group_leader.id,StructureNotifyMask);
14816 if (IfMagickTrue(display_image->debug) )
14817 (void) LogMagickEvent(X11Event,GetMagickModule(),
14818 "Window id: 0x%lx (group leader)",windows->group_leader.id);
14820 XMakeWindow(display,
14821 (Window) (resource_info->backdrop ? windows->backdrop.id : root_window),
14822 argv,argc,class_hints,manager_hints,&windows->image);
14823 (void) XChangeProperty(display,windows->image.id,windows->im_protocols,
14824 XA_STRING,8,PropModeReplace,(unsigned char *) NULL,0);
14825 if (windows->group_leader.id != (Window) NULL)
14826 (void) XSetTransientForHint(display,windows->image.id,
14827 windows->group_leader.id);
14828 if (IfMagickTrue(display_image->debug) )
14829 (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (image)",
14830 windows->image.id);
14832 Initialize Info widget.
14834 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,resource_info,
14836 (void) CloneString(&windows->info.name,"Info");
14837 (void) CloneString(&windows->info.icon_name,"Info");
14838 windows->info.border_width=1;
14841 windows->info.flags|=PPosition;
14842 windows->info.attributes.win_gravity=UnmapGravity;
14843 windows->info.attributes.event_mask=ButtonPressMask | ExposureMask |
14844 StructureNotifyMask;
14845 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
14846 manager_hints->input=MagickFalse;
14847 manager_hints->initial_state=NormalState;
14848 manager_hints->window_group=windows->image.id;
14849 XMakeWindow(display,windows->image.id,argv,argc,class_hints,manager_hints,
14851 windows->info.highlight_stipple=XCreateBitmapFromData(display,
14852 windows->info.id,(char *) HighlightBitmap,HighlightWidth,HighlightHeight);
14853 windows->info.shadow_stipple=XCreateBitmapFromData(display,
14854 windows->info.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
14855 (void) XSetTransientForHint(display,windows->info.id,windows->image.id);
14856 if (IfMagickTrue(windows->image.mapped) )
14857 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
14858 if (IfMagickTrue(display_image->debug) )
14859 (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (info)",
14862 Initialize Command widget.
14864 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
14865 resource_info,&windows->command);
14866 windows->command.data=MagickMenus;
14867 (void) XCommandWidget(display,windows,CommandMenu,(XEvent *) NULL);
14868 (void) FormatLocaleString(resource_name,MaxTextExtent,"%s.command",
14869 resource_info->client_name);
14870 windows->command.geometry=XGetResourceClass(resource_info->resource_database,
14871 resource_name,"geometry",(char *) NULL);
14872 (void) CloneString(&windows->command.name,MagickTitle);
14873 windows->command.border_width=0;
14874 windows->command.flags|=PPosition;
14875 windows->command.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
14876 ButtonReleaseMask | EnterWindowMask | ExposureMask | LeaveWindowMask |
14877 OwnerGrabButtonMask | StructureNotifyMask;
14878 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
14879 manager_hints->input=MagickTrue;
14880 manager_hints->initial_state=NormalState;
14881 manager_hints->window_group=windows->image.id;
14882 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14883 &windows->command);
14884 windows->command.highlight_stipple=XCreateBitmapFromData(display,
14885 windows->command.id,(char *) HighlightBitmap,HighlightWidth,
14887 windows->command.shadow_stipple=XCreateBitmapFromData(display,
14888 windows->command.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
14889 (void) XSetTransientForHint(display,windows->command.id,windows->image.id);
14890 if (IfMagickTrue(windows->command.mapped) )
14891 (void) XMapRaised(display,windows->command.id);
14892 if (IfMagickTrue(display_image->debug) )
14893 (void) LogMagickEvent(X11Event,GetMagickModule(),
14894 "Window id: 0x%lx (command)",windows->command.id);
14896 Initialize Widget window.
14898 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
14899 resource_info,&windows->widget);
14900 (void) FormatLocaleString(resource_name,MaxTextExtent,"%s.widget",
14901 resource_info->client_name);
14902 windows->widget.geometry=XGetResourceClass(resource_info->resource_database,
14903 resource_name,"geometry",(char *) NULL);
14904 windows->widget.border_width=0;
14905 windows->widget.flags|=PPosition;
14906 windows->widget.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
14907 ButtonReleaseMask | EnterWindowMask | ExposureMask | KeyPressMask |
14908 KeyReleaseMask | LeaveWindowMask | OwnerGrabButtonMask |
14909 StructureNotifyMask;
14910 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
14911 manager_hints->input=MagickTrue;
14912 manager_hints->initial_state=NormalState;
14913 manager_hints->window_group=windows->image.id;
14914 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14916 windows->widget.highlight_stipple=XCreateBitmapFromData(display,
14917 windows->widget.id,(char *) HighlightBitmap,HighlightWidth,HighlightHeight);
14918 windows->widget.shadow_stipple=XCreateBitmapFromData(display,
14919 windows->widget.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
14920 (void) XSetTransientForHint(display,windows->widget.id,windows->image.id);
14921 if (IfMagickTrue(display_image->debug) )
14922 (void) LogMagickEvent(X11Event,GetMagickModule(),
14923 "Window id: 0x%lx (widget)",windows->widget.id);
14925 Initialize popup window.
14927 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
14928 resource_info,&windows->popup);
14929 windows->popup.border_width=0;
14930 windows->popup.flags|=PPosition;
14931 windows->popup.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
14932 ButtonReleaseMask | EnterWindowMask | ExposureMask | KeyPressMask |
14933 KeyReleaseMask | LeaveWindowMask | StructureNotifyMask;
14934 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
14935 manager_hints->input=MagickTrue;
14936 manager_hints->initial_state=NormalState;
14937 manager_hints->window_group=windows->image.id;
14938 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14940 windows->popup.highlight_stipple=XCreateBitmapFromData(display,
14941 windows->popup.id,(char *) HighlightBitmap,HighlightWidth,HighlightHeight);
14942 windows->popup.shadow_stipple=XCreateBitmapFromData(display,
14943 windows->popup.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
14944 (void) XSetTransientForHint(display,windows->popup.id,windows->image.id);
14945 if (IfMagickTrue(display_image->debug) )
14946 (void) LogMagickEvent(X11Event,GetMagickModule(),
14947 "Window id: 0x%lx (pop up)",windows->popup.id);
14949 Initialize Magnify window and cursor.
14951 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
14952 resource_info,&windows->magnify);
14953 if (IfMagickFalse(resource_info->use_shared_memory) )
14954 windows->magnify.shared_memory=MagickFalse;
14955 (void) FormatLocaleString(resource_name,MaxTextExtent,"%s.magnify",
14956 resource_info->client_name);
14957 windows->magnify.geometry=XGetResourceClass(resource_info->resource_database,
14958 resource_name,"geometry",(char *) NULL);
14959 (void) FormatLocaleString(windows->magnify.name,MaxTextExtent,"Magnify %uX",
14960 resource_info->magnify);
14961 if (windows->magnify.cursor != (Cursor) NULL)
14962 (void) XFreeCursor(display,windows->magnify.cursor);
14963 windows->magnify.cursor=XMakeCursor(display,windows->image.id,
14964 map_info->colormap,resource_info->background_color,
14965 resource_info->foreground_color);
14966 if (windows->magnify.cursor == (Cursor) NULL)
14967 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateCursor",
14968 display_image->filename);
14969 windows->magnify.width=MagnifySize;
14970 windows->magnify.height=MagnifySize;
14971 windows->magnify.flags|=PPosition;
14972 windows->magnify.min_width=MagnifySize;
14973 windows->magnify.min_height=MagnifySize;
14974 windows->magnify.width_inc=MagnifySize;
14975 windows->magnify.height_inc=MagnifySize;
14976 windows->magnify.data=resource_info->magnify;
14977 windows->magnify.attributes.cursor=windows->magnify.cursor;
14978 windows->magnify.attributes.event_mask=ButtonPressMask | ButtonReleaseMask |
14979 ExposureMask | KeyPressMask | KeyReleaseMask | OwnerGrabButtonMask |
14980 StructureNotifyMask;
14981 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
14982 manager_hints->input=MagickTrue;
14983 manager_hints->initial_state=NormalState;
14984 manager_hints->window_group=windows->image.id;
14985 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14986 &windows->magnify);
14987 if (IfMagickTrue(display_image->debug) )
14988 (void) LogMagickEvent(X11Event,GetMagickModule(),
14989 "Window id: 0x%lx (magnify)",windows->magnify.id);
14990 (void) XSetTransientForHint(display,windows->magnify.id,windows->image.id);
14992 Initialize panning window.
14994 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
14995 resource_info,&windows->pan);
14996 (void) CloneString(&windows->pan.name,"Pan Icon");
14997 windows->pan.width=windows->icon.width;
14998 windows->pan.height=windows->icon.height;
14999 (void) FormatLocaleString(resource_name,MaxTextExtent,"%s.pan",
15000 resource_info->client_name);
15001 windows->pan.geometry=XGetResourceClass(resource_info->resource_database,
15002 resource_name,"geometry",(char *) NULL);
15003 (void) XParseGeometry(windows->pan.geometry,&windows->pan.x,&windows->pan.y,
15004 &windows->pan.width,&windows->pan.height);
15005 windows->pan.flags|=PPosition;
15006 windows->pan.immutable=MagickTrue;
15007 windows->pan.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
15008 ButtonReleaseMask | ExposureMask | KeyPressMask | KeyReleaseMask |
15009 StructureNotifyMask;
15010 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
15011 manager_hints->input=MagickFalse;
15012 manager_hints->initial_state=NormalState;
15013 manager_hints->window_group=windows->image.id;
15014 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
15016 if (IfMagickTrue(display_image->debug) )
15017 (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (pan)",
15019 (void) XSetTransientForHint(display,windows->pan.id,windows->image.id);
15020 if (IfMagickTrue(windows->info.mapped) )
15021 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
15022 if (IfMagickFalse(windows->image.mapped) ||
15023 (windows->backdrop.id != (Window) NULL))
15024 (void) XMapWindow(display,windows->image.id);
15026 Set our progress monitor and warning handlers.
15028 if (warning_handler == (WarningHandler) NULL)
15030 warning_handler=resource_info->display_warnings ?
15031 SetErrorHandler(XWarning) : SetErrorHandler((ErrorHandler) NULL);
15032 warning_handler=resource_info->display_warnings ?
15033 SetWarningHandler(XWarning) : SetWarningHandler((WarningHandler) NULL);
15036 Initialize Image and Magnify X images.
15038 windows->image.x=0;
15039 windows->image.y=0;
15040 windows->magnify.shape=MagickFalse;
15041 width=(unsigned int) display_image->columns;
15042 height=(unsigned int) display_image->rows;
15043 if ((display_image->columns != width) || (display_image->rows != height))
15044 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
15045 display_image->filename);
15046 status=XMakeImage(display,resource_info,&windows->image,display_image,
15047 width,height,exception);
15048 if (IfMagickFalse(status) )
15049 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
15050 display_image->filename);
15051 status=XMakeImage(display,resource_info,&windows->magnify,(Image *) NULL,
15052 windows->magnify.width,windows->magnify.height,exception);
15053 if (IfMagickFalse(status))
15054 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
15055 display_image->filename);
15056 if (IfMagickTrue(windows->magnify.mapped) )
15057 (void) XMapRaised(display,windows->magnify.id);
15058 if (IfMagickTrue(windows->pan.mapped) )
15059 (void) XMapRaised(display,windows->pan.id);
15060 windows->image.window_changes.width=(int) display_image->columns;
15061 windows->image.window_changes.height=(int) display_image->rows;
15062 (void) XConfigureImage(display,resource_info,windows,display_image,exception);
15063 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
15064 (void) XSync(display,MagickFalse);
15068 delay=display_image->delay/MagickMax(display_image->ticks_per_second,1L);
15069 timer=time((time_t *) NULL)+(delay == 0 ? 1 : delay)+1;
15071 if (IfMagickTrue(resource_info->update) )
15077 Determine when file data was last modified.
15079 status=GetPathAttributes(display_image->filename,&attributes);
15080 if (IfMagickTrue(status) )
15081 update_time=attributes.st_mtime;
15083 *state&=(~FormerImageState);
15084 *state&=(~MontageImageState);
15085 *state&=(~NextImageState);
15089 Handle a window event.
15091 if (IfMagickTrue(windows->image.mapped) )
15092 if ((display_image->delay != 0) || (resource_info->update != 0))
15094 if (timer < time((time_t *) NULL))
15096 if (IfMagickFalse(resource_info->update) )
15097 *state|=NextImageState | ExitState;
15104 Determine if image file was modified.
15106 status=GetPathAttributes(display_image->filename,&attributes);
15107 if (IfMagickTrue(status) )
15108 if (update_time != attributes.st_mtime)
15113 (void) FormatLocaleString(
15114 resource_info->image_info->filename,MaxTextExtent,
15115 "%s:%s",display_image->magick,
15116 display_image->filename);
15117 nexus=ReadImage(resource_info->image_info,exception);
15118 if (nexus != (Image *) NULL)
15120 nexus=DestroyImage(nexus);
15121 *state|=NextImageState | ExitState;
15124 delay=display_image->delay/MagickMax(
15125 display_image->ticks_per_second,1L);
15126 timer=time((time_t *) NULL)+(delay == 0 ? 1 : delay)+1;
15129 if (XEventsQueued(display,QueuedAfterFlush) == 0)
15132 Do not block if delay > 0.
15134 XDelay(display,SuspendTime << 2);
15138 timestamp=time((time_t *) NULL);
15139 (void) XNextEvent(display,&event);
15140 if (IfMagickFalse(windows->image.stasis) )
15141 windows->image.stasis=IsMagickTrue((time((time_t *) NULL)-timestamp) > 0);
15142 if (IfMagickFalse(windows->magnify.stasis) )
15143 windows->magnify.stasis=IsMagickTrue((time((time_t *) NULL)-timestamp) > 0);
15144 if (event.xany.window == windows->command.id)
15147 Select a command from the Command widget.
15149 id=XCommandWidget(display,windows,CommandMenu,&event);
15152 (void) CopyMagickString(command,CommandMenu[id],MaxTextExtent);
15153 command_type=CommandMenus[id];
15154 if (id < MagickMenus)
15157 Select a command from a pop-up menu.
15159 entry=XMenuWidget(display,windows,CommandMenu[id],Menus[id],
15163 (void) CopyMagickString(command,Menus[id][entry],MaxTextExtent);
15164 command_type=Commands[id][entry];
15166 if (command_type != NullCommand)
15167 nexus=XMagickCommand(display,resource_info,windows,command_type,
15168 &display_image,exception);
15171 switch (event.type)
15175 if (IfMagickTrue(display_image->debug) )
15176 (void) LogMagickEvent(X11Event,GetMagickModule(),
15177 "Button Press: 0x%lx %u +%d+%d",event.xbutton.window,
15178 event.xbutton.button,event.xbutton.x,event.xbutton.y);
15179 if ((event.xbutton.button == Button3) &&
15180 (event.xbutton.state & Mod1Mask))
15183 Convert Alt-Button3 to Button2.
15185 event.xbutton.button=Button2;
15186 event.xbutton.state&=(~Mod1Mask);
15188 if (event.xbutton.window == windows->backdrop.id)
15190 (void) XSetInputFocus(display,event.xbutton.window,RevertToParent,
15191 event.xbutton.time);
15194 if (event.xbutton.window == windows->image.id)
15196 switch (event.xbutton.button)
15200 if (resource_info->immutable)
15203 Select a command from the Virtual menu.
15205 entry=XMenuWidget(display,windows,"Commands",VirtualMenu,
15208 nexus=XMagickCommand(display,resource_info,windows,
15209 VirtualCommands[entry],&display_image,exception);
15213 Map/unmap Command widget.
15215 if (IfMagickTrue(windows->command.mapped) )
15216 (void) XWithdrawWindow(display,windows->command.id,
15217 windows->command.screen);
15220 (void) XCommandWidget(display,windows,CommandMenu,
15222 (void) XMapRaised(display,windows->command.id);
15229 User pressed the image magnify button.
15231 (void) XMagickCommand(display,resource_info,windows,ZoomCommand,
15232 &display_image,exception);
15233 XMagnifyImage(display,windows,&event,exception);
15238 if (resource_info->immutable)
15241 Select a command from the Virtual menu.
15243 entry=XMenuWidget(display,windows,"Commands",VirtualMenu,
15246 nexus=XMagickCommand(display,resource_info,windows,
15247 VirtualCommands[entry],&display_image,exception);
15250 if (display_image->montage != (char *) NULL)
15253 Open or delete a tile from a visual image directory.
15255 nexus=XTileImage(display,resource_info,windows,
15256 display_image,&event,exception);
15257 if (nexus != (Image *) NULL)
15258 *state|=MontageImageState | NextImageState | ExitState;
15259 vid_info.x=(short int) windows->image.x;
15260 vid_info.y=(short int) windows->image.y;
15264 Select a command from the Short Cuts menu.
15266 entry=XMenuWidget(display,windows,"Short Cuts",ShortCutsMenu,
15269 nexus=XMagickCommand(display,resource_info,windows,
15270 ShortCutsCommands[entry],&display_image,exception);
15278 XTranslateImage(display,windows,*image,XK_Up);
15286 XTranslateImage(display,windows,*image,XK_Down);
15294 if (event.xbutton.window == windows->magnify.id)
15314 MagnifyCommands[] =
15327 Select a magnify factor from the pop-up menu.
15329 factor=XMenuWidget(display,windows,"Magnify",MagnifyMenu,command);
15331 XMagnifyWindowCommand(display,windows,0,MagnifyCommands[factor],
15335 if (event.xbutton.window == windows->pan.id)
15337 switch (event.xbutton.button)
15344 XTranslateImage(display,windows,*image,XK_Up);
15352 XTranslateImage(display,windows,*image,XK_Down);
15357 XPanImage(display,windows,&event,exception);
15363 delay=display_image->delay/MagickMax(display_image->ticks_per_second,
15365 timer=time((time_t *) NULL)+(delay == 0 ? 1 : delay)+1;
15368 case ButtonRelease:
15370 if (IfMagickTrue(display_image->debug) )
15371 (void) LogMagickEvent(X11Event,GetMagickModule(),
15372 "Button Release: 0x%lx %u +%d+%d",event.xbutton.window,
15373 event.xbutton.button,event.xbutton.x,event.xbutton.y);
15376 case ClientMessage:
15378 if (IfMagickTrue(display_image->debug) )
15379 (void) LogMagickEvent(X11Event,GetMagickModule(),
15380 "Client Message: 0x%lx 0x%lx %d 0x%lx",event.xclient.window,
15381 event.xclient.message_type,event.xclient.format,(unsigned long)
15382 event.xclient.data.l[0]);
15383 if (event.xclient.message_type == windows->im_protocols)
15385 if (*event.xclient.data.l == (long) windows->im_update_widget)
15387 (void) CloneString(&windows->command.name,MagickTitle);
15388 windows->command.data=MagickMenus;
15389 (void) XCommandWidget(display,windows,CommandMenu,
15393 if (*event.xclient.data.l == (long) windows->im_update_colormap)
15396 Update graphic context and window colormap.
15398 for (i=0; i < (int) number_windows; i++)
15400 if (magick_windows[i]->id == windows->icon.id)
15402 context_values.background=pixel->background_color.pixel;
15403 context_values.foreground=pixel->foreground_color.pixel;
15404 (void) XChangeGC(display,magick_windows[i]->annotate_context,
15405 context_mask,&context_values);
15406 (void) XChangeGC(display,magick_windows[i]->widget_context,
15407 context_mask,&context_values);
15408 context_values.background=pixel->foreground_color.pixel;
15409 context_values.foreground=pixel->background_color.pixel;
15410 context_values.plane_mask=context_values.background ^
15411 context_values.foreground;
15412 (void) XChangeGC(display,magick_windows[i]->highlight_context,
15413 (size_t) (context_mask | GCPlaneMask),
15415 magick_windows[i]->attributes.background_pixel=
15416 pixel->background_color.pixel;
15417 magick_windows[i]->attributes.border_pixel=
15418 pixel->border_color.pixel;
15419 magick_windows[i]->attributes.colormap=map_info->colormap;
15420 (void) XChangeWindowAttributes(display,magick_windows[i]->id,
15421 (unsigned long) magick_windows[i]->mask,
15422 &magick_windows[i]->attributes);
15424 if (IfMagickTrue(windows->pan.mapped) )
15426 (void) XSetWindowBackgroundPixmap(display,windows->pan.id,
15427 windows->pan.pixmap);
15428 (void) XClearWindow(display,windows->pan.id);
15429 XDrawPanRectangle(display,windows);
15431 if (windows->backdrop.id != (Window) NULL)
15432 (void) XInstallColormap(display,map_info->colormap);
15435 if (*event.xclient.data.l == (long) windows->im_former_image)
15437 *state|=FormerImageState | ExitState;
15440 if (*event.xclient.data.l == (long) windows->im_next_image)
15442 *state|=NextImageState | ExitState;
15445 if (*event.xclient.data.l == (long) windows->im_retain_colors)
15447 *state|=RetainColorsState;
15450 if (*event.xclient.data.l == (long) windows->im_exit)
15457 if (event.xclient.message_type == windows->dnd_protocols)
15475 Display image named by the Drag-and-Drop selection.
15477 if ((*event.xclient.data.l != 2) && (*event.xclient.data.l != 128))
15479 selection=XInternAtom(display,"DndSelection",MagickFalse);
15480 status=XGetWindowProperty(display,root_window,selection,0L,(long)
15481 MaxTextExtent,MagickFalse,(Atom) AnyPropertyType,&type,&format,
15482 &length,&after,&data);
15483 if ((status != Success) || (length == 0))
15485 if (*event.xclient.data.l == 2)
15490 (void) CopyMagickString(resource_info->image_info->filename,
15491 (char *) data,MaxTextExtent);
15498 if (strncmp((char *) data, "file:", 5) != 0)
15500 (void) XFree((void *) data);
15503 (void) CopyMagickString(resource_info->image_info->filename,
15504 ((char *) data)+5,MaxTextExtent);
15506 nexus=ReadImage(resource_info->image_info,exception);
15507 CatchException(exception);
15508 if (nexus != (Image *) NULL)
15509 *state|=NextImageState | ExitState;
15510 (void) XFree((void *) data);
15514 If client window delete message, exit.
15516 if (event.xclient.message_type != windows->wm_protocols)
15518 if (*event.xclient.data.l != (long) windows->wm_delete_window)
15520 (void) XWithdrawWindow(display,event.xclient.window,
15521 visual_info->screen);
15522 if (event.xclient.window == windows->image.id)
15527 if (event.xclient.window == windows->pan.id)
15530 Restore original image size when pan window is deleted.
15532 windows->image.window_changes.width=windows->image.ximage->width;
15533 windows->image.window_changes.height=windows->image.ximage->height;
15534 (void) XConfigureImage(display,resource_info,windows,
15535 display_image,exception);
15539 case ConfigureNotify:
15541 if (IfMagickTrue(display_image->debug) )
15542 (void) LogMagickEvent(X11Event,GetMagickModule(),
15543 "Configure Notify: 0x%lx %dx%d+%d+%d %d",event.xconfigure.window,
15544 event.xconfigure.width,event.xconfigure.height,event.xconfigure.x,
15545 event.xconfigure.y,event.xconfigure.send_event);
15546 if (event.xconfigure.window == windows->image.id)
15549 Image window has a new configuration.
15551 if (event.xconfigure.send_event != 0)
15557 Position the transient windows relative of the Image window.
15559 if (windows->command.geometry == (char *) NULL)
15560 if (IfMagickFalse(windows->command.mapped) )
15562 windows->command.x=event.xconfigure.x-
15563 windows->command.width-25;
15564 windows->command.y=event.xconfigure.y;
15565 XConstrainWindowPosition(display,&windows->command);
15566 window_changes.x=windows->command.x;
15567 window_changes.y=windows->command.y;
15568 (void) XReconfigureWMWindow(display,windows->command.id,
15569 windows->command.screen,(unsigned int) (CWX | CWY),
15572 if (windows->widget.geometry == (char *) NULL)
15573 if (IfMagickFalse(windows->widget.mapped) )
15575 windows->widget.x=event.xconfigure.x+
15576 event.xconfigure.width/10;
15577 windows->widget.y=event.xconfigure.y+
15578 event.xconfigure.height/10;
15579 XConstrainWindowPosition(display,&windows->widget);
15580 window_changes.x=windows->widget.x;
15581 window_changes.y=windows->widget.y;
15582 (void) XReconfigureWMWindow(display,windows->widget.id,
15583 windows->widget.screen,(unsigned int) (CWX | CWY),
15586 if (windows->magnify.geometry == (char *) NULL)
15587 if (IfMagickFalse(windows->magnify.mapped) )
15589 windows->magnify.x=event.xconfigure.x+
15590 event.xconfigure.width+25;
15591 windows->magnify.y=event.xconfigure.y;
15592 XConstrainWindowPosition(display,&windows->magnify);
15593 window_changes.x=windows->magnify.x;
15594 window_changes.y=windows->magnify.y;
15595 (void) XReconfigureWMWindow(display,windows->magnify.id,
15596 windows->magnify.screen,(unsigned int) (CWX | CWY),
15599 if (windows->pan.geometry == (char *) NULL)
15600 if (IfMagickFalse(windows->pan.mapped) )
15602 windows->pan.x=event.xconfigure.x+
15603 event.xconfigure.width+25;
15604 windows->pan.y=event.xconfigure.y+
15605 windows->magnify.height+50;
15606 XConstrainWindowPosition(display,&windows->pan);
15607 window_changes.x=windows->pan.x;
15608 window_changes.y=windows->pan.y;
15609 (void) XReconfigureWMWindow(display,windows->pan.id,
15610 windows->pan.screen,(unsigned int) (CWX | CWY),
15614 if ((event.xconfigure.width == (int) windows->image.width) &&
15615 (event.xconfigure.height == (int) windows->image.height))
15617 windows->image.width=(unsigned int) event.xconfigure.width;
15618 windows->image.height=(unsigned int) event.xconfigure.height;
15619 windows->image.x=0;
15620 windows->image.y=0;
15621 if (display_image->montage != (char *) NULL)
15623 windows->image.x=vid_info.x;
15624 windows->image.y=vid_info.y;
15626 if (IfMagickTrue(windows->image.mapped) &&
15627 IfMagickTrue(windows->image.stasis) )
15630 Update image window configuration.
15632 windows->image.window_changes.width=event.xconfigure.width;
15633 windows->image.window_changes.height=event.xconfigure.height;
15634 (void) XConfigureImage(display,resource_info,windows,
15635 display_image,exception);
15638 Update pan window configuration.
15640 if ((event.xconfigure.width < windows->image.ximage->width) ||
15641 (event.xconfigure.height < windows->image.ximage->height))
15643 (void) XMapRaised(display,windows->pan.id);
15644 XDrawPanRectangle(display,windows);
15647 if (IfMagickTrue(windows->pan.mapped) )
15648 (void) XWithdrawWindow(display,windows->pan.id,
15649 windows->pan.screen);
15652 if (event.xconfigure.window == windows->magnify.id)
15658 Magnify window has a new configuration.
15660 windows->magnify.width=(unsigned int) event.xconfigure.width;
15661 windows->magnify.height=(unsigned int) event.xconfigure.height;
15662 if (IfMagickFalse(windows->magnify.mapped) )
15665 while ((int) magnify <= event.xconfigure.width)
15667 while ((int) magnify <= event.xconfigure.height)
15670 if (((int) magnify != event.xconfigure.width) ||
15671 ((int) magnify != event.xconfigure.height))
15673 window_changes.width=(int) magnify;
15674 window_changes.height=(int) magnify;
15675 (void) XReconfigureWMWindow(display,windows->magnify.id,
15676 windows->magnify.screen,(unsigned int) (CWWidth | CWHeight),
15680 if (IfMagickTrue(windows->magnify.mapped) &&
15681 IfMagickTrue(windows->magnify.stasis) )
15683 status=XMakeImage(display,resource_info,&windows->magnify,
15684 display_image,windows->magnify.width,windows->magnify.height,
15686 XMakeMagnifyImage(display,windows,exception);
15690 if (IfMagickTrue(windows->magnify.mapped) &&
15691 (event.xconfigure.window == windows->pan.id))
15694 Pan icon window has a new configuration.
15696 if (event.xconfigure.send_event != 0)
15698 windows->pan.x=event.xconfigure.x;
15699 windows->pan.y=event.xconfigure.y;
15701 windows->pan.width=(unsigned int) event.xconfigure.width;
15702 windows->pan.height=(unsigned int) event.xconfigure.height;
15705 if (event.xconfigure.window == windows->icon.id)
15708 Icon window has a new configuration.
15710 windows->icon.width=(unsigned int) event.xconfigure.width;
15711 windows->icon.height=(unsigned int) event.xconfigure.height;
15716 case DestroyNotify:
15719 Group leader has exited.
15721 if (IfMagickTrue(display_image->debug) )
15722 (void) LogMagickEvent(X11Event,GetMagickModule(),
15723 "Destroy Notify: 0x%lx",event.xdestroywindow.window);
15724 if (event.xdestroywindow.window == windows->group_leader.id)
15734 Selectively install colormap.
15736 if (map_info->colormap != XDefaultColormap(display,visual_info->screen))
15737 if (event.xcrossing.mode != NotifyUngrab)
15738 XInstallColormap(display,map_info->colormap);
15743 if (IfMagickTrue(display_image->debug) )
15744 (void) LogMagickEvent(X11Event,GetMagickModule(),
15745 "Expose: 0x%lx %dx%d+%d+%d",event.xexpose.window,
15746 event.xexpose.width,event.xexpose.height,event.xexpose.x,
15749 Refresh windows that are now exposed.
15751 if ((event.xexpose.window == windows->image.id) &&
15752 IfMagickTrue(windows->image.mapped) )
15754 XRefreshWindow(display,&windows->image,&event);
15755 delay=display_image->delay/MagickMax(
15756 display_image->ticks_per_second,1L);
15757 timer=time((time_t *) NULL)+(delay == 0 ? 1 : delay)+1;
15760 if ((event.xexpose.window == windows->magnify.id) &&
15761 IfMagickTrue(windows->magnify.mapped))
15763 XMakeMagnifyImage(display,windows,exception);
15766 if (event.xexpose.window == windows->pan.id)
15768 XDrawPanRectangle(display,windows);
15771 if (event.xexpose.window == windows->icon.id)
15773 XRefreshWindow(display,&windows->icon,&event);
15784 Respond to a user key press.
15786 length=XLookupString((XKeyEvent *) &event.xkey,command,(int)
15787 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
15788 *(command+length)='\0';
15789 if (IfMagickTrue(display_image->debug) )
15790 (void) LogMagickEvent(X11Event,GetMagickModule(),
15791 "Key press: %d 0x%lx (%s)",event.xkey.state,(unsigned long)
15792 key_symbol,command);
15793 if (event.xkey.window == windows->image.id)
15795 command_type=XImageWindowCommand(display,resource_info,windows,
15796 event.xkey.state,key_symbol,&display_image,exception);
15797 if (command_type != NullCommand)
15798 nexus=XMagickCommand(display,resource_info,windows,command_type,
15799 &display_image,exception);
15801 if (event.xkey.window == windows->magnify.id)
15802 XMagnifyWindowCommand(display,windows,event.xkey.state,key_symbol,
15804 if (event.xkey.window == windows->pan.id)
15806 if ((key_symbol == XK_q) || (key_symbol == XK_Escape))
15807 (void) XWithdrawWindow(display,windows->pan.id,
15808 windows->pan.screen);
15810 if ((key_symbol == XK_F1) || (key_symbol == XK_Help))
15811 XTextViewWidget(display,resource_info,windows,MagickFalse,
15812 "Help Viewer - Image Pan",ImagePanHelp);
15814 XTranslateImage(display,windows,*image,key_symbol);
15816 delay=display_image->delay/MagickMax(
15817 display_image->ticks_per_second,1L);
15818 timer=time((time_t *) NULL)+(delay == 0 ? 1 : delay)+1;
15824 Respond to a user key release.
15826 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
15827 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
15828 if (IfMagickTrue(display_image->debug) )
15829 (void) LogMagickEvent(X11Event,GetMagickModule(),
15830 "Key release: 0x%lx (%c)",(unsigned long) key_symbol,*command);
15836 Selectively uninstall colormap.
15838 if (map_info->colormap != XDefaultColormap(display,visual_info->screen))
15839 if (event.xcrossing.mode != NotifyUngrab)
15840 XUninstallColormap(display,map_info->colormap);
15845 if (IfMagickTrue(display_image->debug) )
15846 (void) LogMagickEvent(X11Event,GetMagickModule(),"Map Notify: 0x%lx",
15847 event.xmap.window);
15848 if (event.xmap.window == windows->backdrop.id)
15850 (void) XSetInputFocus(display,event.xmap.window,RevertToParent,
15852 windows->backdrop.mapped=MagickTrue;
15855 if (event.xmap.window == windows->image.id)
15857 if (windows->backdrop.id != (Window) NULL)
15858 (void) XInstallColormap(display,map_info->colormap);
15859 if (LocaleCompare(display_image->magick,"LOGO") == 0)
15861 if (LocaleCompare(display_image->filename,"LOGO") == 0)
15862 nexus=XOpenImage(display,resource_info,windows,MagickFalse);
15864 if (((int) windows->image.width < windows->image.ximage->width) ||
15865 ((int) windows->image.height < windows->image.ximage->height))
15866 (void) XMapRaised(display,windows->pan.id);
15867 windows->image.mapped=MagickTrue;
15870 if (event.xmap.window == windows->magnify.id)
15872 XMakeMagnifyImage(display,windows,exception);
15873 windows->magnify.mapped=MagickTrue;
15874 (void) XWithdrawWindow(display,windows->info.id,
15875 windows->info.screen);
15878 if (event.xmap.window == windows->pan.id)
15880 XMakePanImage(display,resource_info,windows,display_image,
15882 windows->pan.mapped=MagickTrue;
15885 if (event.xmap.window == windows->info.id)
15887 windows->info.mapped=MagickTrue;
15890 if (event.xmap.window == windows->icon.id)
15896 Create an icon image.
15898 taint=display_image->taint;
15899 XMakeStandardColormap(display,icon_visual,icon_resources,
15900 display_image,icon_map,icon_pixel,exception);
15901 (void) XMakeImage(display,icon_resources,&windows->icon,
15902 display_image,windows->icon.width,windows->icon.height,
15904 display_image->taint=taint;
15905 (void) XSetWindowBackgroundPixmap(display,windows->icon.id,
15906 windows->icon.pixmap);
15907 (void) XClearWindow(display,windows->icon.id);
15908 (void) XWithdrawWindow(display,windows->info.id,
15909 windows->info.screen);
15910 windows->icon.mapped=MagickTrue;
15913 if (event.xmap.window == windows->command.id)
15915 windows->command.mapped=MagickTrue;
15918 if (event.xmap.window == windows->popup.id)
15920 windows->popup.mapped=MagickTrue;
15923 if (event.xmap.window == windows->widget.id)
15925 windows->widget.mapped=MagickTrue;
15930 case MappingNotify:
15932 (void) XRefreshKeyboardMapping(&event.xmapping);
15937 case PropertyNotify:
15953 if (IfMagickTrue(display_image->debug) )
15954 (void) LogMagickEvent(X11Event,GetMagickModule(),
15955 "Property Notify: 0x%lx 0x%lx %d",event.xproperty.window,
15956 event.xproperty.atom,event.xproperty.state);
15957 if (event.xproperty.atom != windows->im_remote_command)
15960 Display image named by the remote command protocol.
15962 status=XGetWindowProperty(display,event.xproperty.window,
15963 event.xproperty.atom,0L,(long) MaxTextExtent,MagickFalse,(Atom)
15964 AnyPropertyType,&type,&format,&length,&after,&data);
15965 if ((status != Success) || (length == 0))
15967 if (LocaleCompare((char *) data,"-quit") == 0)
15969 XClientMessage(display,windows->image.id,windows->im_protocols,
15970 windows->im_exit,CurrentTime);
15971 (void) XFree((void *) data);
15974 (void) CopyMagickString(resource_info->image_info->filename,
15975 (char *) data,MaxTextExtent);
15976 (void) XFree((void *) data);
15977 nexus=ReadImage(resource_info->image_info,exception);
15978 CatchException(exception);
15979 if (nexus != (Image *) NULL)
15980 *state|=NextImageState | ExitState;
15983 case ReparentNotify:
15985 if (IfMagickTrue(display_image->debug) )
15986 (void) LogMagickEvent(X11Event,GetMagickModule(),
15987 "Reparent Notify: 0x%lx=>0x%lx",event.xreparent.parent,
15988 event.xreparent.window);
15993 if (IfMagickTrue(display_image->debug) )
15994 (void) LogMagickEvent(X11Event,GetMagickModule(),
15995 "Unmap Notify: 0x%lx",event.xunmap.window);
15996 if (event.xunmap.window == windows->backdrop.id)
15998 windows->backdrop.mapped=MagickFalse;
16001 if (event.xunmap.window == windows->image.id)
16003 windows->image.mapped=MagickFalse;
16006 if (event.xunmap.window == windows->magnify.id)
16008 windows->magnify.mapped=MagickFalse;
16011 if (event.xunmap.window == windows->pan.id)
16013 windows->pan.mapped=MagickFalse;
16016 if (event.xunmap.window == windows->info.id)
16018 windows->info.mapped=MagickFalse;
16021 if (event.xunmap.window == windows->icon.id)
16023 if (map_info->colormap == icon_map->colormap)
16024 XConfigureImageColormap(display,resource_info,windows,
16025 display_image,exception);
16026 (void) XFreeStandardColormap(display,icon_visual,icon_map,
16028 windows->icon.mapped=MagickFalse;
16031 if (event.xunmap.window == windows->command.id)
16033 windows->command.mapped=MagickFalse;
16036 if (event.xunmap.window == windows->popup.id)
16038 if (windows->backdrop.id != (Window) NULL)
16039 (void) XSetInputFocus(display,windows->image.id,RevertToParent,
16041 windows->popup.mapped=MagickFalse;
16044 if (event.xunmap.window == windows->widget.id)
16046 if (windows->backdrop.id != (Window) NULL)
16047 (void) XSetInputFocus(display,windows->image.id,RevertToParent,
16049 windows->widget.mapped=MagickFalse;
16056 if (IfMagickTrue(display_image->debug) )
16057 (void) LogMagickEvent(X11Event,GetMagickModule(),"Event type: %d",
16062 } while (!(*state & ExitState));
16063 if ((*state & ExitState) == 0)
16064 (void) XMagickCommand(display,resource_info,windows,FreeBuffersCommand,
16065 &display_image,exception);
16067 if (IfMagickTrue(resource_info->confirm_edit) )
16070 Query user if image has changed.
16072 if (IfMagickFalse(resource_info->immutable) &&
16073 IfMagickTrue(display_image->taint))
16078 status=XConfirmWidget(display,windows,"Your image changed.",
16079 "Do you want to save it");
16081 *state&=(~ExitState);
16084 (void) XMagickCommand(display,resource_info,windows,SaveCommand,
16085 &display_image,exception);
16088 if ((windows->visual_info->klass == GrayScale) ||
16089 (windows->visual_info->klass == PseudoColor) ||
16090 (windows->visual_info->klass == DirectColor))
16093 Withdraw pan and Magnify window.
16095 if (IfMagickTrue(windows->info.mapped) )
16096 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
16097 if (IfMagickTrue(windows->magnify.mapped) )
16098 (void) XWithdrawWindow(display,windows->magnify.id,
16099 windows->magnify.screen);
16100 if (IfMagickTrue(windows->command.mapped) )
16101 (void) XWithdrawWindow(display,windows->command.id,
16102 windows->command.screen);
16104 if (IfMagickTrue(windows->pan.mapped) )
16105 (void) XWithdrawWindow(display,windows->pan.id,windows->pan.screen);
16106 if (IfMagickFalse(resource_info->backdrop) )
16107 if (windows->backdrop.mapped)
16109 (void) XWithdrawWindow(display,windows->backdrop.id,
16110 windows->backdrop.screen);
16111 (void) XDestroyWindow(display,windows->backdrop.id);
16112 windows->backdrop.id=(Window) NULL;
16113 (void) XWithdrawWindow(display,windows->image.id,
16114 windows->image.screen);
16115 (void) XDestroyWindow(display,windows->image.id);
16116 windows->image.id=(Window) NULL;
16118 XSetCursorState(display,windows,MagickTrue);
16119 XCheckRefreshWindows(display,windows);
16120 if (((*state & FormerImageState) != 0) || ((*state & NextImageState) != 0))
16121 *state&=(~ExitState);
16122 if (*state & ExitState)
16125 Free Standard Colormap.
16127 (void) XFreeStandardColormap(display,icon_visual,icon_map,icon_pixel);
16128 if (resource_info->map_type == (char *) NULL)
16129 (void) XFreeStandardColormap(display,visual_info,map_info,pixel);
16133 if (resource_info->copy_image != (Image *) NULL)
16135 resource_info->copy_image=DestroyImage(resource_info->copy_image);
16136 resource_info->copy_image=NewImageList();
16138 DestroyXResources();
16140 (void) XSync(display,MagickFalse);
16142 Restore our progress monitor and warning handlers.
16144 (void) SetErrorHandler(warning_handler);
16145 (void) SetWarningHandler(warning_handler);
16147 Change to home directory.
16149 directory=getcwd(working_directory,MaxTextExtent);
16155 if (*resource_info->home_directory == '\0')
16156 (void) CopyMagickString(resource_info->home_directory,".",MaxTextExtent);
16157 status=chdir(resource_info->home_directory);
16159 (void) ThrowMagickException(exception,GetMagickModule(),FileOpenError,
16160 "UnableToOpenFile","%s",resource_info->home_directory);
16162 *image=display_image;
16168 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
16172 + D i s p l a y I m a g e s %
16176 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
16178 % DisplayImages() displays an image sequence to any X window screen. It
16179 % returns a value other than 0 if successful. Check the exception member
16180 % of image to determine the reason for any failure.
16182 % The format of the DisplayImages method is:
16184 % MagickBooleanType DisplayImages(const ImageInfo *image_info,
16185 % Image *images,ExceptionInfo *exception)
16187 % A description of each parameter follows:
16189 % o image_info: the image info.
16191 % o image: the image.
16193 % o exception: return any errors or warnings in this structure.
16196 MagickExport MagickBooleanType DisplayImages(const ImageInfo *image_info,
16197 Image *image,ExceptionInfo *exception)
16199 assert(image_info != (const ImageInfo *) NULL);
16200 assert(image_info->signature == MagickSignature);
16201 assert(image != (Image *) NULL);
16202 assert(image->signature == MagickSignature);
16204 if (IfMagickTrue(image->debug) )
16205 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
16206 (void) ThrowMagickException(exception,GetMagickModule(),MissingDelegateError,
16207 "DelegateLibrarySupportNotBuiltIn","'%s' (X11)",image->filename);
16208 return(MagickFalse);
16212 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
16216 + R e m o t e D i s p l a y C o m m a n d %
16220 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
16222 % RemoteDisplayCommand() encourages a remote display program to display the
16223 % specified image filename.
16225 % The format of the RemoteDisplayCommand method is:
16227 % MagickBooleanType RemoteDisplayCommand(const ImageInfo *image,
16228 % const char *window,const char *filename,ExceptionInfo *exception)
16230 % A description of each parameter follows:
16232 % o image_info: the image info.
16234 % o window: Specifies the name or id of an X window.
16236 % o filename: the name of the image filename to display.
16238 % o exception: return any errors or warnings in this structure.
16241 MagickExport MagickBooleanType RemoteDisplayCommand(const ImageInfo *image_info,
16242 const char *window,const char *filename,ExceptionInfo *exception)
16244 assert(image_info != (const ImageInfo *) NULL);
16245 assert(image_info->signature == MagickSignature);
16246 assert(filename != (char *) NULL);
16248 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
16249 (void) ThrowMagickException(exception,GetMagickModule(),MissingDelegateError,
16250 "DelegateLibrarySupportNotBuiltIn","'%s' (X11)",image_info->filename);
16251 return(MagickFalse);