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-2011 ImageMagick Studio LLC, a non-profit organization %
21 % dedicated to making software imaging solutions freely available. %
23 % You may not use this file except in compliance with the License. You may %
24 % obtain a copy of the License at %
26 % http://www.imagemagick.org/script/license.php %
28 % Unless required by applicable law or agreed to in writing, software %
29 % distributed under the License is distributed on an "AS IS" BASIS, %
30 % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
31 % See the License for the specific language governing permissions and %
32 % limitations under the License. %
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
42 #include "MagickCore/studio.h"
43 #include "MagickCore/artifact.h"
44 #include "MagickCore/blob.h"
45 #include "MagickCore/cache.h"
46 #include "MagickCore/client.h"
47 #include "MagickCore/color.h"
48 #include "MagickCore/colorspace.h"
49 #include "MagickCore/composite.h"
50 #include "MagickCore/constitute.h"
51 #include "MagickCore/decorate.h"
52 #include "MagickCore/delegate.h"
53 #include "MagickCore/display.h"
54 #include "MagickCore/display-private.h"
55 #include "MagickCore/draw.h"
56 #include "MagickCore/effect.h"
57 #include "MagickCore/enhance.h"
58 #include "MagickCore/exception.h"
59 #include "MagickCore/exception-private.h"
60 #include "MagickCore/fx.h"
61 #include "MagickCore/geometry.h"
62 #include "MagickCore/image.h"
63 #include "MagickCore/image-private.h"
64 #include "MagickCore/list.h"
65 #include "MagickCore/log.h"
66 #include "MagickCore/magick.h"
67 #include "MagickCore/memory_.h"
68 #include "MagickCore/monitor.h"
69 #include "MagickCore/monitor-private.h"
70 #include "MagickCore/montage.h"
71 #include "MagickCore/option.h"
72 #include "MagickCore/paint.h"
73 #include "MagickCore/pixel.h"
74 #include "MagickCore/pixel-accessor.h"
75 #include "MagickCore/PreRvIcccm.h"
76 #include "MagickCore/property.h"
77 #include "MagickCore/quantum.h"
78 #include "MagickCore/quantum-private.h"
79 #include "MagickCore/resize.h"
80 #include "MagickCore/resource_.h"
81 #include "MagickCore/shear.h"
82 #include "MagickCore/segment.h"
83 #include "MagickCore/string_.h"
84 #include "MagickCore/string-private.h"
85 #include "MagickCore/transform.h"
86 #include "MagickCore/threshold.h"
87 #include "MagickCore/utility.h"
88 #include "MagickCore/utility-private.h"
89 #include "MagickCore/version.h"
90 #include "MagickCore/widget.h"
91 #include "MagickCore/widget-private.h"
92 #include "MagickCore/xwindow.h"
93 #include "MagickCore/xwindow-private.h"
95 #if defined(MAGICKCORE_X11_DELEGATE)
99 #define MaxColors MagickMin((ssize_t) windows->visual_info->colormap_size,256L)
102 Constant declarations.
104 static const unsigned char
107 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55
111 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
115 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
139 Help widget declarations.
142 *ImageAnnotateHelp[] =
144 "In annotate mode, the Command widget has these options:",
194 "Choose a font name from the Font Name sub-menu. Additional",
195 "font names can be specified with the font browser. You can",
196 "change the menu names by setting the X resources font1",
199 "Choose a font color from the Font Color sub-menu.",
200 "Additional font colors can be specified with the color",
201 "browser. You can change the menu colors by setting the X",
202 "resources pen1 through pen9.",
204 "If you select the color browser and press Grab, you can",
205 "choose the font color by moving the pointer to the desired",
206 "color on the screen and press any button.",
208 "If you choose to rotate the text, choose Rotate Text from the",
209 "menu and select an angle. Typically you will only want to",
210 "rotate one line of text at a time. Depending on the angle you",
211 "choose, subsequent lines may end up overwriting each other.",
213 "Choosing a font and its color is optional. The default font",
214 "is fixed and the default color is black. However, you must",
215 "choose a location to begin entering text and press button 1.",
216 "An underscore character will appear at the location of the",
217 "pointer. The cursor changes to a pencil to indicate you are",
218 "in text mode. To exit immediately, press Dismiss.",
220 "In text mode, any key presses will display the character at",
221 "the location of the underscore and advance the underscore",
222 "cursor. Enter your text and once completed press Apply to",
223 "finish your image annotation. To correct errors press BACK",
224 "SPACE. To delete an entire line of text, press DELETE. Any",
225 "text that exceeds the boundaries of the image window is",
226 "automagically continued onto the next line.",
228 "The actual color you request for the font is saved in the",
229 "image. However, the color that appears in your image window",
230 "may be different. For example, on a monochrome screen the",
231 "text will appear black or white even if you choose the color",
232 "red as the font color. However, the image saved to a file",
233 "with -write is written with red lettering. To assure the",
234 "correct color text in the final image, any PseudoClass image",
235 "is promoted to DirectClass (see miff(5)). To force a",
236 "PseudoClass image to remain PseudoClass, use -colors.",
241 "In chop mode, the Command widget has these options:",
249 "If the you choose the horizontal direction (this the",
250 "default), the area of the image between the two horizontal",
251 "endpoints of the chop line is removed. Otherwise, the area",
252 "of the image between the two vertical endpoints of the chop",
255 "Select a location within the image window to begin your chop,",
256 "press and hold any button. Next, move the pointer to",
257 "another location in the image. As you move a line will",
258 "connect the initial location and the pointer. When you",
259 "release the button, the area within the image to chop is",
260 "determined by which direction you choose from the Command",
263 "To cancel the image chopping, move the pointer back to the",
264 "starting point of the line and release the button.",
267 *ImageColorEditHelp[] =
269 "In color edit mode, the Command widget has these options:",
310 "Choose a color editing method from the Method sub-menu",
311 "of the Command widget. The point method recolors any pixel",
312 "selected with the pointer until the button is released. The",
313 "replace method recolors any pixel that matches the color of",
314 "the pixel you select with a button press. Floodfill recolors",
315 "any pixel that matches the color of the pixel you select with",
316 "a button press and is a neighbor. Whereas filltoborder recolors",
317 "any neighbor pixel that is not the border color. Finally reset",
318 "changes the entire image to the designated color.",
320 "Next, choose a pixel color from the Pixel Color sub-menu.",
321 "Additional pixel colors can be specified with the color",
322 "browser. You can change the menu colors by setting the X",
323 "resources pen1 through pen9.",
325 "Now press button 1 to select a pixel within the image window",
326 "to change its color. Additional pixels may be recolored as",
327 "prescribed by the method you choose.",
329 "If the Magnify widget is mapped, it can be helpful in positioning",
330 "your pointer within the image (refer to button 2).",
332 "The actual color you request for the pixels is saved in the",
333 "image. However, the color that appears in your image window",
334 "may be different. For example, on a monochrome screen the",
335 "pixel will appear black or white even if you choose the",
336 "color red as the pixel color. However, the image saved to a",
337 "file with -write is written with red pixels. To assure the",
338 "correct color text in the final image, any PseudoClass image",
339 "is promoted to DirectClass (see miff(5)). To force a",
340 "PseudoClass image to remain PseudoClass, use -colors.",
343 *ImageCompositeHelp[] =
345 "First a widget window is displayed requesting you to enter an",
346 "image name. Press Composite, Grab or type a file name.",
347 "Press Cancel if you choose not to create a composite image.",
348 "When you choose Grab, move the pointer to the desired window",
349 "and press any button.",
351 "If the Composite image does not have any matte information,",
352 "you are informed and the file browser is displayed again.",
353 "Enter the name of a mask image. The image is typically",
354 "grayscale and the same size as the composite image. If the",
355 "image is not grayscale, it is converted to grayscale and the",
356 "resulting intensities are used as matte information.",
358 "A small window appears showing the location of the cursor in",
359 "the image window. You are now in composite mode. To exit",
360 "immediately, press Dismiss. In composite mode, the Command",
361 "widget has these options:",
387 "Choose a composite operation from the Operators sub-menu of",
388 "the Command widget. How each operator behaves is described",
389 "below. Image window is the image currently displayed on",
390 "your X server and image is the image obtained with the File",
393 "Over The result is the union of the two image shapes,",
394 " with image obscuring image window in the region of",
397 "In The result is simply image cut by the shape of",
398 " image window. None of the image data of image",
399 " window is in the result.",
401 "Out The resulting image is image with the shape of",
402 " image window cut out.",
404 "Atop The result is the same shape as image image window,",
405 " with image obscuring image window where the image",
406 " shapes overlap. Note this differs from over",
407 " because the portion of image outside image window's",
408 " shape does not appear in the result.",
410 "Xor The result is the image data from both image and",
411 " image window that is outside the overlap region.",
412 " The overlap region is blank.",
414 "Plus The result is just the sum of the image data.",
415 " Output values are cropped to QuantumRange (no overflow).",
417 "Minus The result of image - image window, with underflow",
420 "Add The result of image + image window, with overflow",
421 " wrapping around (mod 256).",
423 "Subtract The result of image - image window, with underflow",
424 " wrapping around (mod 256). The add and subtract",
425 " operators can be used to perform reversible",
429 " The result of abs(image - image window). This",
430 " useful for comparing two very similar images.",
433 " The result of image * image window. This",
434 " useful for the creation of drop-shadows.",
436 "Bumpmap The result of surface normals from image * image",
439 "Copy The resulting image is image window replaced with",
440 " image. Here the matte information is ignored.",
442 "CopyRed The red layer of the image window is replace with",
443 " the red layer of the image. The other layers are",
447 " The green layer of the image window is replace with",
448 " the green layer of the image. The other layers are",
451 "CopyBlue The blue layer of the image window is replace with",
452 " the blue layer of the image. The other layers are",
456 " The matte layer of the image window is replace with",
457 " the matte layer of the image. The other layers are",
460 "The image compositor requires a matte, or alpha channel in",
461 "the image for some operations. This extra channel usually",
462 "defines a mask which represents a sort of a cookie-cutter",
463 "for the image. This the case when matte is opaque (full",
464 "coverage) for pixels inside the shape, zero outside, and",
465 "between 0 and QuantumRange on the boundary. If image does not",
466 "have a matte channel, it is initialized with 0 for any pixel",
467 "matching in color to pixel location (0,0), otherwise QuantumRange.",
469 "If you choose Dissolve, the composite operator becomes Over. The",
470 "image matte channel percent transparency is initialized to factor.",
471 "The image window is initialized to (100-factor). Where factor is the",
472 "value you specify in the Dialog widget.",
474 "Displace shifts the image pixels as defined by a displacement",
475 "map. With this option, image is used as a displacement map.",
476 "Black, within the displacement map, is a maximum positive",
477 "displacement. White is a maximum negative displacement and",
478 "middle gray is neutral. The displacement is scaled to determine",
479 "the pixel shift. By default, the displacement applies in both the",
480 "horizontal and vertical directions. However, if you specify a mask,",
481 "image is the horizontal X displacement and mask the vertical Y",
484 "Note that matte information for image window is not retained",
485 "for colormapped X server visuals (e.g. StaticColor,",
486 "StaticColor, GrayScale, PseudoColor). Correct compositing",
487 "behavior may require a TrueColor or DirectColor visual or a",
488 "Standard Colormap.",
490 "Choosing a composite operator is optional. The default",
491 "operator is replace. However, you must choose a location to",
492 "composite your image and press button 1. Press and hold the",
493 "button before releasing and an outline of the image will",
494 "appear to help you identify your location.",
496 "The actual colors of the composite image is saved. However,",
497 "the color that appears in image window may be different.",
498 "For example, on a monochrome screen image window will appear",
499 "black or white even though your composited image may have",
500 "many colors. If the image is saved to a file it is written",
501 "with the correct colors. To assure the correct colors are",
502 "saved in the final image, any PseudoClass image is promoted",
503 "to DirectClass (see miff(5)). To force a PseudoClass image",
504 "to remain PseudoClass, use -colors.",
509 "In cut mode, the Command widget has these options:",
514 "To define a cut region, press button 1 and drag. The",
515 "cut region is defined by a highlighted rectangle that",
516 "expands or contracts as it follows the pointer. Once you",
517 "are satisfied with the cut region, release the button.",
518 "You are now in rectify mode. In rectify mode, the Command",
519 "widget has these options:",
525 "You can make adjustments by moving the pointer to one of the",
526 "cut rectangle corners, pressing a button, and dragging.",
527 "Finally, press Cut to commit your copy region. To",
528 "exit without cutting the image, press Dismiss.",
533 "In copy mode, the Command widget has these options:",
538 "To define a copy region, press button 1 and drag. The",
539 "copy region is defined by a highlighted rectangle that",
540 "expands or contracts as it follows the pointer. Once you",
541 "are satisfied with the copy region, release the button.",
542 "You are now in rectify mode. In rectify mode, the Command",
543 "widget has these options:",
549 "You can make adjustments by moving the pointer to one of the",
550 "copy rectangle corners, pressing a button, and dragging.",
551 "Finally, press Copy to commit your copy region. To",
552 "exit without copying the image, press Dismiss.",
557 "In crop mode, the Command widget has these options:",
562 "To define a cropping region, press button 1 and drag. The",
563 "cropping region is defined by a highlighted rectangle that",
564 "expands or contracts as it follows the pointer. Once you",
565 "are satisfied with the cropping region, release the button.",
566 "You are now in rectify mode. In rectify mode, the Command",
567 "widget has these options:",
573 "You can make adjustments by moving the pointer to one of the",
574 "cropping rectangle corners, pressing a button, and dragging.",
575 "Finally, press Crop to commit your cropping region. To",
576 "exit without cropping the image, press Dismiss.",
581 "The cursor changes to a crosshair to indicate you are in",
582 "draw mode. To exit immediately, press Dismiss. In draw mode,",
583 "the Command widget has these options:",
628 "Choose a drawing primitive from the Element sub-menu.",
630 "Choose a color from the Color sub-menu. Additional",
631 "colors can be specified with the color browser.",
633 "If you choose the color browser and press Grab, you can",
634 "select the color by moving the pointer to the desired",
635 "color on the screen and press any button. The transparent",
636 "color updates the image matte channel and is useful for",
637 "image compositing.",
639 "Choose a stipple, if appropriate, from the Stipple sub-menu.",
640 "Additional stipples can be specified with the file browser.",
641 "Stipples obtained from the file browser must be on disk in the",
642 "X11 bitmap format.",
644 "Choose a width, if appropriate, from the Width sub-menu. To",
645 "choose a specific width select the Dialog widget.",
647 "Choose a point in the Image window and press button 1 and",
648 "hold. Next, move the pointer to another location in the",
649 "image. As you move, a line connects the initial location and",
650 "the pointer. When you release the button, the image is",
651 "updated with the primitive you just drew. For polygons, the",
652 "image is updated when you press and release the button without",
653 "moving the pointer.",
655 "To cancel image drawing, move the pointer back to the",
656 "starting point of the line and release the button.",
662 " The effects of each button press is described below. Three",
663 " buttons are required. If you have a two button mouse,",
664 " button 1 and 3 are returned. Press ALT and button 3 to",
665 " simulate button 2.",
667 " 1 Press this button to map or unmap the Command widget.",
669 " 2 Press and drag to define a region of the image to",
672 " 3 Press and drag to choose from a select set of commands.",
673 " This button behaves differently if the image being",
674 " displayed is a visual image directory. Here, choose a",
675 " particular tile of the directory and press this button and",
676 " drag to select a command from a pop-up menu. Choose from",
677 " these menu items:",
685 " If you choose Open, the image represented by the tile is",
686 " displayed. To return to the visual image directory, choose",
687 " Next from the Command widget. Next and Former moves to the",
688 " next or former image respectively. Choose Delete to delete",
689 " a particular image tile. Finally, choose Update to",
690 " synchronize all the image tiles with their respective",
694 " The Command widget lists a number of sub-menus and commands.",
706 " Visual Directory...",
740 " Contrast Stretch...",
741 " Sigmoidal Contrast...",
769 " Charcoal Drawing...",
780 " Region of Interest...",
792 " Browse Documentation",
795 " Menu items with a indented triangle have a sub-menu. They",
796 " are represented above as the indented items. To access a",
797 " sub-menu item, move the pointer to the appropriate menu and",
798 " press a button and drag. When you find the desired sub-menu",
799 " item, release the button and the command is executed. Move",
800 " the pointer away from the sub-menu if you decide not to",
801 " execute a particular command.",
803 "KEYBOARD ACCELERATORS",
804 " Accelerators are one or two key presses that effect a",
805 " particular command. The keyboard accelerators that",
806 " display(1) understands is:",
808 " Ctl+O Press to open an image from a file.",
810 " space Press to display the next image.",
812 " If the image is a multi-paged document such as a Postscript",
813 " document, you can skip ahead several pages by preceding",
814 " this command with a number. For example to display the",
815 " third page beyond the current page, press 3<space>.",
817 " backspace Press to display the former image.",
819 " If the image is a multi-paged document such as a Postscript",
820 " document, you can skip behind several pages by preceding",
821 " this command with a number. For example to display the",
822 " third page preceding the current page, press 3<backspace>.",
824 " Ctl+S Press to write the image to a file.",
826 " Ctl+P Press to print the image to a Postscript printer.",
828 " Ctl+D Press to delete an image file.",
830 " Ctl+N Press to create a blank canvas.",
832 " Ctl+Q Press to discard all images and exit program.",
834 " Ctl+Z Press to undo last image transformation.",
836 " Ctl+R Press to redo last image transformation.",
838 " Ctl+X Press to cut a region of the image.",
840 " Ctl+C Press to copy a region of the image.",
842 " Ctl+V Press to paste a region to the image.",
844 " < Press to half the image size.",
846 " - Press to return to the original image size.",
848 " > Press to double the image size.",
850 " % Press to resize the image to a width and height you",
853 "Cmd-A Press to make any image transformations permanent."
855 " By default, any image size transformations are applied",
856 " to the original image to create the image displayed on",
857 " the X server. However, the transformations are not",
858 " permanent (i.e. the original image does not change",
859 " size only the X image does). For example, if you",
860 " press > the X image will appear to double in size,",
861 " but the original image will in fact remain the same size.",
862 " To force the original image to double in size, press >",
863 " followed by Cmd-A.",
865 " @ Press to refresh the image window.",
867 " C Press to cut out a rectangular region of the image.",
869 " [ Press to chop the image.",
871 " H Press to flop image in the horizontal direction.",
873 " V Press to flip image in the vertical direction.",
875 " / Press to rotate the image 90 degrees clockwise.",
877 " \\ Press to rotate the image 90 degrees counter-clockwise.",
879 " * Press to rotate the image the number of degrees you",
882 " S Press to shear the image the number of degrees you",
885 " R Press to roll the image.",
887 " T Press to trim the image edges.",
889 " Shft-H Press to vary the image hue.",
891 " Shft-S Press to vary the color saturation.",
893 " Shft-L Press to vary the color brightness.",
895 " Shft-G Press to gamma correct the image.",
897 " Shft-C Press to sharpen the image contrast.",
899 " Shft-Z Press to dull the image contrast.",
901 " = Press to perform histogram equalization on the image.",
903 " Shft-N Press to perform histogram normalization on the image.",
905 " Shft-~ Press to negate the colors of the image.",
907 " . Press to convert the image colors to gray.",
909 " Shft-# Press to set the maximum number of unique colors in the",
912 " F2 Press to reduce the speckles in an image.",
914 " F3 Press to eliminate peak noise from an image.",
916 " F4 Press to add noise to an image.",
918 " F5 Press to sharpen an image.",
920 " F6 Press to delete an image file.",
922 " F7 Press to threshold the image.",
924 " F8 Press to detect edges within an image.",
926 " F9 Press to emboss an image.",
928 " F10 Press to displace pixels by a random amount.",
930 " F11 Press to negate all pixels above the threshold level.",
932 " F12 Press to shade the image using a distant light source.",
934 " F13 Press to lighten or darken image edges to create a 3-D effect.",
936 " F14 Press to segment the image by color.",
938 " Meta-S Press to swirl image pixels about the center.",
940 " Meta-I Press to implode image pixels about the center.",
942 " Meta-W Press to alter an image along a sine wave.",
944 " Meta-P Press to simulate an oil painting.",
946 " Meta-C Press to simulate a charcoal drawing.",
948 " Alt-A Press to annotate the image with text.",
950 " Alt-D Press to draw on an image.",
952 " Alt-P Press to edit an image pixel color.",
954 " Alt-M Press to edit the image matte information.",
956 " Alt-V Press to composite the image with another.",
958 " Alt-B Press to add a border to the image.",
960 " Alt-F Press to add an ornamental border to the image.",
963 " Press to add an image comment.",
965 " Ctl-A Press to apply image processing techniques to a region",
968 " Shft-? Press to display information about the image.",
970 " Shft-+ Press to map the zoom image window.",
972 " Shft-P Press to preview an image enhancement, effect, or f/x.",
974 " F1 Press to display helpful information about display(1).",
976 " Find Press to browse documentation about ImageMagick.",
978 " 1-9 Press to change the level of magnification.",
980 " Use the arrow keys to move the image one pixel up, down,",
981 " left, or right within the magnify window. Be sure to first",
982 " map the magnify window by pressing button 2.",
984 " Press ALT and one of the arrow keys to trim off one pixel",
985 " from any side of the image.",
988 *ImageMatteEditHelp[] =
990 "Matte information within an image is useful for some",
991 "operations such as image compositing (See IMAGE",
992 "COMPOSITING). This extra channel usually defines a mask",
993 "which represents a sort of a cookie-cutter for the image.",
994 "This the case when matte is opaque (full coverage) for",
995 "pixels inside the shape, zero outside, and between 0 and",
996 "QuantumRange on the boundary.",
998 "A small window appears showing the location of the cursor in",
999 "the image window. You are now in matte edit mode. To exit",
1000 "immediately, press Dismiss. In matte edit mode, the Command",
1001 "widget has these options:",
1035 "Choose a matte editing method from the Method sub-menu of",
1036 "the Command widget. The point method changes the matte value",
1037 "of any pixel selected with the pointer until the button is",
1038 "is released. The replace method changes the matte value of",
1039 "any pixel that matches the color of the pixel you select with",
1040 "a button press. Floodfill changes the matte value of any pixel",
1041 "that matches the color of the pixel you select with a button",
1042 "press and is a neighbor. Whereas filltoborder changes the matte",
1043 "value any neighbor pixel that is not the border color. Finally",
1044 "reset changes the entire image to the designated matte value.",
1046 "Choose Matte Value and pick Opaque or Transarent. For other values",
1047 "select the Dialog entry. Here a dialog appears requesting a matte",
1048 "value. The value you select is assigned as the opacity value of the",
1049 "selected pixel or pixels.",
1051 "Now, press any button to select a pixel within the image",
1052 "window to change its matte value.",
1054 "If the Magnify widget is mapped, it can be helpful in positioning",
1055 "your pointer within the image (refer to button 2).",
1057 "Matte information is only valid in a DirectClass image.",
1058 "Therefore, any PseudoClass image is promoted to DirectClass",
1059 "(see miff(5)). Note that matte information for PseudoClass",
1060 "is not retained for colormapped X server visuals (e.g.",
1061 "StaticColor, StaticColor, GrayScale, PseudoColor) unless you",
1062 "immediately save your image to a file (refer to Write).",
1063 "Correct matte editing behavior may require a TrueColor or",
1064 "DirectColor visual or a Standard Colormap.",
1069 "When an image exceeds the width or height of the X server",
1070 "screen, display maps a small panning icon. The rectangle",
1071 "within the panning icon shows the area that is currently",
1072 "displayed in the image window. To pan about the image,",
1073 "press any button and drag the pointer within the panning",
1074 "icon. The pan rectangle moves with the pointer and the",
1075 "image window is updated to reflect the location of the",
1076 "rectangle within the panning icon. When you have selected",
1077 "the area of the image you wish to view, release the button.",
1079 "Use the arrow keys to pan the image one pixel up, down,",
1080 "left, or right within the image window.",
1082 "The panning icon is withdrawn if the image becomes smaller",
1083 "than the dimensions of the X server screen.",
1088 "A small window appears showing the location of the cursor in",
1089 "the image window. You are now in paste mode. To exit",
1090 "immediately, press Dismiss. In paste mode, the Command",
1091 "widget has these options:",
1108 "Choose a composite operation from the Operators sub-menu of",
1109 "the Command widget. How each operator behaves is described",
1110 "below. Image window is the image currently displayed on",
1111 "your X server and image is the image obtained with the File",
1114 "Over The result is the union of the two image shapes,",
1115 " with image obscuring image window in the region of",
1118 "In The result is simply image cut by the shape of",
1119 " image window. None of the image data of image",
1120 " window is in the result.",
1122 "Out The resulting image is image with the shape of",
1123 " image window cut out.",
1125 "Atop The result is the same shape as image image window,",
1126 " with image obscuring image window where the image",
1127 " shapes overlap. Note this differs from over",
1128 " because the portion of image outside image window's",
1129 " shape does not appear in the result.",
1131 "Xor The result is the image data from both image and",
1132 " image window that is outside the overlap region.",
1133 " The overlap region is blank.",
1135 "Plus The result is just the sum of the image data.",
1136 " Output values are cropped to QuantumRange (no overflow).",
1137 " This operation is independent of the matte",
1140 "Minus The result of image - image window, with underflow",
1141 " cropped to zero.",
1143 "Add The result of image + image window, with overflow",
1144 " wrapping around (mod 256).",
1146 "Subtract The result of image - image window, with underflow",
1147 " wrapping around (mod 256). The add and subtract",
1148 " operators can be used to perform reversible",
1149 " transformations.",
1152 " The result of abs(image - image window). This",
1153 " useful for comparing two very similar images.",
1155 "Copy The resulting image is image window replaced with",
1156 " image. Here the matte information is ignored.",
1158 "CopyRed The red layer of the image window is replace with",
1159 " the red layer of the image. The other layers are",
1163 " The green layer of the image window is replace with",
1164 " the green layer of the image. The other layers are",
1167 "CopyBlue The blue layer of the image window is replace with",
1168 " the blue layer of the image. The other layers are",
1172 " The matte layer of the image window is replace with",
1173 " the matte layer of the image. The other layers are",
1176 "The image compositor requires a matte, or alpha channel in",
1177 "the image for some operations. This extra channel usually",
1178 "defines a mask which represents a sort of a cookie-cutter",
1179 "for the image. This the case when matte is opaque (full",
1180 "coverage) for pixels inside the shape, zero outside, and",
1181 "between 0 and QuantumRange on the boundary. If image does not",
1182 "have a matte channel, it is initialized with 0 for any pixel",
1183 "matching in color to pixel location (0,0), otherwise QuantumRange.",
1185 "Note that matte information for image window is not retained",
1186 "for colormapped X server visuals (e.g. StaticColor,",
1187 "StaticColor, GrayScale, PseudoColor). Correct compositing",
1188 "behavior may require a TrueColor or DirectColor visual or a",
1189 "Standard Colormap.",
1191 "Choosing a composite operator is optional. The default",
1192 "operator is replace. However, you must choose a location to",
1193 "paste your image and press button 1. Press and hold the",
1194 "button before releasing and an outline of the image will",
1195 "appear to help you identify your location.",
1197 "The actual colors of the pasted image is saved. However,",
1198 "the color that appears in image window may be different.",
1199 "For example, on a monochrome screen image window will appear",
1200 "black or white even though your pasted image may have",
1201 "many colors. If the image is saved to a file it is written",
1202 "with the correct colors. To assure the correct colors are",
1203 "saved in the final image, any PseudoClass image is promoted",
1204 "to DirectClass (see miff(5)). To force a PseudoClass image",
1205 "to remain PseudoClass, use -colors.",
1210 "In region of interest mode, the Command widget has these",
1216 "To define a region of interest, press button 1 and drag.",
1217 "The region of interest is defined by a highlighted rectangle",
1218 "that expands or contracts as it follows the pointer. Once",
1219 "you are satisfied with the region of interest, release the",
1220 "button. You are now in apply mode. In apply mode the",
1221 "Command widget has these options:",
1241 " Contrast Stretch",
1242 " Sigmoidal Contrast...",
1269 " Charcoal Drawing...",
1279 "You can make adjustments to the region of interest by moving",
1280 "the pointer to one of the rectangle corners, pressing a",
1281 "button, and dragging. Finally, choose an image processing",
1282 "technique from the Command widget. You can choose more than",
1283 "one image processing technique to apply to an area.",
1284 "Alternatively, you can move the region of interest before",
1285 "applying another image processing technique. To exit, press",
1289 *ImageRotateHelp[] =
1291 "In rotate mode, the Command widget has these options:",
1310 "Choose a background color from the Pixel Color sub-menu.",
1311 "Additional background colors can be specified with the color",
1312 "browser. You can change the menu colors by setting the X",
1313 "resources pen1 through pen9.",
1315 "If you choose the color browser and press Grab, you can",
1316 "select the background color by moving the pointer to the",
1317 "desired color on the screen and press any button.",
1319 "Choose a point in the image window and press this button and",
1320 "hold. Next, move the pointer to another location in the",
1321 "image. As you move a line connects the initial location and",
1322 "the pointer. When you release the button, the degree of",
1323 "image rotation is determined by the slope of the line you",
1324 "just drew. The slope is relative to the direction you",
1325 "choose from the Direction sub-menu of the Command widget.",
1327 "To cancel the image rotation, move the pointer back to the",
1328 "starting point of the line and release the button.",
1333 Enumeration declarations.
1352 VisualDirectoryCommand,
1360 OriginalSizeCommand,
1382 ContrastStretchCommand,
1383 SigmoidalContrastCommand,
1409 CharcoalDrawCommand,
1419 RegionofInterestCommand,
1425 ShowHistogramCommand,
1431 BrowseDocumentationCommand,
1433 SaveToUndoBufferCommand,
1440 AnnotateNameCommand,
1441 AnnotateFontColorCommand,
1442 AnnotateBackgroundColorCommand,
1443 AnnotateRotateCommand,
1444 AnnotateHelpCommand,
1445 AnnotateDismissCommand,
1448 ChopDirectionCommand,
1451 HorizontalChopCommand,
1452 VerticalChopCommand,
1453 ColorEditMethodCommand,
1454 ColorEditColorCommand,
1455 ColorEditBorderCommand,
1456 ColorEditFuzzCommand,
1457 ColorEditUndoCommand,
1458 ColorEditHelpCommand,
1459 ColorEditDismissCommand,
1460 CompositeOperatorsCommand,
1461 CompositeDissolveCommand,
1462 CompositeDisplaceCommand,
1463 CompositeHelpCommand,
1464 CompositeDismissCommand,
1469 RectifyDismissCommand,
1478 MatteEditBorderCommand,
1479 MatteEditFuzzCommand,
1480 MatteEditValueCommand,
1481 MatteEditUndoCommand,
1482 MatteEditHelpCommand,
1483 MatteEditDismissCommand,
1484 PasteOperatorsCommand,
1486 PasteDismissCommand,
1488 RotateDirectionCommand,
1490 RotateSharpenCommand,
1492 RotateDismissCommand,
1493 HorizontalRotateCommand,
1494 VerticalRotateCommand,
1505 #define BricksWidth 20
1506 #define BricksHeight 20
1507 #define DiagonalWidth 16
1508 #define DiagonalHeight 16
1509 #define HighlightWidth 8
1510 #define HighlightHeight 8
1511 #define OpaqueWidth 8
1512 #define OpaqueHeight 8
1513 #define ScalesWidth 16
1514 #define ScalesHeight 16
1515 #define ShadowWidth 8
1516 #define ShadowHeight 8
1517 #define VerticalWidth 16
1518 #define VerticalHeight 16
1519 #define WavyWidth 16
1520 #define WavyHeight 16
1523 Constant declaration.
1528 static const unsigned char
1531 0xff, 0xff, 0x0f, 0x03, 0x0c, 0x00, 0x03, 0x0c, 0x00, 0x03, 0x0c, 0x00,
1532 0x03, 0x0c, 0x00, 0xff, 0xff, 0x0f, 0x60, 0x80, 0x01, 0x60, 0x80, 0x01,
1533 0x60, 0x80, 0x01, 0x60, 0x80, 0x01, 0xff, 0xff, 0x0f, 0x03, 0x0c, 0x00,
1534 0x03, 0x0c, 0x00, 0x03, 0x0c, 0x00, 0x03, 0x0c, 0x00, 0xff, 0xff, 0x0f,
1535 0x60, 0x80, 0x01, 0x60, 0x80, 0x01, 0x60, 0x80, 0x01, 0x60, 0x80, 0x01
1539 0x44, 0x44, 0x88, 0x88, 0x11, 0x11, 0x22, 0x22, 0x44, 0x44, 0x88, 0x88,
1540 0x11, 0x11, 0x22, 0x22, 0x44, 0x44, 0x88, 0x88, 0x11, 0x11, 0x22, 0x22,
1541 0x44, 0x44, 0x88, 0x88, 0x11, 0x11, 0x22, 0x22
1545 0x08, 0x08, 0x08, 0x08, 0x14, 0x14, 0xe3, 0xe3, 0x80, 0x80, 0x80, 0x80,
1546 0x41, 0x41, 0x3e, 0x3e, 0x08, 0x08, 0x08, 0x08, 0x14, 0x14, 0xe3, 0xe3,
1547 0x80, 0x80, 0x80, 0x80, 0x41, 0x41, 0x3e, 0x3e
1551 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
1552 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
1553 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
1557 0xfe, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfd, 0xff, 0xfd, 0xff, 0xfb, 0xff,
1558 0xe7, 0xff, 0x1f, 0xff, 0xff, 0xf8, 0xff, 0xe7, 0xff, 0xdf, 0xff, 0xbf,
1559 0xff, 0xbf, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f
1563 Function prototypes.
1566 XImageWindowCommand(Display *,XResourceInfo *,XWindows *,
1567 const MagickStatusType,KeySym,Image **,ExceptionInfo *);
1570 *XMagickCommand(Display *,XResourceInfo *,XWindows *,const CommandType,
1571 Image **,ExceptionInfo *),
1572 *XOpenImage(Display *,XResourceInfo *,XWindows *,const MagickBooleanType),
1573 *XTileImage(Display *,XResourceInfo *,XWindows *,Image *,XEvent *,
1575 *XVisualDirectoryImage(Display *,XResourceInfo *,XWindows *,
1578 static MagickBooleanType
1579 XAnnotateEditImage(Display *,XResourceInfo *,XWindows *,Image *,
1581 XBackgroundImage(Display *,XResourceInfo *,XWindows *,Image **,
1583 XChopImage(Display *,XResourceInfo *,XWindows *,Image **,
1585 XCropImage(Display *,XResourceInfo *,XWindows *,Image *,const ClipboardMode,
1587 XColorEditImage(Display *,XResourceInfo *,XWindows *,Image **,
1589 XCompositeImage(Display *,XResourceInfo *,XWindows *,Image *,
1591 XConfigureImage(Display *,XResourceInfo *,XWindows *,Image *,ExceptionInfo *),
1592 XDrawEditImage(Display *,XResourceInfo *,XWindows *,Image **,
1594 XMatteEditImage(Display *,XResourceInfo *,XWindows *,Image **,
1596 XPasteImage(Display *,XResourceInfo *,XWindows *,Image *,ExceptionInfo *),
1597 XPrintImage(Display *,XResourceInfo *,XWindows *,Image *,ExceptionInfo *),
1598 XRotateImage(Display *,XResourceInfo *,XWindows *,double,Image **,
1600 XROIImage(Display *,XResourceInfo *,XWindows *,Image **,ExceptionInfo *),
1601 XSaveImage(Display *,XResourceInfo *,XWindows *,Image *,ExceptionInfo *),
1602 XTrimImage(Display *,XResourceInfo *,XWindows *,Image *,ExceptionInfo *);
1605 XDrawPanRectangle(Display *,XWindows *),
1606 XImageCache(Display *,XResourceInfo *,XWindows *,const CommandType,Image **,
1608 XMagnifyImage(Display *,XWindows *,XEvent *),
1609 XMakePanImage(Display *,XResourceInfo *,XWindows *,Image *,ExceptionInfo *),
1610 XPanImage(Display *,XWindows *,XEvent *),
1611 XMagnifyWindowCommand(Display *,XWindows *,const MagickStatusType,
1613 XSetCropGeometry(Display *,XWindows *,RectangleInfo *,Image *),
1614 XScreenEvent(Display *,XWindows *,XEvent *),
1615 XTranslateImage(Display *,XWindows *,Image *,const KeySym);
1618 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1622 % D i s p l a y I m a g e s %
1626 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1628 % DisplayImages() displays an image sequence to any X window screen. It
1629 % returns a value other than 0 if successful. Check the exception member
1630 % of image to determine the reason for any failure.
1632 % The format of the DisplayImages method is:
1634 % MagickBooleanType DisplayImages(const ImageInfo *image_info,
1635 % Image *images,ExceptionInfo *exception)
1637 % A description of each parameter follows:
1639 % o image_info: the image info.
1641 % o image: the image.
1643 % o exception: return any errors or warnings in this structure.
1646 MagickExport MagickBooleanType DisplayImages(const ImageInfo *image_info,
1647 Image *images,ExceptionInfo *exception)
1670 assert(image_info != (const ImageInfo *) NULL);
1671 assert(image_info->signature == MagickSignature);
1672 assert(images != (Image *) NULL);
1673 assert(images->signature == MagickSignature);
1674 if (images->debug != MagickFalse)
1675 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",images->filename);
1676 display=XOpenDisplay(image_info->server_name);
1677 if (display == (Display *) NULL)
1679 (void) ThrowMagickException(exception,GetMagickModule(),XServerError,
1680 "UnableToOpenXServer","`%s'",XDisplayName(image_info->server_name));
1681 return(MagickFalse);
1683 if (exception->severity != UndefinedException)
1684 CatchException(exception);
1685 (void) XSetErrorHandler(XError);
1686 resource_database=XGetResourceDatabase(display,GetClientName());
1687 (void) ResetMagickMemory(&resource_info,0,sizeof(resource_info));
1688 XGetResourceInfo(image_info,resource_database,GetClientName(),&resource_info);
1689 if (image_info->page != (char *) NULL)
1690 resource_info.image_geometry=AcquireString(image_info->page);
1691 resource_info.immutable=MagickTrue;
1692 argv[0]=AcquireString(GetClientName());
1694 for (i=0; (state & ExitState) == 0; i++)
1696 if ((images->iterations != 0) && (i >= (ssize_t) images->iterations))
1698 image=GetImageFromList(images,i % GetImageListLength(images));
1699 (void) XDisplayImage(display,&resource_info,argv,1,&image,&state,exception);
1701 SetErrorHandler((ErrorHandler) NULL);
1702 SetWarningHandler((WarningHandler) NULL);
1703 argv[0]=DestroyString(argv[0]);
1704 (void) XCloseDisplay(display);
1705 XDestroyResourceInfo(&resource_info);
1706 if (exception->severity != UndefinedException)
1707 return(MagickFalse);
1712 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1716 % R e m o t e D i s p l a y C o m m a n d %
1720 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1722 % RemoteDisplayCommand() encourages a remote display program to display the
1723 % specified image filename.
1725 % The format of the RemoteDisplayCommand method is:
1727 % MagickBooleanType RemoteDisplayCommand(const ImageInfo *image_info,
1728 % const char *window,const char *filename,ExceptionInfo *exception)
1730 % A description of each parameter follows:
1732 % o image_info: the image info.
1734 % o window: Specifies the name or id of an X window.
1736 % o filename: the name of the image filename to display.
1738 % o exception: return any errors or warnings in this structure.
1741 MagickExport MagickBooleanType RemoteDisplayCommand(const ImageInfo *image_info,
1742 const char *window,const char *filename,ExceptionInfo *exception)
1750 assert(image_info != (const ImageInfo *) NULL);
1751 assert(image_info->signature == MagickSignature);
1752 assert(filename != (char *) NULL);
1753 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
1754 display=XOpenDisplay(image_info->server_name);
1755 if (display == (Display *) NULL)
1757 (void) ThrowMagickException(exception,GetMagickModule(),XServerError,
1758 "UnableToOpenXServer","`%s'",XDisplayName(image_info->server_name));
1759 return(MagickFalse);
1761 (void) XSetErrorHandler(XError);
1762 status=XRemoteCommand(display,window,filename);
1763 (void) XCloseDisplay(display);
1764 return(status != 0 ? MagickTrue : MagickFalse);
1768 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1772 + X A n n o t a t e E d i t I m a g e %
1776 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1778 % XAnnotateEditImage() annotates the image with text.
1780 % The format of the XAnnotateEditImage method is:
1782 % MagickBooleanType XAnnotateEditImage(Display *display,
1783 % XResourceInfo *resource_info,XWindows *windows,Image *image,
1784 % ExceptionInfo *exception)
1786 % A description of each parameter follows:
1788 % o display: Specifies a connection to an X server; returned from
1791 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1793 % o windows: Specifies a pointer to a XWindows structure.
1795 % o image: the image; returned from ReadImage.
1799 static inline ssize_t MagickMax(const ssize_t x,const ssize_t y)
1806 static inline ssize_t MagickMin(const ssize_t x,const ssize_t y)
1813 static MagickBooleanType XAnnotateEditImage(Display *display,
1814 XResourceInfo *resource_info,XWindows *windows,Image *image,
1815 ExceptionInfo *exception)
1835 static const ModeType
1836 AnnotateCommands[] =
1838 AnnotateNameCommand,
1839 AnnotateFontColorCommand,
1840 AnnotateBackgroundColorCommand,
1841 AnnotateRotateCommand,
1842 AnnotateHelpCommand,
1843 AnnotateDismissCommand
1851 static MagickBooleanType
1852 transparent_box = MagickTrue,
1853 transparent_pen = MagickFalse;
1855 static MagickRealType
1859 box_id = MaxNumberPens-2,
1864 command[MaxTextExtent],
1865 text[MaxTextExtent];
1868 *ColorMenu[MaxNumberPens+1];
1916 (void) CloneString(&windows->command.name,"Annotate");
1917 windows->command.data=4;
1918 (void) XCommandWidget(display,windows,AnnotateMenu,(XEvent *) NULL);
1919 (void) XMapRaised(display,windows->command.id);
1920 XClientMessage(display,windows->image.id,windows->im_protocols,
1921 windows->im_update_widget,CurrentTime);
1923 Track pointer until button 1 is pressed.
1925 XQueryPosition(display,windows->image.id,&x,&y);
1926 (void) XSelectInput(display,windows->image.id,
1927 windows->image.attributes.event_mask | PointerMotionMask);
1928 cursor=XCreateFontCursor(display,XC_left_side);
1929 (void) XCheckDefineCursor(display,windows->image.id,cursor);
1933 if (windows->info.mapped != MagickFalse)
1936 Display pointer position.
1938 (void) FormatLocaleString(text,MaxTextExtent," %+d%+d ",
1939 x+windows->image.x,y+windows->image.y);
1940 XInfoWidget(display,windows,text);
1943 Wait for next event.
1945 XScreenEvent(display,windows,&event);
1946 if (event.xany.window == windows->command.id)
1949 Select a command from the Command widget.
1951 id=XCommandWidget(display,windows,AnnotateMenu,&event);
1952 (void) XCheckDefineCursor(display,windows->image.id,cursor);
1955 switch (AnnotateCommands[id])
1957 case AnnotateNameCommand:
1960 *FontMenu[MaxNumberFonts];
1966 Initialize menu selections.
1968 for (i=0; i < MaxNumberFonts; i++)
1969 FontMenu[i]=resource_info->font_name[i];
1970 FontMenu[MaxNumberFonts-2]="Browser...";
1971 FontMenu[MaxNumberFonts-1]=(const char *) NULL;
1973 Select a font name from the pop-up menu.
1975 font_number=XMenuWidget(display,windows,AnnotateMenu[id],
1976 (const char **) FontMenu,command);
1977 if (font_number < 0)
1979 if (font_number == (MaxNumberFonts-2))
1982 font_name[MaxTextExtent] = "fixed";
1985 Select a font name from a browser.
1987 resource_info->font_name[font_number]=font_name;
1988 XFontBrowserWidget(display,windows,"Select",font_name);
1989 if (*font_name == '\0')
1993 Initialize font info.
1995 font_info=XLoadQueryFont(display,resource_info->font_name[
1997 if (font_info == (XFontStruct *) NULL)
1999 XNoticeWidget(display,windows,"Unable to load font:",
2000 resource_info->font_name[font_number]);
2003 font_id=(unsigned int) font_number;
2004 (void) XFreeFont(display,font_info);
2007 case AnnotateFontColorCommand:
2010 Initialize menu selections.
2012 for (i=0; i < (int) (MaxNumberPens-2); i++)
2013 ColorMenu[i]=resource_info->pen_colors[i];
2014 ColorMenu[MaxNumberPens-2]="transparent";
2015 ColorMenu[MaxNumberPens-1]="Browser...";
2016 ColorMenu[MaxNumberPens]=(const char *) NULL;
2018 Select a pen color from the pop-up menu.
2020 pen_number=XMenuWidget(display,windows,AnnotateMenu[id],
2021 (const char **) ColorMenu,command);
2024 transparent_pen=pen_number == (MaxNumberPens-2) ? MagickTrue :
2026 if (transparent_pen != MagickFalse)
2028 if (pen_number == (MaxNumberPens-1))
2031 color_name[MaxTextExtent] = "gray";
2034 Select a pen color from a dialog.
2036 resource_info->pen_colors[pen_number]=color_name;
2037 XColorBrowserWidget(display,windows,"Select",color_name);
2038 if (*color_name == '\0')
2044 (void) XParseColor(display,windows->map_info->colormap,
2045 resource_info->pen_colors[pen_number],&color);
2046 XBestPixel(display,windows->map_info->colormap,(XColor *) NULL,
2047 (unsigned int) MaxColors,&color);
2048 windows->pixel_info->pen_colors[pen_number]=color;
2049 pen_id=(unsigned int) pen_number;
2052 case AnnotateBackgroundColorCommand:
2055 Initialize menu selections.
2057 for (i=0; i < (int) (MaxNumberPens-2); i++)
2058 ColorMenu[i]=resource_info->pen_colors[i];
2059 ColorMenu[MaxNumberPens-2]="transparent";
2060 ColorMenu[MaxNumberPens-1]="Browser...";
2061 ColorMenu[MaxNumberPens]=(const char *) NULL;
2063 Select a pen color from the pop-up menu.
2065 pen_number=XMenuWidget(display,windows,AnnotateMenu[id],
2066 (const char **) ColorMenu,command);
2069 transparent_box=pen_number == (MaxNumberPens-2) ? MagickTrue :
2071 if (transparent_box != MagickFalse)
2073 if (pen_number == (MaxNumberPens-1))
2076 color_name[MaxTextExtent] = "gray";
2079 Select a pen color from a dialog.
2081 resource_info->pen_colors[pen_number]=color_name;
2082 XColorBrowserWidget(display,windows,"Select",color_name);
2083 if (*color_name == '\0')
2089 (void) XParseColor(display,windows->map_info->colormap,
2090 resource_info->pen_colors[pen_number],&color);
2091 XBestPixel(display,windows->map_info->colormap,(XColor *) NULL,
2092 (unsigned int) MaxColors,&color);
2093 windows->pixel_info->pen_colors[pen_number]=color;
2094 box_id=(unsigned int) pen_number;
2097 case AnnotateRotateCommand:
2103 angle[MaxTextExtent] = "30.0";
2121 Select a command from the pop-up menu.
2123 entry=XMenuWidget(display,windows,AnnotateMenu[id],RotateMenu,
2129 degrees=InterpretLocaleValue(RotateMenu[entry],(char **) NULL);
2132 (void) XDialogWidget(display,windows,"OK","Enter rotation angle:",
2136 degrees=InterpretLocaleValue(angle,(char **) NULL);
2139 case AnnotateHelpCommand:
2141 XTextViewWidget(display,resource_info,windows,MagickFalse,
2142 "Help Viewer - Image Annotation",ImageAnnotateHelp);
2145 case AnnotateDismissCommand:
2163 if (event.xbutton.button != Button1)
2165 if (event.xbutton.window != windows->image.id)
2168 Change to text entering mode.
2181 if (event.xkey.window != windows->image.id)
2184 Respond to a user key press.
2186 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
2187 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
2188 switch ((int) key_symbol)
2203 XTextViewWidget(display,resource_info,windows,MagickFalse,
2204 "Help Viewer - Image Annotation",ImageAnnotateHelp);
2209 (void) XBell(display,0);
2218 Map and unmap Info widget as cursor crosses its boundaries.
2222 if (windows->info.mapped != MagickFalse)
2224 if ((x < (int) (windows->info.x+windows->info.width)) &&
2225 (y < (int) (windows->info.y+windows->info.height)))
2226 (void) XWithdrawWindow(display,windows->info.id,
2227 windows->info.screen);
2230 if ((x > (int) (windows->info.x+windows->info.width)) ||
2231 (y > (int) (windows->info.y+windows->info.height)))
2232 (void) XMapWindow(display,windows->info.id);
2238 } while ((state & ExitState) == 0);
2239 (void) XSelectInput(display,windows->image.id,
2240 windows->image.attributes.event_mask);
2241 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
2242 if ((state & EscapeState) != 0)
2245 Set font info and check boundary conditions.
2247 font_info=XLoadQueryFont(display,resource_info->font_name[font_id]);
2248 if (font_info == (XFontStruct *) NULL)
2250 XNoticeWidget(display,windows,"Unable to load font:",
2251 resource_info->font_name[font_id]);
2252 font_info=windows->font_info;
2254 if ((x+font_info->max_bounds.width) >= (int) windows->image.width)
2255 x=(int) windows->image.width-font_info->max_bounds.width;
2256 if (y < (int) (font_info->ascent+font_info->descent))
2257 y=(int) font_info->ascent+font_info->descent;
2258 if (((int) font_info->max_bounds.width > (int) windows->image.width) ||
2259 ((font_info->ascent+font_info->descent) >= (int) windows->image.height))
2260 return(MagickFalse);
2262 Initialize annotate structure.
2264 annotate_info=(XAnnotateInfo *) AcquireMagickMemory(sizeof(*annotate_info));
2265 if (annotate_info == (XAnnotateInfo *) NULL)
2266 return(MagickFalse);
2267 XGetAnnotateInfo(annotate_info);
2270 if ((transparent_box == MagickFalse) && (transparent_pen == MagickFalse))
2271 annotate_info->stencil=OpaqueStencil;
2273 if (transparent_box == MagickFalse)
2274 annotate_info->stencil=BackgroundStencil;
2276 annotate_info->stencil=ForegroundStencil;
2277 annotate_info->height=(unsigned int) font_info->ascent+font_info->descent;
2278 annotate_info->degrees=degrees;
2279 annotate_info->font_info=font_info;
2280 annotate_info->text=(char *) AcquireQuantumMemory((size_t)
2281 windows->image.width/MagickMax((ssize_t) font_info->min_bounds.width,1)+2UL,
2282 sizeof(*annotate_info->text));
2283 if (annotate_info->text == (char *) NULL)
2284 return(MagickFalse);
2286 Create cursor and set graphic context.
2288 cursor=XCreateFontCursor(display,XC_pencil);
2289 (void) XCheckDefineCursor(display,windows->image.id,cursor);
2290 annotate_context=windows->image.annotate_context;
2291 (void) XSetFont(display,annotate_context,font_info->fid);
2292 (void) XSetBackground(display,annotate_context,
2293 windows->pixel_info->pen_colors[box_id].pixel);
2294 (void) XSetForeground(display,annotate_context,
2295 windows->pixel_info->pen_colors[pen_id].pixel);
2297 Begin annotating the image with text.
2299 (void) CloneString(&windows->command.name,"Text");
2300 windows->command.data=0;
2301 (void) XCommandWidget(display,windows,TextMenu,(XEvent *) NULL);
2303 (void) XDrawString(display,windows->image.id,annotate_context,x,y,"_",1);
2304 text_event.xexpose.width=(int) font_info->max_bounds.width;
2305 text_event.xexpose.height=font_info->max_bounds.ascent+
2306 font_info->max_bounds.descent;
2307 p=annotate_info->text;
2311 Display text cursor.
2314 (void) XDrawString(display,windows->image.id,annotate_context,x,y,"_",1);
2316 Wait for next event.
2318 XScreenEvent(display,windows,&event);
2319 if (event.xany.window == windows->command.id)
2322 Select a command from the Command widget.
2324 (void) XSetBackground(display,annotate_context,
2325 windows->pixel_info->background_color.pixel);
2326 (void) XSetForeground(display,annotate_context,
2327 windows->pixel_info->foreground_color.pixel);
2328 id=XCommandWidget(display,windows,AnnotateMenu,&event);
2329 (void) XSetBackground(display,annotate_context,
2330 windows->pixel_info->pen_colors[box_id].pixel);
2331 (void) XSetForeground(display,annotate_context,
2332 windows->pixel_info->pen_colors[pen_id].pixel);
2335 switch (TextCommands[id])
2337 case TextHelpCommand:
2339 XTextViewWidget(display,resource_info,windows,MagickFalse,
2340 "Help Viewer - Image Annotation",ImageAnnotateHelp);
2341 (void) XCheckDefineCursor(display,windows->image.id,cursor);
2344 case TextApplyCommand:
2347 Finished annotating.
2349 annotate_info->width=(unsigned int) XTextWidth(font_info,
2350 annotate_info->text,(int) strlen(annotate_info->text));
2351 XRefreshWindow(display,&windows->image,&text_event);
2363 text_event.xexpose.x=x;
2364 text_event.xexpose.y=y-font_info->max_bounds.ascent;
2365 (void) XClearArea(display,windows->image.id,x,text_event.xexpose.y,
2366 (unsigned int) text_event.xexpose.width,(unsigned int)
2367 text_event.xexpose.height,MagickFalse);
2368 XRefreshWindow(display,&windows->image,&text_event);
2373 if (event.xbutton.window != windows->image.id)
2375 if (event.xbutton.button == Button2)
2378 Request primary selection.
2380 (void) XConvertSelection(display,XA_PRIMARY,XA_STRING,XA_STRING,
2381 windows->image.id,CurrentTime);
2388 if (event.xexpose.count == 0)
2394 Refresh Image window.
2396 XRefreshWindow(display,&windows->image,(XEvent *) NULL);
2397 text_info=annotate_info;
2398 while (text_info != (XAnnotateInfo *) NULL)
2400 if (annotate_info->stencil == ForegroundStencil)
2401 (void) XDrawString(display,windows->image.id,annotate_context,
2402 text_info->x,text_info->y,text_info->text,
2403 (int) strlen(text_info->text));
2405 (void) XDrawImageString(display,windows->image.id,
2406 annotate_context,text_info->x,text_info->y,text_info->text,
2407 (int) strlen(text_info->text));
2408 text_info=text_info->previous;
2410 (void) XDrawString(display,windows->image.id,annotate_context,
2420 if (event.xkey.window != windows->image.id)
2423 Respond to a user key press.
2425 length=XLookupString((XKeyEvent *) &event.xkey,command,(int)
2426 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
2427 *(command+length)='\0';
2428 if (((event.xkey.state & ControlMask) != 0) ||
2429 ((event.xkey.state & Mod1Mask) != 0))
2430 state|=ModifierState;
2431 if ((state & ModifierState) != 0)
2432 switch ((int) key_symbol)
2437 key_symbol=DeleteCommand;
2443 switch ((int) key_symbol)
2448 Erase one character.
2450 if (p == annotate_info->text)
2452 if (annotate_info->previous == (XAnnotateInfo *) NULL)
2457 Go to end of the previous line of text.
2459 annotate_info=annotate_info->previous;
2460 p=annotate_info->text;
2461 x=annotate_info->x+annotate_info->width;
2463 if (annotate_info->width != 0)
2464 p+=strlen(annotate_info->text);
2469 x-=XTextWidth(font_info,p,1);
2470 text_event.xexpose.x=x;
2471 text_event.xexpose.y=y-font_info->max_bounds.ascent;
2472 XRefreshWindow(display,&windows->image,&text_event);
2475 case XK_bracketleft:
2477 key_symbol=XK_Escape;
2483 Erase the entire line of text.
2485 while (p != annotate_info->text)
2488 x-=XTextWidth(font_info,p,1);
2489 text_event.xexpose.x=x;
2490 XRefreshWindow(display,&windows->image,&text_event);
2498 Finished annotating.
2500 annotate_info->width=(unsigned int) XTextWidth(font_info,
2501 annotate_info->text,(int) strlen(annotate_info->text));
2502 XRefreshWindow(display,&windows->image,&text_event);
2509 Draw a single character on the Image window.
2511 if ((state & ModifierState) != 0)
2513 if (*command == '\0')
2516 if (annotate_info->stencil == ForegroundStencil)
2517 (void) XDrawString(display,windows->image.id,annotate_context,
2520 (void) XDrawImageString(display,windows->image.id,
2521 annotate_context,x,y,p,1);
2522 x+=XTextWidth(font_info,p,1);
2524 if ((x+font_info->max_bounds.width) < (int) windows->image.width)
2531 Advance to the next line of text.
2534 annotate_info->width=(unsigned int) XTextWidth(font_info,
2535 annotate_info->text,(int) strlen(annotate_info->text));
2536 if (annotate_info->next != (XAnnotateInfo *) NULL)
2539 Line of text already exists.
2541 annotate_info=annotate_info->next;
2544 p=annotate_info->text;
2547 annotate_info->next=(XAnnotateInfo *) AcquireMagickMemory(
2548 sizeof(*annotate_info->next));
2549 if (annotate_info->next == (XAnnotateInfo *) NULL)
2550 return(MagickFalse);
2551 *annotate_info->next=(*annotate_info);
2552 annotate_info->next->previous=annotate_info;
2553 annotate_info=annotate_info->next;
2554 annotate_info->text=(char *) AcquireQuantumMemory((size_t)
2555 windows->image.width/MagickMax((ssize_t)
2556 font_info->min_bounds.width,1)+2UL,sizeof(*annotate_info->text));
2557 if (annotate_info->text == (char *) NULL)
2558 return(MagickFalse);
2559 annotate_info->y+=annotate_info->height;
2560 if (annotate_info->y > (int) windows->image.height)
2561 annotate_info->y=(int) annotate_info->height;
2562 annotate_info->next=(XAnnotateInfo *) NULL;
2565 p=annotate_info->text;
2574 Respond to a user key release.
2576 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
2577 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
2578 state&=(~ModifierState);
2581 case SelectionNotify:
2597 Obtain response from primary selection.
2599 if (event.xselection.property == (Atom) None)
2601 status=XGetWindowProperty(display,event.xselection.requestor,
2602 event.xselection.property,0L,(long) MaxTextExtent,True,XA_STRING,
2603 &type,&format,&length,&after,&data);
2604 if ((status != Success) || (type != XA_STRING) || (format == 32) ||
2608 Annotate Image window with primary selection.
2610 for (i=0; i < (ssize_t) length; i++)
2612 if ((char) data[i] != '\n')
2615 Draw a single character on the Image window.
2618 (void) XDrawString(display,windows->image.id,annotate_context,
2620 x+=XTextWidth(font_info,p,1);
2622 if ((x+font_info->max_bounds.width) < (int) windows->image.width)
2626 Advance to the next line of text.
2629 annotate_info->width=(unsigned int) XTextWidth(font_info,
2630 annotate_info->text,(int) strlen(annotate_info->text));
2631 if (annotate_info->next != (XAnnotateInfo *) NULL)
2634 Line of text already exists.
2636 annotate_info=annotate_info->next;
2639 p=annotate_info->text;
2642 annotate_info->next=(XAnnotateInfo *) AcquireMagickMemory(
2643 sizeof(*annotate_info->next));
2644 if (annotate_info->next == (XAnnotateInfo *) NULL)
2645 return(MagickFalse);
2646 *annotate_info->next=(*annotate_info);
2647 annotate_info->next->previous=annotate_info;
2648 annotate_info=annotate_info->next;
2649 annotate_info->text=(char *) AcquireQuantumMemory((size_t)
2650 windows->image.width/MagickMax((ssize_t)
2651 font_info->min_bounds.width,1)+2UL,sizeof(*annotate_info->text));
2652 if (annotate_info->text == (char *) NULL)
2653 return(MagickFalse);
2654 annotate_info->y+=annotate_info->height;
2655 if (annotate_info->y > (int) windows->image.height)
2656 annotate_info->y=(int) annotate_info->height;
2657 annotate_info->next=(XAnnotateInfo *) NULL;
2660 p=annotate_info->text;
2662 (void) XFree((void *) data);
2668 } while ((state & ExitState) == 0);
2669 (void) XFreeCursor(display,cursor);
2671 Annotation is relative to image configuration.
2673 width=(unsigned int) image->columns;
2674 height=(unsigned int) image->rows;
2677 if (windows->image.crop_geometry != (char *) NULL)
2678 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
2680 Initialize annotated image.
2682 XSetCursorState(display,windows,MagickTrue);
2683 XCheckRefreshWindows(display,windows);
2684 while (annotate_info != (XAnnotateInfo *) NULL)
2686 if (annotate_info->width == 0)
2689 No text on this line-- go to the next line of text.
2691 previous_info=annotate_info->previous;
2692 annotate_info->text=(char *)
2693 RelinquishMagickMemory(annotate_info->text);
2694 annotate_info=(XAnnotateInfo *) RelinquishMagickMemory(annotate_info);
2695 annotate_info=previous_info;
2699 Determine pixel index for box and pen color.
2701 windows->pixel_info->box_color=windows->pixel_info->pen_colors[box_id];
2702 if (windows->pixel_info->colors != 0)
2703 for (i=0; i < (ssize_t) windows->pixel_info->colors; i++)
2704 if (windows->pixel_info->pixels[i] ==
2705 windows->pixel_info->pen_colors[box_id].pixel)
2707 windows->pixel_info->box_index=(unsigned short) i;
2710 windows->pixel_info->pen_color=windows->pixel_info->pen_colors[pen_id];
2711 if (windows->pixel_info->colors != 0)
2712 for (i=0; i < (ssize_t) windows->pixel_info->colors; i++)
2713 if (windows->pixel_info->pixels[i] ==
2714 windows->pixel_info->pen_colors[pen_id].pixel)
2716 windows->pixel_info->pen_index=(unsigned short) i;
2720 Define the annotate geometry string.
2722 annotate_info->x=(int)
2723 width*(annotate_info->x+windows->image.x)/windows->image.ximage->width;
2724 annotate_info->y=(int) height*(annotate_info->y-font_info->ascent+
2725 windows->image.y)/windows->image.ximage->height;
2726 (void) FormatLocaleString(annotate_info->geometry,MaxTextExtent,
2727 "%ux%u%+d%+d",width*annotate_info->width/windows->image.ximage->width,
2728 height*annotate_info->height/windows->image.ximage->height,
2729 annotate_info->x+x,annotate_info->y+y);
2731 Annotate image with text.
2733 status=XAnnotateImage(display,windows->pixel_info,annotate_info,image);
2735 return(MagickFalse);
2739 previous_info=annotate_info->previous;
2740 annotate_info->text=DestroyString(annotate_info->text);
2741 annotate_info=(XAnnotateInfo *) RelinquishMagickMemory(annotate_info);
2742 annotate_info=previous_info;
2744 (void) XSetForeground(display,annotate_context,
2745 windows->pixel_info->foreground_color.pixel);
2746 (void) XSetBackground(display,annotate_context,
2747 windows->pixel_info->background_color.pixel);
2748 (void) XSetFont(display,annotate_context,windows->font_info->fid);
2749 XSetCursorState(display,windows,MagickFalse);
2750 (void) XFreeFont(display,font_info);
2752 Update image configuration.
2754 XConfigureImageColormap(display,resource_info,windows,image);
2755 (void) XConfigureImage(display,resource_info,windows,image,exception);
2760 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2764 + X B a c k g r o u n d I m a g e %
2768 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2770 % XBackgroundImage() displays the image in the background of a window.
2772 % The format of the XBackgroundImage method is:
2774 % MagickBooleanType XBackgroundImage(Display *display,
2775 % XResourceInfo *resource_info,XWindows *windows,Image **image,
2776 % ExceptionInfo *exception)
2778 % A description of each parameter follows:
2780 % o display: Specifies a connection to an X server; returned from
2783 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
2785 % o windows: Specifies a pointer to a XWindows structure.
2787 % o image: the image.
2789 % o exception: return any errors or warnings in this structure.
2792 static MagickBooleanType XBackgroundImage(Display *display,
2793 XResourceInfo *resource_info,XWindows *windows,Image **image,
2794 ExceptionInfo *exception)
2796 #define BackgroundImageTag "Background/Image"
2802 window_id[MaxTextExtent] = "root";
2805 background_resources;
2808 Put image in background.
2810 status=XDialogWidget(display,windows,"Background",
2811 "Enter window id (id 0x00 selects window with pointer):",window_id);
2812 if (*window_id == '\0')
2813 return(MagickFalse);
2814 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image,
2816 XInfoWidget(display,windows,BackgroundImageTag);
2817 XSetCursorState(display,windows,MagickTrue);
2818 XCheckRefreshWindows(display,windows);
2819 background_resources=(*resource_info);
2820 background_resources.window_id=window_id;
2821 background_resources.backdrop=status != 0 ? MagickTrue : MagickFalse;
2822 status=XDisplayBackgroundImage(display,&background_resources,*image,
2824 if (status != MagickFalse)
2825 XClientMessage(display,windows->image.id,windows->im_protocols,
2826 windows->im_retain_colors,CurrentTime);
2827 XSetCursorState(display,windows,MagickFalse);
2828 (void) XMagickCommand(display,resource_info,windows,UndoCommand,image,
2834 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2838 + X C h o p I m a g e %
2842 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2844 % XChopImage() chops the X image.
2846 % The format of the XChopImage method is:
2848 % MagickBooleanType XChopImage(Display *display,XResourceInfo *resource_info,
2849 % XWindows *windows,Image **image,ExceptionInfo *exception)
2851 % A description of each parameter follows:
2853 % o display: Specifies a connection to an X server; returned from
2856 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
2858 % o windows: Specifies a pointer to a XWindows structure.
2860 % o image: the image.
2862 % o exception: return any errors or warnings in this structure.
2865 static MagickBooleanType XChopImage(Display *display,
2866 XResourceInfo *resource_info,XWindows *windows,Image **image,
2867 ExceptionInfo *exception)
2879 direction = HorizontalChopCommand;
2881 static const ModeType
2884 ChopDirectionCommand,
2888 DirectionCommands[] =
2890 HorizontalChopCommand,
2895 text[MaxTextExtent];
2928 (void) CloneString(&windows->command.name,"Chop");
2929 windows->command.data=1;
2930 (void) XCommandWidget(display,windows,ChopMenu,(XEvent *) NULL);
2931 (void) XMapRaised(display,windows->command.id);
2932 XClientMessage(display,windows->image.id,windows->im_protocols,
2933 windows->im_update_widget,CurrentTime);
2935 Track pointer until button 1 is pressed.
2937 XQueryPosition(display,windows->image.id,&x,&y);
2938 (void) XSelectInput(display,windows->image.id,
2939 windows->image.attributes.event_mask | PointerMotionMask);
2943 if (windows->info.mapped != MagickFalse)
2946 Display pointer position.
2948 (void) FormatLocaleString(text,MaxTextExtent," %+d%+d ",
2949 x+windows->image.x,y+windows->image.y);
2950 XInfoWidget(display,windows,text);
2953 Wait for next event.
2955 XScreenEvent(display,windows,&event);
2956 if (event.xany.window == windows->command.id)
2959 Select a command from the Command widget.
2961 id=XCommandWidget(display,windows,ChopMenu,&event);
2964 switch (ChopCommands[id])
2966 case ChopDirectionCommand:
2969 command[MaxTextExtent];
2980 Select a command from the pop-up menu.
2982 id=XMenuWidget(display,windows,ChopMenu[id],Directions,command);
2984 direction=DirectionCommands[id];
2987 case ChopHelpCommand:
2989 XTextViewWidget(display,resource_info,windows,MagickFalse,
2990 "Help Viewer - Image Chop",ImageChopHelp);
2993 case ChopDismissCommand:
3011 if (event.xbutton.button != Button1)
3013 if (event.xbutton.window != windows->image.id)
3016 User has committed to start point of chopping line.
3018 segment_info.x1=(short int) event.xbutton.x;
3019 segment_info.x2=(short int) event.xbutton.x;
3020 segment_info.y1=(short int) event.xbutton.y;
3021 segment_info.y2=(short int) event.xbutton.y;
3032 command[MaxTextExtent];
3037 if (event.xkey.window != windows->image.id)
3040 Respond to a user key press.
3042 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
3043 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
3044 switch ((int) key_symbol)
3059 (void) XSetFunction(display,windows->image.highlight_context,
3061 XTextViewWidget(display,resource_info,windows,MagickFalse,
3062 "Help Viewer - Image Chop",ImageChopHelp);
3063 (void) XSetFunction(display,windows->image.highlight_context,
3069 (void) XBell(display,0);
3078 Map and unmap Info widget as text cursor crosses its boundaries.
3082 if (windows->info.mapped != MagickFalse)
3084 if ((x < (int) (windows->info.x+windows->info.width)) &&
3085 (y < (int) (windows->info.y+windows->info.height)))
3086 (void) XWithdrawWindow(display,windows->info.id,
3087 windows->info.screen);
3090 if ((x > (int) (windows->info.x+windows->info.width)) ||
3091 (y > (int) (windows->info.y+windows->info.height)))
3092 (void) XMapWindow(display,windows->info.id);
3095 } while ((state & ExitState) == 0);
3096 (void) XSelectInput(display,windows->image.id,
3097 windows->image.attributes.event_mask);
3098 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
3099 if ((state & EscapeState) != 0)
3102 Draw line as pointer moves until the mouse button is released.
3109 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
3116 Display info and draw chopping line.
3118 if (windows->info.mapped == MagickFalse)
3119 (void) XMapWindow(display,windows->info.id);
3120 (void) FormatLocaleString(text,MaxTextExtent,
3121 " %.20gx%.20g%+.20g%+.20g",(double) chop_info.width,(double)
3122 chop_info.height,(double) chop_info.x,(double) chop_info.y);
3123 XInfoWidget(display,windows,text);
3124 XHighlightLine(display,windows->image.id,
3125 windows->image.highlight_context,&segment_info);
3128 if (windows->info.mapped != MagickFalse)
3129 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
3131 Wait for next event.
3133 XScreenEvent(display,windows,&event);
3135 XHighlightLine(display,windows->image.id,
3136 windows->image.highlight_context,&segment_info);
3141 segment_info.x2=(short int) event.xmotion.x;
3142 segment_info.y2=(short int) event.xmotion.y;
3148 User has committed to chopping line.
3150 segment_info.x2=(short int) event.xbutton.x;
3151 segment_info.y2=(short int) event.xbutton.y;
3159 segment_info.x2=(short int) event.xmotion.x;
3160 segment_info.y2=(short int) event.xmotion.y;
3166 Check boundary conditions.
3168 if (segment_info.x2 < 0)
3171 if (segment_info.x2 > windows->image.ximage->width)
3172 segment_info.x2=windows->image.ximage->width;
3173 if (segment_info.y2 < 0)
3176 if (segment_info.y2 > windows->image.ximage->height)
3177 segment_info.y2=windows->image.ximage->height;
3178 distance=(unsigned int)
3179 (((segment_info.x2-segment_info.x1)*(segment_info.x2-segment_info.x1))+
3180 ((segment_info.y2-segment_info.y1)*(segment_info.y2-segment_info.y1)));
3182 Compute chopping geometry.
3184 if (direction == HorizontalChopCommand)
3186 chop_info.width=(size_t) (segment_info.x2-segment_info.x1+1);
3187 chop_info.x=(ssize_t) windows->image.x+segment_info.x1;
3190 if (segment_info.x1 > (int) segment_info.x2)
3192 chop_info.width=(size_t) (segment_info.x1-segment_info.x2+1);
3193 chop_info.x=(ssize_t) windows->image.x+segment_info.x2;
3199 chop_info.height=(size_t) (segment_info.y2-segment_info.y1+1);
3201 chop_info.y=(ssize_t) windows->image.y+segment_info.y1;
3202 if (segment_info.y1 > segment_info.y2)
3204 chop_info.height=(size_t) (segment_info.y1-segment_info.y2+1);
3205 chop_info.y=(ssize_t) windows->image.y+segment_info.y2;
3208 } while ((state & ExitState) == 0);
3209 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
3210 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
3214 Image chopping is relative to image configuration.
3216 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image,
3218 XSetCursorState(display,windows,MagickTrue);
3219 XCheckRefreshWindows(display,windows);
3220 windows->image.window_changes.width=windows->image.ximage->width-
3221 (unsigned int) chop_info.width;
3222 windows->image.window_changes.height=windows->image.ximage->height-
3223 (unsigned int) chop_info.height;
3224 width=(unsigned int) (*image)->columns;
3225 height=(unsigned int) (*image)->rows;
3228 if (windows->image.crop_geometry != (char *) NULL)
3229 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
3230 scale_factor=(MagickRealType) width/windows->image.ximage->width;
3232 chop_info.x=(ssize_t) (scale_factor*chop_info.x+0.5);
3233 chop_info.width=(unsigned int) (scale_factor*chop_info.width+0.5);
3234 scale_factor=(MagickRealType) height/windows->image.ximage->height;
3236 chop_info.y=(ssize_t) (scale_factor*chop_info.y+0.5);
3237 chop_info.height=(unsigned int) (scale_factor*chop_info.height+0.5);
3241 chop_image=ChopImage(*image,&chop_info,exception);
3242 XSetCursorState(display,windows,MagickFalse);
3243 if (chop_image == (Image *) NULL)
3244 return(MagickFalse);
3245 *image=DestroyImage(*image);
3248 Update image configuration.
3250 XConfigureImageColormap(display,resource_info,windows,*image);
3251 (void) XConfigureImage(display,resource_info,windows,*image,exception);
3256 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3260 + X C o l o r E d i t I m a g e %
3264 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3266 % XColorEditImage() allows the user to interactively change the color of one
3267 % pixel for a DirectColor image or one colormap entry for a PseudoClass image.
3269 % The format of the XColorEditImage method is:
3271 % MagickBooleanType XColorEditImage(Display *display,
3272 % XResourceInfo *resource_info,XWindows *windows,Image **image,
3273 % ExceptionInfo *exception)
3275 % A description of each parameter follows:
3277 % o display: Specifies a connection to an X server; returned from
3280 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
3282 % o windows: Specifies a pointer to a XWindows structure.
3284 % o image: the image; returned from ReadImage.
3286 % o exception: return any errors or warnings in this structure.
3289 static MagickBooleanType XColorEditImage(Display *display,
3290 XResourceInfo *resource_info,XWindows *windows,Image **image,
3291 ExceptionInfo *exception)
3306 static const ModeType
3307 ColorEditCommands[] =
3309 ColorEditMethodCommand,
3310 ColorEditColorCommand,
3311 ColorEditBorderCommand,
3312 ColorEditFuzzCommand,
3313 ColorEditUndoCommand,
3314 ColorEditHelpCommand,
3315 ColorEditDismissCommand
3319 method = PointMethod;
3325 border_color = { 0, 0, 0, 0, 0, 0 };
3328 command[MaxTextExtent],
3329 text[MaxTextExtent];
3364 (void) CloneString(&windows->command.name,"Color Edit");
3365 windows->command.data=4;
3366 (void) XCommandWidget(display,windows,ColorEditMenu,(XEvent *) NULL);
3367 (void) XMapRaised(display,windows->command.id);
3368 XClientMessage(display,windows->image.id,windows->im_protocols,
3369 windows->im_update_widget,CurrentTime);
3373 cursor=XMakeCursor(display,windows->image.id,windows->map_info->colormap,
3374 resource_info->background_color,resource_info->foreground_color);
3375 (void) XCheckDefineCursor(display,windows->image.id,cursor);
3377 Track pointer until button 1 is pressed.
3379 XQueryPosition(display,windows->image.id,&x,&y);
3380 (void) XSelectInput(display,windows->image.id,
3381 windows->image.attributes.event_mask | PointerMotionMask);
3385 if (windows->info.mapped != MagickFalse)
3388 Display pointer position.
3390 (void) FormatLocaleString(text,MaxTextExtent," %+d%+d ",
3391 x+windows->image.x,y+windows->image.y);
3392 XInfoWidget(display,windows,text);
3395 Wait for next event.
3397 XScreenEvent(display,windows,&event);
3398 if (event.xany.window == windows->command.id)
3401 Select a command from the Command widget.
3403 id=XCommandWidget(display,windows,ColorEditMenu,&event);
3406 (void) XCheckDefineCursor(display,windows->image.id,cursor);
3409 switch (ColorEditCommands[id])
3411 case ColorEditMethodCommand:
3417 Select a method from the pop-up menu.
3419 methods=(char **) GetCommandOptions(MagickMethodOptions);
3420 if (methods == (char **) NULL)
3422 entry=XMenuWidget(display,windows,ColorEditMenu[id],
3423 (const char **) methods,command);
3425 method=(PaintMethod) ParseCommandOption(MagickMethodOptions,
3426 MagickFalse,methods[entry]);
3427 methods=DestroyStringList(methods);
3430 case ColorEditColorCommand:
3433 *ColorMenu[MaxNumberPens];
3439 Initialize menu selections.
3441 for (i=0; i < (int) (MaxNumberPens-2); i++)
3442 ColorMenu[i]=resource_info->pen_colors[i];
3443 ColorMenu[MaxNumberPens-2]="Browser...";
3444 ColorMenu[MaxNumberPens-1]=(const char *) NULL;
3446 Select a pen color from the pop-up menu.
3448 pen_number=XMenuWidget(display,windows,ColorEditMenu[id],
3449 (const char **) ColorMenu,command);
3452 if (pen_number == (MaxNumberPens-2))
3455 color_name[MaxTextExtent] = "gray";
3458 Select a pen color from a dialog.
3460 resource_info->pen_colors[pen_number]=color_name;
3461 XColorBrowserWidget(display,windows,"Select",color_name);
3462 if (*color_name == '\0')
3468 (void) XParseColor(display,windows->map_info->colormap,
3469 resource_info->pen_colors[pen_number],&color);
3470 XBestPixel(display,windows->map_info->colormap,(XColor *) NULL,
3471 (unsigned int) MaxColors,&color);
3472 windows->pixel_info->pen_colors[pen_number]=color;
3473 pen_id=(unsigned int) pen_number;
3476 case ColorEditBorderCommand:
3479 *ColorMenu[MaxNumberPens];
3485 Initialize menu selections.
3487 for (i=0; i < (int) (MaxNumberPens-2); i++)
3488 ColorMenu[i]=resource_info->pen_colors[i];
3489 ColorMenu[MaxNumberPens-2]="Browser...";
3490 ColorMenu[MaxNumberPens-1]=(const char *) NULL;
3492 Select a pen color from the pop-up menu.
3494 pen_number=XMenuWidget(display,windows,ColorEditMenu[id],
3495 (const char **) ColorMenu,command);
3498 if (pen_number == (MaxNumberPens-2))
3501 color_name[MaxTextExtent] = "gray";
3504 Select a pen color from a dialog.
3506 resource_info->pen_colors[pen_number]=color_name;
3507 XColorBrowserWidget(display,windows,"Select",color_name);
3508 if (*color_name == '\0')
3514 (void) XParseColor(display,windows->map_info->colormap,
3515 resource_info->pen_colors[pen_number],&border_color);
3518 case ColorEditFuzzCommand:
3521 fuzz[MaxTextExtent];
3536 Select a command from the pop-up menu.
3538 entry=XMenuWidget(display,windows,ColorEditMenu[id],FuzzMenu,
3544 (*image)->fuzz=SiPrefixToDouble(FuzzMenu[entry],1.0*
3548 (void) (void) CopyMagickString(fuzz,"20%",MaxTextExtent);
3549 (void) XDialogWidget(display,windows,"Ok",
3550 "Enter fuzz factor (0.0 - 99.9%):",fuzz);
3553 (void) ConcatenateMagickString(fuzz,"%",MaxTextExtent);
3554 (*image)->fuzz=SiPrefixToDouble(fuzz,1.0*QuantumRange+1.0);
3557 case ColorEditUndoCommand:
3559 (void) XMagickCommand(display,resource_info,windows,UndoCommand,
3563 case ColorEditHelpCommand:
3566 XTextViewWidget(display,resource_info,windows,MagickFalse,
3567 "Help Viewer - Image Annotation",ImageColorEditHelp);
3570 case ColorEditDismissCommand:
3580 (void) XCheckDefineCursor(display,windows->image.id,cursor);
3587 if (event.xbutton.button != Button1)
3589 if ((event.xbutton.window != windows->image.id) &&
3590 (event.xbutton.window != windows->magnify.id))
3597 (void) XMagickCommand(display,resource_info,windows,
3598 SaveToUndoBufferCommand,image,exception);
3599 state|=UpdateConfigurationState;
3604 if (event.xbutton.button != Button1)
3606 if ((event.xbutton.window != windows->image.id) &&
3607 (event.xbutton.window != windows->magnify.id))
3610 Update colormap information.
3614 XConfigureImageColormap(display,resource_info,windows,*image);
3615 (void) XConfigureImage(display,resource_info,windows,*image,exception);
3616 XInfoWidget(display,windows,text);
3617 (void) XCheckDefineCursor(display,windows->image.id,cursor);
3618 state&=(~UpdateConfigurationState);
3628 if (event.xkey.window == windows->magnify.id)
3633 window=windows->magnify.id;
3634 while (XCheckWindowEvent(display,window,KeyPressMask,&event)) ;
3636 if (event.xkey.window != windows->image.id)
3639 Respond to a user key press.
3641 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
3642 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
3643 switch ((int) key_symbol)
3657 XTextViewWidget(display,resource_info,windows,MagickFalse,
3658 "Help Viewer - Image Annotation",ImageColorEditHelp);
3663 (void) XBell(display,0);
3672 Map and unmap Info widget as cursor crosses its boundaries.
3676 if (windows->info.mapped != MagickFalse)
3678 if ((x < (int) (windows->info.x+windows->info.width)) &&
3679 (y < (int) (windows->info.y+windows->info.height)))
3680 (void) XWithdrawWindow(display,windows->info.id,
3681 windows->info.screen);
3684 if ((x > (int) (windows->info.x+windows->info.width)) ||
3685 (y > (int) (windows->info.y+windows->info.height)))
3686 (void) XMapWindow(display,windows->info.id);
3692 if (event.xany.window == windows->magnify.id)
3694 x=windows->magnify.x-windows->image.x;
3695 y=windows->magnify.y-windows->image.y;
3699 if ((state & UpdateConfigurationState) != 0)
3709 Pixel edit is relative to image configuration.
3711 (void) XClearArea(display,windows->image.id,x_offset,y_offset,1,1,
3713 color=windows->pixel_info->pen_colors[pen_id];
3714 XPutPixel(windows->image.ximage,x_offset,y_offset,color.pixel);
3715 width=(unsigned int) (*image)->columns;
3716 height=(unsigned int) (*image)->rows;
3719 if (windows->image.crop_geometry != (char *) NULL)
3720 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,
3723 (width*(windows->image.x+x_offset)/windows->image.ximage->width+x);
3725 (height*(windows->image.y+y_offset)/windows->image.ximage->height+y);
3726 if ((x_offset < 0) || (y_offset < 0))
3728 if ((x_offset >= (int) (*image)->columns) ||
3729 (y_offset >= (int) (*image)->rows))
3731 image_view=AcquireCacheView(*image);
3738 Update color information using point algorithm.
3740 if (SetImageStorageClass(*image,DirectClass,exception) == MagickFalse)
3741 return(MagickFalse);
3742 q=GetCacheViewAuthenticPixels(image_view,(ssize_t)x_offset,
3743 (ssize_t) y_offset,1,1,exception);
3744 if (q == (Quantum *) NULL)
3746 SetPixelRed(*image,ScaleShortToQuantum(color.red),q);
3747 SetPixelGreen(*image,ScaleShortToQuantum(color.green),q);
3748 SetPixelBlue(*image,ScaleShortToQuantum(color.blue),q);
3749 (void) SyncCacheViewAuthenticPixels(image_view,exception);
3759 Update color information using replace algorithm.
3761 (void) GetOneCacheViewVirtualPixel(image_view,(ssize_t) x_offset,
3762 (ssize_t) y_offset,&target,exception);
3763 if ((*image)->storage_class == DirectClass)
3765 for (y=0; y < (int) (*image)->rows; y++)
3767 q=GetCacheViewAuthenticPixels(image_view,0,(ssize_t) y,
3768 (*image)->columns,1,exception);
3769 if (q == (Quantum *) NULL)
3771 for (x=0; x < (int) (*image)->columns; x++)
3773 GetPixelPacket(*image,q,&pixel);
3774 if (IsFuzzyEquivalencePixelPacket(*image,&pixel,&target))
3776 SetPixelRed(*image,ScaleShortToQuantum(
3778 SetPixelGreen(*image,ScaleShortToQuantum(
3780 SetPixelBlue(*image,ScaleShortToQuantum(
3783 q+=GetPixelChannels(*image);
3785 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
3791 for (i=0; i < (ssize_t) (*image)->colors; i++)
3792 if (IsFuzzyEquivalencePixelPacket(*image,(*image)->colormap+i,&target))
3794 (*image)->colormap[i].red=ScaleShortToQuantum(
3796 (*image)->colormap[i].green=ScaleShortToQuantum(
3798 (*image)->colormap[i].blue=ScaleShortToQuantum(
3801 (void) SyncImage(*image);
3805 case FloodfillMethod:
3806 case FillToBorderMethod:
3815 Update color information using floodfill algorithm.
3817 (void) GetOneVirtualMagickPixel(*image,(ssize_t) x_offset,
3818 (ssize_t) y_offset,&target,exception);
3819 if (method == FillToBorderMethod)
3821 target.red=(MagickRealType)
3822 ScaleShortToQuantum(border_color.red);
3823 target.green=(MagickRealType)
3824 ScaleShortToQuantum(border_color.green);
3825 target.blue=(MagickRealType)
3826 ScaleShortToQuantum(border_color.blue);
3828 draw_info=CloneDrawInfo(resource_info->image_info,
3830 (void) QueryColorDatabase(resource_info->pen_colors[pen_id],
3831 &draw_info->fill,exception);
3832 (void) FloodfillPaintImage(*image,draw_info,&target,(ssize_t)
3833 x_offset,(ssize_t) y_offset,method == FloodfillMethod ?
3834 MagickFalse : MagickTrue,exception);
3835 draw_info=DestroyDrawInfo(draw_info);
3841 Update color information using reset algorithm.
3843 if (SetImageStorageClass(*image,DirectClass,exception) == MagickFalse)
3844 return(MagickFalse);
3845 for (y=0; y < (int) (*image)->rows; y++)
3847 q=QueueCacheViewAuthenticPixels(image_view,0,(ssize_t) y,
3848 (*image)->columns,1,exception);
3849 if (q == (Quantum *) NULL)
3851 for (x=0; x < (int) (*image)->columns; x++)
3853 SetPixelRed(*image,ScaleShortToQuantum(color.red),q);
3854 SetPixelGreen(*image,ScaleShortToQuantum(color.green),q);
3855 SetPixelBlue(*image,ScaleShortToQuantum(color.blue),q);
3856 q+=GetPixelChannels(*image);
3858 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
3864 image_view=DestroyCacheView(image_view);
3865 state&=(~UpdateConfigurationState);
3867 } while ((state & ExitState) == 0);
3868 (void) XSelectInput(display,windows->image.id,
3869 windows->image.attributes.event_mask);
3870 XSetCursorState(display,windows,MagickFalse);
3871 (void) XFreeCursor(display,cursor);
3876 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3880 + X C o m p o s i t e I m a g e %
3884 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3886 % XCompositeImage() requests an image name from the user, reads the image and
3887 % composites it with the X window image at a location the user chooses with
3890 % The format of the XCompositeImage method is:
3892 % MagickBooleanType XCompositeImage(Display *display,
3893 % XResourceInfo *resource_info,XWindows *windows,Image *image,
3894 % ExceptionInfo *exception)
3896 % A description of each parameter follows:
3898 % o display: Specifies a connection to an X server; returned from
3901 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
3903 % o windows: Specifies a pointer to a XWindows structure.
3905 % o image: the image; returned from ReadImage.
3907 % o exception: return any errors or warnings in this structure.
3910 static MagickBooleanType XCompositeImage(Display *display,
3911 XResourceInfo *resource_info,XWindows *windows,Image *image,
3912 ExceptionInfo *exception)
3915 displacement_geometry[MaxTextExtent] = "30x30",
3916 filename[MaxTextExtent] = "\0";
3929 static CompositeOperator
3930 compose = CopyCompositeOp;
3932 static const ModeType
3933 CompositeCommands[] =
3935 CompositeOperatorsCommand,
3936 CompositeDissolveCommand,
3937 CompositeDisplaceCommand,
3938 CompositeHelpCommand,
3939 CompositeDismissCommand
3943 text[MaxTextExtent];
3976 Request image file name from user.
3978 XFileBrowserWidget(display,windows,"Composite",filename);
3979 if (*filename == '\0')
3984 XSetCursorState(display,windows,MagickTrue);
3985 XCheckRefreshWindows(display,windows);
3986 (void) CopyMagickString(resource_info->image_info->filename,filename,
3988 composite_image=ReadImage(resource_info->image_info,exception);
3989 CatchException(exception);
3990 XSetCursorState(display,windows,MagickFalse);
3991 if (composite_image == (Image *) NULL)
3992 return(MagickFalse);
3996 (void) CloneString(&windows->command.name,"Composite");
3997 windows->command.data=1;
3998 (void) XCommandWidget(display,windows,CompositeMenu,(XEvent *) NULL);
3999 (void) XMapRaised(display,windows->command.id);
4000 XClientMessage(display,windows->image.id,windows->im_protocols,
4001 windows->im_update_widget,CurrentTime);
4003 Track pointer until button 1 is pressed.
4005 XQueryPosition(display,windows->image.id,&x,&y);
4006 (void) XSelectInput(display,windows->image.id,
4007 windows->image.attributes.event_mask | PointerMotionMask);
4008 composite_info.x=(ssize_t) windows->image.x+x;
4009 composite_info.y=(ssize_t) windows->image.y+y;
4010 composite_info.width=0;
4011 composite_info.height=0;
4012 cursor=XCreateFontCursor(display,XC_ul_angle);
4013 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
4018 if (windows->info.mapped != MagickFalse)
4021 Display pointer position.
4023 (void) FormatLocaleString(text,MaxTextExtent," %+ld%+ld ",
4024 (long) composite_info.x,(long) composite_info.y);
4025 XInfoWidget(display,windows,text);
4027 highlight_info=composite_info;
4028 highlight_info.x=composite_info.x-windows->image.x;
4029 highlight_info.y=composite_info.y-windows->image.y;
4030 XHighlightRectangle(display,windows->image.id,
4031 windows->image.highlight_context,&highlight_info);
4033 Wait for next event.
4035 XScreenEvent(display,windows,&event);
4036 XHighlightRectangle(display,windows->image.id,
4037 windows->image.highlight_context,&highlight_info);
4038 if (event.xany.window == windows->command.id)
4041 Select a command from the Command widget.
4043 id=XCommandWidget(display,windows,CompositeMenu,&event);
4046 switch (CompositeCommands[id])
4048 case CompositeOperatorsCommand:
4051 command[MaxTextExtent],
4055 Select a command from the pop-up menu.
4057 operators=GetCommandOptions(MagickComposeOptions);
4058 if (operators == (char **) NULL)
4060 entry=XMenuWidget(display,windows,CompositeMenu[id],
4061 (const char **) operators,command);
4063 compose=(CompositeOperator) ParseCommandOption(
4064 MagickComposeOptions,MagickFalse,operators[entry]);
4065 operators=DestroyStringList(operators);
4068 case CompositeDissolveCommand:
4071 factor[MaxTextExtent] = "20.0";
4074 Dissolve the two images a given percent.
4076 (void) XSetFunction(display,windows->image.highlight_context,
4078 (void) XDialogWidget(display,windows,"Dissolve",
4079 "Enter the blend factor (0.0 - 99.9%):",factor);
4080 (void) XSetFunction(display,windows->image.highlight_context,
4082 if (*factor == '\0')
4084 blend=InterpretLocaleValue(factor,(char **) NULL);
4085 compose=DissolveCompositeOp;
4088 case CompositeDisplaceCommand:
4091 Get horizontal and vertical scale displacement geometry.
4093 (void) XSetFunction(display,windows->image.highlight_context,
4095 (void) XDialogWidget(display,windows,"Displace",
4096 "Enter the horizontal and vertical scale:",displacement_geometry);
4097 (void) XSetFunction(display,windows->image.highlight_context,
4099 if (*displacement_geometry == '\0')
4101 compose=DisplaceCompositeOp;
4104 case CompositeHelpCommand:
4106 (void) XSetFunction(display,windows->image.highlight_context,
4108 XTextViewWidget(display,resource_info,windows,MagickFalse,
4109 "Help Viewer - Image Composite",ImageCompositeHelp);
4110 (void) XSetFunction(display,windows->image.highlight_context,
4114 case CompositeDismissCommand:
4132 if (image->debug != MagickFalse)
4133 (void) LogMagickEvent(X11Event,GetMagickModule(),
4134 "Button Press: 0x%lx %u +%d+%d",event.xbutton.window,
4135 event.xbutton.button,event.xbutton.x,event.xbutton.y);
4136 if (event.xbutton.button != Button1)
4138 if (event.xbutton.window != windows->image.id)
4143 composite_info.width=composite_image->columns;
4144 composite_info.height=composite_image->rows;
4145 (void) XCheckDefineCursor(display,windows->image.id,cursor);
4146 composite_info.x=(ssize_t) windows->image.x+event.xbutton.x;
4147 composite_info.y=(ssize_t) windows->image.y+event.xbutton.y;
4152 if (image->debug != MagickFalse)
4153 (void) LogMagickEvent(X11Event,GetMagickModule(),
4154 "Button Release: 0x%lx %u +%d+%d",event.xbutton.window,
4155 event.xbutton.button,event.xbutton.x,event.xbutton.y);
4156 if (event.xbutton.button != Button1)
4158 if (event.xbutton.window != windows->image.id)
4160 if ((composite_info.width != 0) && (composite_info.height != 0))
4163 User has selected the location of the composite image.
4165 composite_info.x=(ssize_t) windows->image.x+event.xbutton.x;
4166 composite_info.y=(ssize_t) windows->image.y+event.xbutton.y;
4176 command[MaxTextExtent];
4184 if (event.xkey.window != windows->image.id)
4187 Respond to a user key press.
4189 length=XLookupString((XKeyEvent *) &event.xkey,command,(int)
4190 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
4191 *(command+length)='\0';
4192 if (image->debug != MagickFalse)
4193 (void) LogMagickEvent(X11Event,GetMagickModule(),
4194 "Key press: 0x%lx (%s)",(unsigned long) key_symbol,command);
4195 switch ((int) key_symbol)
4203 composite_image=DestroyImage(composite_image);
4211 (void) XSetFunction(display,windows->image.highlight_context,
4213 XTextViewWidget(display,resource_info,windows,MagickFalse,
4214 "Help Viewer - Image Composite",ImageCompositeHelp);
4215 (void) XSetFunction(display,windows->image.highlight_context,
4221 (void) XBell(display,0);
4230 Map and unmap Info widget as text cursor crosses its boundaries.
4234 if (windows->info.mapped != MagickFalse)
4236 if ((x < (int) (windows->info.x+windows->info.width)) &&
4237 (y < (int) (windows->info.y+windows->info.height)))
4238 (void) XWithdrawWindow(display,windows->info.id,
4239 windows->info.screen);
4242 if ((x > (int) (windows->info.x+windows->info.width)) ||
4243 (y > (int) (windows->info.y+windows->info.height)))
4244 (void) XMapWindow(display,windows->info.id);
4245 composite_info.x=(ssize_t) windows->image.x+x;
4246 composite_info.y=(ssize_t) windows->image.y+y;
4251 if (image->debug != MagickFalse)
4252 (void) LogMagickEvent(X11Event,GetMagickModule(),"Event type: %d",
4257 } while ((state & ExitState) == 0);
4258 (void) XSelectInput(display,windows->image.id,
4259 windows->image.attributes.event_mask);
4260 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
4261 XSetCursorState(display,windows,MagickFalse);
4262 (void) XFreeCursor(display,cursor);
4263 if ((state & EscapeState) != 0)
4266 Image compositing is relative to image configuration.
4268 XSetCursorState(display,windows,MagickTrue);
4269 XCheckRefreshWindows(display,windows);
4270 width=(unsigned int) image->columns;
4271 height=(unsigned int) image->rows;
4274 if (windows->image.crop_geometry != (char *) NULL)
4275 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
4276 scale_factor=(MagickRealType) width/windows->image.ximage->width;
4277 composite_info.x+=x;
4278 composite_info.x=(ssize_t) (scale_factor*composite_info.x+0.5);
4279 composite_info.width=(unsigned int) (scale_factor*composite_info.width+0.5);
4280 scale_factor=(MagickRealType) height/windows->image.ximage->height;
4281 composite_info.y+=y;
4282 composite_info.y=(ssize_t) (scale_factor*composite_info.y+0.5);
4283 composite_info.height=(unsigned int) (scale_factor*composite_info.height+0.5);
4284 if ((composite_info.width != composite_image->columns) ||
4285 (composite_info.height != composite_image->rows))
4291 Scale composite image.
4293 resize_image=ResizeImage(composite_image,composite_info.width,
4294 composite_info.height,composite_image->filter,composite_image->blur,
4296 composite_image=DestroyImage(composite_image);
4297 if (resize_image == (Image *) NULL)
4299 XSetCursorState(display,windows,MagickFalse);
4300 return(MagickFalse);
4302 composite_image=resize_image;
4304 if (compose == DisplaceCompositeOp)
4305 (void) SetImageArtifact(composite_image,"compose:args",
4306 displacement_geometry);
4325 Create mattes for blending.
4327 (void) SetImageAlphaChannel(composite_image,OpaqueAlphaChannel,exception);
4328 opacity=(Quantum) (ScaleQuantumToChar((Quantum) QuantumRange)-
4329 ((ssize_t) ScaleQuantumToChar((Quantum) QuantumRange)*blend)/100);
4330 if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
4331 return(MagickFalse);
4332 image->matte=MagickTrue;
4333 image_view=AcquireCacheView(image);
4334 for (y=0; y < (int) image->rows; y++)
4336 q=GetCacheViewAuthenticPixels(image_view,0,(ssize_t) y,image->columns,1,
4338 if (q == (Quantum *) NULL)
4340 for (x=0; x < (int) image->columns; x++)
4342 SetPixelAlpha(image,opacity,q);
4343 q+=GetPixelChannels(image);
4345 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
4348 image_view=DestroyCacheView(image_view);
4351 Composite image with X Image window.
4353 (void) CompositeImage(image,compose,composite_image,composite_info.x,
4355 composite_image=DestroyImage(composite_image);
4356 XSetCursorState(display,windows,MagickFalse);
4358 Update image configuration.
4360 XConfigureImageColormap(display,resource_info,windows,image);
4361 (void) XConfigureImage(display,resource_info,windows,image,exception);
4366 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4370 + X C o n f i g u r e I m a g e %
4374 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4376 % XConfigureImage() creates a new X image. It also notifies the window
4377 % manager of the new image size and configures the transient widows.
4379 % The format of the XConfigureImage method is:
4381 % MagickBooleanType XConfigureImage(Display *display,
4382 % XResourceInfo *resource_info,XWindows *windows,Image *image,
4383 % ExceptionInfo *exception)
4385 % A description of each parameter follows:
4387 % o display: Specifies a connection to an X server; returned from
4390 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
4392 % o windows: Specifies a pointer to a XWindows structure.
4394 % o image: the image.
4396 % o exception: return any errors or warnings in this structure.
4398 % o exception: return any errors or warnings in this structure.
4401 static MagickBooleanType XConfigureImage(Display *display,
4402 XResourceInfo *resource_info,XWindows *windows,Image *image,
4403 ExceptionInfo *exception)
4406 geometry[MaxTextExtent];
4427 Dismiss if window dimensions are zero.
4429 width=(unsigned int) windows->image.window_changes.width;
4430 height=(unsigned int) windows->image.window_changes.height;
4431 if (image->debug != MagickFalse)
4432 (void) LogMagickEvent(X11Event,GetMagickModule(),
4433 "Configure Image: %dx%d=>%.20gx%.20g",windows->image.ximage->width,
4434 windows->image.ximage->height,(double) width,(double) height);
4435 if ((width*height) == 0)
4440 Resize image to fit Image window dimensions.
4442 XSetCursorState(display,windows,MagickTrue);
4443 (void) XFlush(display);
4444 if (((int) width != windows->image.ximage->width) ||
4445 ((int) height != windows->image.ximage->height))
4446 image->taint=MagickTrue;
4447 windows->magnify.x=(int)
4448 width*windows->magnify.x/windows->image.ximage->width;
4449 windows->magnify.y=(int)
4450 height*windows->magnify.y/windows->image.ximage->height;
4451 windows->image.x=(int) (width*windows->image.x/windows->image.ximage->width);
4452 windows->image.y=(int)
4453 (height*windows->image.y/windows->image.ximage->height);
4454 status=XMakeImage(display,resource_info,&windows->image,image,
4455 (unsigned int) width,(unsigned int) height,exception);
4456 if (status == MagickFalse)
4457 XNoticeWidget(display,windows,"Unable to configure X image:",
4458 windows->image.name);
4460 Notify window manager of the new configuration.
4462 if (resource_info->image_geometry != (char *) NULL)
4463 (void) FormatLocaleString(geometry,MaxTextExtent,"%s>!",
4464 resource_info->image_geometry);
4466 (void) FormatLocaleString(geometry,MaxTextExtent,"%ux%u+0+0>!",
4467 XDisplayWidth(display,windows->image.screen),
4468 XDisplayHeight(display,windows->image.screen));
4469 (void) ParseMetaGeometry(geometry,&x,&y,&width,&height);
4470 window_changes.width=(int) width;
4471 if (window_changes.width > XDisplayWidth(display,windows->image.screen))
4472 window_changes.width=XDisplayWidth(display,windows->image.screen);
4473 window_changes.height=(int) height;
4474 if (window_changes.height > XDisplayHeight(display,windows->image.screen))
4475 window_changes.height=XDisplayHeight(display,windows->image.screen);
4476 mask=(size_t) (CWWidth | CWHeight);
4477 if (resource_info->backdrop)
4480 window_changes.x=(int)
4481 ((XDisplayWidth(display,windows->image.screen)/2)-(width/2));
4482 window_changes.y=(int)
4483 ((XDisplayHeight(display,windows->image.screen)/2)-(height/2));
4485 (void) XReconfigureWMWindow(display,windows->image.id,windows->image.screen,
4486 (unsigned int) mask,&window_changes);
4487 (void) XClearWindow(display,windows->image.id);
4488 XRefreshWindow(display,&windows->image,(XEvent *) NULL);
4490 Update Magnify window configuration.
4492 if (windows->magnify.mapped != MagickFalse)
4493 XMakeMagnifyImage(display,windows);
4494 windows->pan.crop_geometry=windows->image.crop_geometry;
4495 XBestIconSize(display,&windows->pan,image);
4496 while (((windows->pan.width << 1) < MaxIconSize) &&
4497 ((windows->pan.height << 1) < MaxIconSize))
4499 windows->pan.width<<=1;
4500 windows->pan.height<<=1;
4502 if (windows->pan.geometry != (char *) NULL)
4503 (void) XParseGeometry(windows->pan.geometry,&windows->pan.x,&windows->pan.y,
4504 &windows->pan.width,&windows->pan.height);
4505 window_changes.width=(int) windows->pan.width;
4506 window_changes.height=(int) windows->pan.height;
4507 size_hints=XAllocSizeHints();
4508 if (size_hints != (XSizeHints *) NULL)
4513 size_hints->flags=PSize | PMinSize | PMaxSize;
4514 size_hints->width=window_changes.width;
4515 size_hints->height=window_changes.height;
4516 size_hints->min_width=size_hints->width;
4517 size_hints->min_height=size_hints->height;
4518 size_hints->max_width=size_hints->width;
4519 size_hints->max_height=size_hints->height;
4520 (void) XSetNormalHints(display,windows->pan.id,size_hints);
4521 (void) XFree((void *) size_hints);
4523 (void) XReconfigureWMWindow(display,windows->pan.id,windows->pan.screen,
4524 (unsigned int) (CWWidth | CWHeight),&window_changes);
4526 Update icon window configuration.
4528 windows->icon.crop_geometry=windows->image.crop_geometry;
4529 XBestIconSize(display,&windows->icon,image);
4530 window_changes.width=(int) windows->icon.width;
4531 window_changes.height=(int) windows->icon.height;
4532 (void) XReconfigureWMWindow(display,windows->icon.id,windows->icon.screen,
4533 (unsigned int) (CWWidth | CWHeight),&window_changes);
4534 XSetCursorState(display,windows,MagickFalse);
4535 return(status != 0 ? MagickTrue : MagickFalse);
4539 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4543 + X C r o p I m a g e %
4547 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4549 % XCropImage() allows the user to select a region of the image and crop, copy,
4550 % or cut it. For copy or cut, the image can subsequently be composited onto
4551 % the image with XPasteImage.
4553 % The format of the XCropImage method is:
4555 % MagickBooleanType XCropImage(Display *display,
4556 % XResourceInfo *resource_info,XWindows *windows,Image *image,
4557 % const ClipboardMode mode,ExceptionInfo *exception)
4559 % A description of each parameter follows:
4561 % o display: Specifies a connection to an X server; returned from
4564 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
4566 % o windows: Specifies a pointer to a XWindows structure.
4568 % o image: the image; returned from ReadImage.
4570 % o mode: This unsigned value specified whether the image should be
4571 % cropped, copied, or cut.
4573 % o exception: return any errors or warnings in this structure.
4576 static MagickBooleanType XCropImage(Display *display,
4577 XResourceInfo *resource_info,XWindows *windows,Image *image,
4578 const ClipboardMode mode,ExceptionInfo *exception)
4587 *RectifyModeMenu[] =
4595 static const ModeType
4605 RectifyDismissCommand
4612 command[MaxTextExtent],
4613 text[MaxTextExtent];
4656 (void) CloneString(&windows->command.name,"Copy");
4661 (void) CloneString(&windows->command.name,"Crop");
4666 (void) CloneString(&windows->command.name,"Cut");
4670 RectifyModeMenu[0]=windows->command.name;
4671 windows->command.data=0;
4672 (void) XCommandWidget(display,windows,CropModeMenu,(XEvent *) NULL);
4673 (void) XMapRaised(display,windows->command.id);
4674 XClientMessage(display,windows->image.id,windows->im_protocols,
4675 windows->im_update_widget,CurrentTime);
4677 Track pointer until button 1 is pressed.
4679 XQueryPosition(display,windows->image.id,&x,&y);
4680 (void) XSelectInput(display,windows->image.id,
4681 windows->image.attributes.event_mask | PointerMotionMask);
4682 crop_info.x=(ssize_t) windows->image.x+x;
4683 crop_info.y=(ssize_t) windows->image.y+y;
4686 cursor=XCreateFontCursor(display,XC_fleur);
4690 if (windows->info.mapped != MagickFalse)
4693 Display pointer position.
4695 (void) FormatLocaleString(text,MaxTextExtent," %+ld%+ld ",
4696 (long) crop_info.x,(long) crop_info.y);
4697 XInfoWidget(display,windows,text);
4700 Wait for next event.
4702 XScreenEvent(display,windows,&event);
4703 if (event.xany.window == windows->command.id)
4706 Select a command from the Command widget.
4708 id=XCommandWidget(display,windows,CropModeMenu,&event);
4711 switch (CropCommands[id])
4713 case CropHelpCommand:
4719 XTextViewWidget(display,resource_info,windows,MagickFalse,
4720 "Help Viewer - Image Copy",ImageCopyHelp);
4725 XTextViewWidget(display,resource_info,windows,MagickFalse,
4726 "Help Viewer - Image Crop",ImageCropHelp);
4731 XTextViewWidget(display,resource_info,windows,MagickFalse,
4732 "Help Viewer - Image Cut",ImageCutHelp);
4738 case CropDismissCommand:
4756 if (event.xbutton.button != Button1)
4758 if (event.xbutton.window != windows->image.id)
4761 Note first corner of cropping rectangle-- exit loop.
4763 (void) XCheckDefineCursor(display,windows->image.id,cursor);
4764 crop_info.x=(ssize_t) windows->image.x+event.xbutton.x;
4765 crop_info.y=(ssize_t) windows->image.y+event.xbutton.y;
4775 if (event.xkey.window != windows->image.id)
4778 Respond to a user key press.
4780 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
4781 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
4782 switch ((int) key_symbol)
4801 XTextViewWidget(display,resource_info,windows,MagickFalse,
4802 "Help Viewer - Image Copy",ImageCopyHelp);
4807 XTextViewWidget(display,resource_info,windows,MagickFalse,
4808 "Help Viewer - Image Crop",ImageCropHelp);
4813 XTextViewWidget(display,resource_info,windows,MagickFalse,
4814 "Help Viewer - Image Cut",ImageCutHelp);
4822 (void) XBell(display,0);
4830 if (event.xmotion.window != windows->image.id)
4833 Map and unmap Info widget as text cursor crosses its boundaries.
4837 if (windows->info.mapped != MagickFalse)
4839 if ((x < (int) (windows->info.x+windows->info.width)) &&
4840 (y < (int) (windows->info.y+windows->info.height)))
4841 (void) XWithdrawWindow(display,windows->info.id,
4842 windows->info.screen);
4845 if ((x > (int) (windows->info.x+windows->info.width)) ||
4846 (y > (int) (windows->info.y+windows->info.height)))
4847 (void) XMapWindow(display,windows->info.id);
4848 crop_info.x=(ssize_t) windows->image.x+x;
4849 crop_info.y=(ssize_t) windows->image.y+y;
4855 } while ((state & ExitState) == 0);
4856 (void) XSelectInput(display,windows->image.id,
4857 windows->image.attributes.event_mask);
4858 if ((state & EscapeState) != 0)
4861 User want to exit without cropping.
4863 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
4864 (void) XFreeCursor(display,cursor);
4867 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
4871 Size rectangle as pointer moves until the mouse button is released.
4873 x=(int) crop_info.x;
4874 y=(int) crop_info.y;
4880 highlight_info=crop_info;
4881 highlight_info.x=crop_info.x-windows->image.x;
4882 highlight_info.y=crop_info.y-windows->image.y;
4883 if ((highlight_info.width > 3) && (highlight_info.height > 3))
4886 Display info and draw cropping rectangle.
4888 if (windows->info.mapped == MagickFalse)
4889 (void) XMapWindow(display,windows->info.id);
4890 (void) FormatLocaleString(text,MaxTextExtent,
4891 " %.20gx%.20g%+.20g%+.20g",(double) crop_info.width,(double)
4892 crop_info.height,(double) crop_info.x,(double) crop_info.y);
4893 XInfoWidget(display,windows,text);
4894 XHighlightRectangle(display,windows->image.id,
4895 windows->image.highlight_context,&highlight_info);
4898 if (windows->info.mapped != MagickFalse)
4899 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
4901 Wait for next event.
4903 XScreenEvent(display,windows,&event);
4904 if ((highlight_info.width > 3) && (highlight_info.height > 3))
4905 XHighlightRectangle(display,windows->image.id,
4906 windows->image.highlight_context,&highlight_info);
4911 crop_info.x=(ssize_t) windows->image.x+event.xbutton.x;
4912 crop_info.y=(ssize_t) windows->image.y+event.xbutton.y;
4918 User has committed to cropping rectangle.
4920 crop_info.x=(ssize_t) windows->image.x+event.xbutton.x;
4921 crop_info.y=(ssize_t) windows->image.y+event.xbutton.y;
4922 XSetCursorState(display,windows,MagickFalse);
4924 windows->command.data=0;
4925 (void) XCommandWidget(display,windows,RectifyModeMenu,
4933 crop_info.x=(ssize_t) windows->image.x+event.xmotion.x;
4934 crop_info.y=(ssize_t) windows->image.y+event.xmotion.y;
4939 if ((((int) crop_info.x != x) && ((int) crop_info.y != y)) ||
4940 ((state & ExitState) != 0))
4943 Check boundary conditions.
4945 if (crop_info.x < 0)
4948 if (crop_info.x > (ssize_t) windows->image.ximage->width)
4949 crop_info.x=(ssize_t) windows->image.ximage->width;
4950 if ((int) crop_info.x < x)
4951 crop_info.width=(unsigned int) (x-crop_info.x);
4954 crop_info.width=(unsigned int) (crop_info.x-x);
4955 crop_info.x=(ssize_t) x;
4957 if (crop_info.y < 0)
4960 if (crop_info.y > (ssize_t) windows->image.ximage->height)
4961 crop_info.y=(ssize_t) windows->image.ximage->height;
4962 if ((int) crop_info.y < y)
4963 crop_info.height=(unsigned int) (y-crop_info.y);
4966 crop_info.height=(unsigned int) (crop_info.y-y);
4967 crop_info.y=(ssize_t) y;
4970 } while ((state & ExitState) == 0);
4972 Wait for user to grab a corner of the rectangle or press return.
4975 (void) XMapWindow(display,windows->info.id);
4978 if (windows->info.mapped != MagickFalse)
4981 Display pointer position.
4983 (void) FormatLocaleString(text,MaxTextExtent,
4984 " %.20gx%.20g%+.20g%+.20g",(double) crop_info.width,(double)
4985 crop_info.height,(double) crop_info.x,(double) crop_info.y);
4986 XInfoWidget(display,windows,text);
4988 highlight_info=crop_info;
4989 highlight_info.x=crop_info.x-windows->image.x;
4990 highlight_info.y=crop_info.y-windows->image.y;
4991 if ((highlight_info.width <= 3) || (highlight_info.height <= 3))
4997 XHighlightRectangle(display,windows->image.id,
4998 windows->image.highlight_context,&highlight_info);
4999 XScreenEvent(display,windows,&event);
5000 if (event.xany.window == windows->command.id)
5003 Select a command from the Command widget.
5005 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
5006 id=XCommandWidget(display,windows,RectifyModeMenu,&event);
5007 (void) XSetFunction(display,windows->image.highlight_context,
5009 XHighlightRectangle(display,windows->image.id,
5010 windows->image.highlight_context,&highlight_info);
5012 switch (RectifyCommands[id])
5014 case RectifyCopyCommand:
5019 case RectifyHelpCommand:
5021 (void) XSetFunction(display,windows->image.highlight_context,
5027 XTextViewWidget(display,resource_info,windows,MagickFalse,
5028 "Help Viewer - Image Copy",ImageCopyHelp);
5033 XTextViewWidget(display,resource_info,windows,MagickFalse,
5034 "Help Viewer - Image Crop",ImageCropHelp);
5039 XTextViewWidget(display,resource_info,windows,MagickFalse,
5040 "Help Viewer - Image Cut",ImageCutHelp);
5044 (void) XSetFunction(display,windows->image.highlight_context,
5048 case RectifyDismissCommand:
5062 XHighlightRectangle(display,windows->image.id,
5063 windows->image.highlight_context,&highlight_info);
5068 if (event.xbutton.button != Button1)
5070 if (event.xbutton.window != windows->image.id)
5072 x=windows->image.x+event.xbutton.x;
5073 y=windows->image.y+event.xbutton.y;
5074 if ((x < (int) (crop_info.x+RoiDelta)) &&
5075 (x > (int) (crop_info.x-RoiDelta)) &&
5076 (y < (int) (crop_info.y+RoiDelta)) &&
5077 (y > (int) (crop_info.y-RoiDelta)))
5079 crop_info.x=(ssize_t) (crop_info.x+crop_info.width);
5080 crop_info.y=(ssize_t) (crop_info.y+crop_info.height);
5081 state|=UpdateConfigurationState;
5084 if ((x < (int) (crop_info.x+RoiDelta)) &&
5085 (x > (int) (crop_info.x-RoiDelta)) &&
5086 (y < (int) (crop_info.y+crop_info.height+RoiDelta)) &&
5087 (y > (int) (crop_info.y+crop_info.height-RoiDelta)))
5089 crop_info.x=(ssize_t) (crop_info.x+crop_info.width);
5090 state|=UpdateConfigurationState;
5093 if ((x < (int) (crop_info.x+crop_info.width+RoiDelta)) &&
5094 (x > (int) (crop_info.x+crop_info.width-RoiDelta)) &&
5095 (y < (int) (crop_info.y+RoiDelta)) &&
5096 (y > (int) (crop_info.y-RoiDelta)))
5098 crop_info.y=(ssize_t) (crop_info.y+crop_info.height);
5099 state|=UpdateConfigurationState;
5102 if ((x < (int) (crop_info.x+crop_info.width+RoiDelta)) &&
5103 (x > (int) (crop_info.x+crop_info.width-RoiDelta)) &&
5104 (y < (int) (crop_info.y+crop_info.height+RoiDelta)) &&
5105 (y > (int) (crop_info.y+crop_info.height-RoiDelta)))
5107 state|=UpdateConfigurationState;
5113 if (event.xbutton.window == windows->pan.id)
5114 if ((highlight_info.x != crop_info.x-windows->image.x) ||
5115 (highlight_info.y != crop_info.y-windows->image.y))
5116 XHighlightRectangle(display,windows->image.id,
5117 windows->image.highlight_context,&highlight_info);
5118 (void) XSetSelectionOwner(display,XA_PRIMARY,windows->image.id,
5119 event.xbutton.time);
5124 if (event.xexpose.window == windows->image.id)
5125 if (event.xexpose.count == 0)
5127 event.xexpose.x=(int) highlight_info.x;
5128 event.xexpose.y=(int) highlight_info.y;
5129 event.xexpose.width=(int) highlight_info.width;
5130 event.xexpose.height=(int) highlight_info.height;
5131 XRefreshWindow(display,&windows->image,&event);
5133 if (event.xexpose.window == windows->info.id)
5134 if (event.xexpose.count == 0)
5135 XInfoWidget(display,windows,text);
5140 if (event.xkey.window != windows->image.id)
5143 Respond to a user key press.
5145 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
5146 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
5147 switch ((int) key_symbol)
5160 crop_info.x=(ssize_t) (windows->image.width/2L-
5161 crop_info.width/2L);
5162 crop_info.y=(ssize_t) (windows->image.height/2L-
5163 crop_info.height/2L);
5195 (void) XSetFunction(display,windows->image.highlight_context,
5201 XTextViewWidget(display,resource_info,windows,MagickFalse,
5202 "Help Viewer - Image Copy",ImageCopyHelp);
5207 XTextViewWidget(display,resource_info,windows,MagickFalse,
5208 "Help Viewer - Image Cropg",ImageCropHelp);
5213 XTextViewWidget(display,resource_info,windows,MagickFalse,
5214 "Help Viewer - Image Cutg",ImageCutHelp);
5218 (void) XSetFunction(display,windows->image.highlight_context,
5224 (void) XBell(display,0);
5228 (void) XSetSelectionOwner(display,XA_PRIMARY,windows->image.id,
5236 if (event.xmotion.window != windows->image.id)
5239 Map and unmap Info widget as text cursor crosses its boundaries.
5243 if (windows->info.mapped != MagickFalse)
5245 if ((x < (int) (windows->info.x+windows->info.width)) &&
5246 (y < (int) (windows->info.y+windows->info.height)))
5247 (void) XWithdrawWindow(display,windows->info.id,
5248 windows->info.screen);
5251 if ((x > (int) (windows->info.x+windows->info.width)) ||
5252 (y > (int) (windows->info.y+windows->info.height)))
5253 (void) XMapWindow(display,windows->info.id);
5254 crop_info.x=(ssize_t) windows->image.x+event.xmotion.x;
5255 crop_info.y=(ssize_t) windows->image.y+event.xmotion.y;
5258 case SelectionRequest:
5263 XSelectionRequestEvent
5267 Set primary selection.
5269 (void) FormatLocaleString(text,MaxTextExtent,
5270 "%.20gx%.20g%+.20g%+.20g",(double) crop_info.width,(double)
5271 crop_info.height,(double) crop_info.x,(double) crop_info.y);
5272 request=(&(event.xselectionrequest));
5273 (void) XChangeProperty(request->display,request->requestor,
5274 request->property,request->target,8,PropModeReplace,
5275 (unsigned char *) text,(int) strlen(text));
5276 notify.type=SelectionNotify;
5277 notify.display=request->display;
5278 notify.requestor=request->requestor;
5279 notify.selection=request->selection;
5280 notify.target=request->target;
5281 notify.time=request->time;
5282 if (request->property == None)
5283 notify.property=request->target;
5285 notify.property=request->property;
5286 (void) XSendEvent(request->display,request->requestor,False,0,
5287 (XEvent *) ¬ify);
5292 if ((state & UpdateConfigurationState) != 0)
5294 (void) XPutBackEvent(display,&event);
5295 (void) XCheckDefineCursor(display,windows->image.id,cursor);
5298 } while ((state & ExitState) == 0);
5299 } while ((state & ExitState) == 0);
5300 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
5301 XSetCursorState(display,windows,MagickFalse);
5302 if ((state & EscapeState) != 0)
5304 if (mode == CropMode)
5305 if (((int) crop_info.width != windows->image.ximage->width) ||
5306 ((int) crop_info.height != windows->image.ximage->height))
5309 Reconfigure Image window as defined by cropping rectangle.
5311 XSetCropGeometry(display,windows,&crop_info,image);
5312 windows->image.window_changes.width=(int) crop_info.width;
5313 windows->image.window_changes.height=(int) crop_info.height;
5314 (void) XConfigureImage(display,resource_info,windows,image,exception);
5318 Copy image before applying image transforms.
5320 XSetCursorState(display,windows,MagickTrue);
5321 XCheckRefreshWindows(display,windows);
5322 width=(unsigned int) image->columns;
5323 height=(unsigned int) image->rows;
5326 if (windows->image.crop_geometry != (char *) NULL)
5327 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
5328 scale_factor=(MagickRealType) width/windows->image.ximage->width;
5330 crop_info.x=(ssize_t) (scale_factor*crop_info.x+0.5);
5331 crop_info.width=(unsigned int) (scale_factor*crop_info.width+0.5);
5332 scale_factor=(MagickRealType) height/windows->image.ximage->height;
5334 crop_info.y=(ssize_t) (scale_factor*crop_info.y+0.5);
5335 crop_info.height=(unsigned int) (scale_factor*crop_info.height+0.5);
5336 crop_image=CropImage(image,&crop_info,exception);
5337 XSetCursorState(display,windows,MagickFalse);
5338 if (crop_image == (Image *) NULL)
5339 return(MagickFalse);
5340 if (resource_info->copy_image != (Image *) NULL)
5341 resource_info->copy_image=DestroyImage(resource_info->copy_image);
5342 resource_info->copy_image=crop_image;
5343 if (mode == CopyMode)
5345 (void) XConfigureImage(display,resource_info,windows,image,exception);
5351 if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
5352 return(MagickFalse);
5353 image->matte=MagickTrue;
5354 image_view=AcquireCacheView(image);
5355 for (y=0; y < (int) crop_info.height; y++)
5357 q=GetCacheViewAuthenticPixels(image_view,crop_info.x,y+crop_info.y,
5358 crop_info.width,1,exception);
5359 if (q == (Quantum *) NULL)
5361 for (x=0; x < (int) crop_info.width; x++)
5363 SetPixelAlpha(image,TransparentAlpha,q);
5364 q+=GetPixelChannels(image);
5366 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
5369 image_view=DestroyCacheView(image_view);
5371 Update image configuration.
5373 XConfigureImageColormap(display,resource_info,windows,image);
5374 (void) XConfigureImage(display,resource_info,windows,image,exception);
5379 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5383 + X D r a w I m a g e %
5387 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5389 % XDrawEditImage() draws a graphic element (point, line, rectangle, etc.) on
5392 % The format of the XDrawEditImage method is:
5394 % MagickBooleanType XDrawEditImage(Display *display,
5395 % XResourceInfo *resource_info,XWindows *windows,Image **image,
5396 % ExceptionInfo *exception)
5398 % A description of each parameter follows:
5400 % o display: Specifies a connection to an X server; returned from
5403 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5405 % o windows: Specifies a pointer to a XWindows structure.
5407 % o image: the image.
5409 % o exception: return any errors or warnings in this structure.
5412 static MagickBooleanType XDrawEditImage(Display *display,
5413 XResourceInfo *resource_info,XWindows *windows,Image **image,
5414 ExceptionInfo *exception)
5430 element = PointElement;
5432 static const ModeType
5445 stipple = (Pixmap) NULL;
5452 command[MaxTextExtent],
5453 text[MaxTextExtent];
5502 Allocate polygon info.
5504 max_coordinates=2048;
5505 coordinate_info=(XPoint *) AcquireQuantumMemory((size_t) max_coordinates,
5506 sizeof(*coordinate_info));
5507 if (coordinate_info == (XPoint *) NULL)
5509 (void) ThrowMagickException(exception,GetMagickModule(),
5510 ResourceLimitError,"MemoryAllocationFailed","`%s'","...");
5511 return(MagickFalse);
5516 (void) CloneString(&windows->command.name,"Draw");
5517 windows->command.data=4;
5518 (void) XCommandWidget(display,windows,DrawMenu,(XEvent *) NULL);
5519 (void) XMapRaised(display,windows->command.id);
5520 XClientMessage(display,windows->image.id,windows->im_protocols,
5521 windows->im_update_widget,CurrentTime);
5523 Wait for first button press.
5525 root_window=XRootWindow(display,XDefaultScreen(display));
5526 draw_info.stencil=OpaqueStencil;
5528 cursor=XCreateFontCursor(display,XC_tcross);
5531 XQueryPosition(display,windows->image.id,&x,&y);
5532 (void) XSelectInput(display,windows->image.id,
5533 windows->image.attributes.event_mask | PointerMotionMask);
5534 (void) XCheckDefineCursor(display,windows->image.id,cursor);
5538 if (windows->info.mapped != MagickFalse)
5541 Display pointer position.
5543 (void) FormatLocaleString(text,MaxTextExtent," %+d%+d ",
5544 x+windows->image.x,y+windows->image.y);
5545 XInfoWidget(display,windows,text);
5548 Wait for next event.
5550 XScreenEvent(display,windows,&event);
5551 if (event.xany.window == windows->command.id)
5554 Select a command from the Command widget.
5556 id=XCommandWidget(display,windows,DrawMenu,&event);
5559 switch (DrawCommands[id])
5561 case DrawElementCommand:
5580 Select a command from the pop-up menu.
5582 element=(ElementType) (XMenuWidget(display,windows,
5583 DrawMenu[id],Elements,command)+1);
5586 case DrawColorCommand:
5589 *ColorMenu[MaxNumberPens+1];
5601 Initialize menu selections.
5603 for (i=0; i < (int) (MaxNumberPens-2); i++)
5604 ColorMenu[i]=resource_info->pen_colors[i];
5605 ColorMenu[MaxNumberPens-2]="transparent";
5606 ColorMenu[MaxNumberPens-1]="Browser...";
5607 ColorMenu[MaxNumberPens]=(char *) NULL;
5609 Select a pen color from the pop-up menu.
5611 pen_number=XMenuWidget(display,windows,DrawMenu[id],
5612 (const char **) ColorMenu,command);
5615 transparent=pen_number == (MaxNumberPens-2) ? MagickTrue :
5617 if (transparent != MagickFalse)
5619 draw_info.stencil=TransparentStencil;
5622 if (pen_number == (MaxNumberPens-1))
5625 color_name[MaxTextExtent] = "gray";
5628 Select a pen color from a dialog.
5630 resource_info->pen_colors[pen_number]=color_name;
5631 XColorBrowserWidget(display,windows,"Select",color_name);
5632 if (*color_name == '\0')
5638 (void) XParseColor(display,windows->map_info->colormap,
5639 resource_info->pen_colors[pen_number],&color);
5640 XBestPixel(display,windows->map_info->colormap,(XColor *) NULL,
5641 (unsigned int) MaxColors,&color);
5642 windows->pixel_info->pen_colors[pen_number]=color;
5643 pen_id=(unsigned int) pen_number;
5644 draw_info.stencil=OpaqueStencil;
5647 case DrawStippleCommand:
5659 filename[MaxTextExtent] = "\0";
5676 Select a command from the pop-up menu.
5678 StipplesMenu[7]="Open...";
5679 entry=XMenuWidget(display,windows,DrawMenu[id],StipplesMenu,
5683 if (stipple != (Pixmap) NULL)
5684 (void) XFreePixmap(display,stipple);
5685 stipple=(Pixmap) NULL;
5692 stipple=XCreateBitmapFromData(display,root_window,
5693 (char *) BricksBitmap,BricksWidth,BricksHeight);
5698 stipple=XCreateBitmapFromData(display,root_window,
5699 (char *) DiagonalBitmap,DiagonalWidth,DiagonalHeight);
5704 stipple=XCreateBitmapFromData(display,root_window,
5705 (char *) ScalesBitmap,ScalesWidth,ScalesHeight);
5710 stipple=XCreateBitmapFromData(display,root_window,
5711 (char *) VerticalBitmap,VerticalWidth,VerticalHeight);
5716 stipple=XCreateBitmapFromData(display,root_window,
5717 (char *) WavyBitmap,WavyWidth,WavyHeight);
5722 stipple=XCreateBitmapFromData(display,root_window,
5723 (char *) HighlightBitmap,HighlightWidth,
5730 stipple=XCreateBitmapFromData(display,root_window,
5731 (char *) OpaqueBitmap,OpaqueWidth,OpaqueHeight);
5737 XFileBrowserWidget(display,windows,"Stipple",filename);
5738 if (*filename == '\0')
5743 XSetCursorState(display,windows,MagickTrue);
5744 XCheckRefreshWindows(display,windows);
5745 image_info=AcquireImageInfo();
5746 (void) CopyMagickString(image_info->filename,filename,
5748 stipple_image=ReadImage(image_info,exception);
5749 CatchException(exception);
5750 XSetCursorState(display,windows,MagickFalse);
5751 if (stipple_image == (Image *) NULL)
5753 (void) AcquireUniqueFileResource(filename);
5754 (void) FormatLocaleString(stipple_image->filename,MaxTextExtent,
5756 (void) WriteImage(image_info,stipple_image,exception);
5757 stipple_image=DestroyImage(stipple_image);
5758 image_info=DestroyImageInfo(image_info);
5759 status=XReadBitmapFile(display,root_window,filename,&width,
5760 &height,&stipple,&x,&y);
5761 (void) RelinquishUniqueFileResource(filename);
5762 if ((status != BitmapSuccess) != 0)
5763 XNoticeWidget(display,windows,"Unable to read X bitmap image:",
5767 case DrawWidthCommand:
5770 width[MaxTextExtent] = "0";
5785 Select a command from the pop-up menu.
5787 entry=XMenuWidget(display,windows,DrawMenu[id],WidthsMenu,
5793 line_width=(unsigned int) StringToUnsignedLong(
5797 (void) XDialogWidget(display,windows,"Ok","Enter line width:",
5801 line_width=(unsigned int) StringToUnsignedLong(width);
5804 case DrawUndoCommand:
5806 (void) XMagickCommand(display,resource_info,windows,UndoCommand,
5810 case DrawHelpCommand:
5812 XTextViewWidget(display,resource_info,windows,MagickFalse,
5813 "Help Viewer - Image Rotation",ImageDrawHelp);
5814 (void) XCheckDefineCursor(display,windows->image.id,cursor);
5817 case DrawDismissCommand:
5829 (void) XCheckDefineCursor(display,windows->image.id,cursor);
5836 if (event.xbutton.button != Button1)
5838 if (event.xbutton.window != windows->image.id)
5857 if (event.xkey.window != windows->image.id)
5860 Respond to a user key press.
5862 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
5863 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
5864 switch ((int) key_symbol)
5879 XTextViewWidget(display,resource_info,windows,MagickFalse,
5880 "Help Viewer - Image Rotation",ImageDrawHelp);
5885 (void) XBell(display,0);
5894 Map and unmap Info widget as text cursor crosses its boundaries.
5898 if (windows->info.mapped != MagickFalse)
5900 if ((x < (int) (windows->info.x+windows->info.width)) &&
5901 (y < (int) (windows->info.y+windows->info.height)))
5902 (void) XWithdrawWindow(display,windows->info.id,
5903 windows->info.screen);
5906 if ((x > (int) (windows->info.x+windows->info.width)) ||
5907 (y > (int) (windows->info.y+windows->info.height)))
5908 (void) XMapWindow(display,windows->info.id);
5912 } while ((state & ExitState) == 0);
5913 (void) XSelectInput(display,windows->image.id,
5914 windows->image.attributes.event_mask);
5915 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
5916 if ((state & EscapeState) != 0)
5919 Draw element as pointer moves until the button is released.
5927 rectangle_info.x=(ssize_t) x;
5928 rectangle_info.y=(ssize_t) y;
5929 rectangle_info.width=0;
5930 rectangle_info.height=0;
5931 number_coordinates=1;
5932 coordinate_info->x=x;
5933 coordinate_info->y=y;
5934 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
5943 if (number_coordinates > 1)
5945 (void) XDrawLines(display,windows->image.id,
5946 windows->image.highlight_context,coordinate_info,
5947 number_coordinates,CoordModeOrigin);
5948 (void) FormatLocaleString(text,MaxTextExtent," %+d%+d",
5949 coordinate_info[number_coordinates-1].x,
5950 coordinate_info[number_coordinates-1].y);
5951 XInfoWidget(display,windows,text);
5960 Display angle of the line.
5962 degrees=RadiansToDegrees(-atan2((double) (line_info.y2-
5963 line_info.y1),(double) (line_info.x2-line_info.x1)));
5964 (void) FormatLocaleString(text,MaxTextExtent," %g",
5966 XInfoWidget(display,windows,text);
5967 XHighlightLine(display,windows->image.id,
5968 windows->image.highlight_context,&line_info);
5971 if (windows->info.mapped != MagickFalse)
5972 (void) XWithdrawWindow(display,windows->info.id,
5973 windows->info.screen);
5976 case RectangleElement:
5977 case FillRectangleElement:
5979 if ((rectangle_info.width > 3) && (rectangle_info.height > 3))
5982 Display info and draw drawing rectangle.
5984 (void) FormatLocaleString(text,MaxTextExtent,
5985 " %.20gx%.20g%+.20g%+.20g",(double) rectangle_info.width,
5986 (double) rectangle_info.height,(double) rectangle_info.x,
5987 (double) rectangle_info.y);
5988 XInfoWidget(display,windows,text);
5989 XHighlightRectangle(display,windows->image.id,
5990 windows->image.highlight_context,&rectangle_info);
5993 if (windows->info.mapped != MagickFalse)
5994 (void) XWithdrawWindow(display,windows->info.id,
5995 windows->info.screen);
5999 case FillCircleElement:
6000 case EllipseElement:
6001 case FillEllipseElement:
6003 if ((rectangle_info.width > 3) && (rectangle_info.height > 3))
6006 Display info and draw drawing rectangle.
6008 (void) FormatLocaleString(text,MaxTextExtent,
6009 " %.20gx%.20g%+.20g%+.20g",(double) rectangle_info.width,
6010 (double) rectangle_info.height,(double) rectangle_info.x,
6011 (double) rectangle_info.y);
6012 XInfoWidget(display,windows,text);
6013 XHighlightEllipse(display,windows->image.id,
6014 windows->image.highlight_context,&rectangle_info);
6017 if (windows->info.mapped != MagickFalse)
6018 (void) XWithdrawWindow(display,windows->info.id,
6019 windows->info.screen);
6022 case PolygonElement:
6023 case FillPolygonElement:
6025 if (number_coordinates > 1)
6026 (void) XDrawLines(display,windows->image.id,
6027 windows->image.highlight_context,coordinate_info,
6028 number_coordinates,CoordModeOrigin);
6032 Display angle of the line.
6034 degrees=RadiansToDegrees(-atan2((double) (line_info.y2-
6035 line_info.y1),(double) (line_info.x2-line_info.x1)));
6036 (void) FormatLocaleString(text,MaxTextExtent," %g",
6038 XInfoWidget(display,windows,text);
6039 XHighlightLine(display,windows->image.id,
6040 windows->image.highlight_context,&line_info);
6043 if (windows->info.mapped != MagickFalse)
6044 (void) XWithdrawWindow(display,windows->info.id,
6045 windows->info.screen);
6050 Wait for next event.
6052 XScreenEvent(display,windows,&event);
6058 if (number_coordinates > 1)
6059 (void) XDrawLines(display,windows->image.id,
6060 windows->image.highlight_context,coordinate_info,
6061 number_coordinates,CoordModeOrigin);
6067 XHighlightLine(display,windows->image.id,
6068 windows->image.highlight_context,&line_info);
6071 case RectangleElement:
6072 case FillRectangleElement:
6074 if ((rectangle_info.width > 3) && (rectangle_info.height > 3))
6075 XHighlightRectangle(display,windows->image.id,
6076 windows->image.highlight_context,&rectangle_info);
6080 case FillCircleElement:
6081 case EllipseElement:
6082 case FillEllipseElement:
6084 if ((rectangle_info.width > 3) && (rectangle_info.height > 3))
6085 XHighlightEllipse(display,windows->image.id,
6086 windows->image.highlight_context,&rectangle_info);
6089 case PolygonElement:
6090 case FillPolygonElement:
6092 if (number_coordinates > 1)
6093 (void) XDrawLines(display,windows->image.id,
6094 windows->image.highlight_context,coordinate_info,
6095 number_coordinates,CoordModeOrigin);
6097 XHighlightLine(display,windows->image.id,
6098 windows->image.highlight_context,&line_info);
6109 User has committed to element.
6111 line_info.x2=event.xbutton.x;
6112 line_info.y2=event.xbutton.y;
6113 rectangle_info.x=(ssize_t) event.xbutton.x;
6114 rectangle_info.y=(ssize_t) event.xbutton.y;
6115 coordinate_info[number_coordinates].x=event.xbutton.x;
6116 coordinate_info[number_coordinates].y=event.xbutton.y;
6117 if (((element != PolygonElement) &&
6118 (element != FillPolygonElement)) || (distance <= 9))
6123 number_coordinates++;
6124 if (number_coordinates < (int) max_coordinates)
6126 line_info.x1=event.xbutton.x;
6127 line_info.y1=event.xbutton.y;
6130 max_coordinates<<=1;
6131 coordinate_info=(XPoint *) ResizeQuantumMemory(coordinate_info,
6132 max_coordinates,sizeof(*coordinate_info));
6133 if (coordinate_info == (XPoint *) NULL)
6134 (void) ThrowMagickException(exception,GetMagickModule(),
6135 ResourceLimitError,"MemoryAllocationFailed","`%s'","...");
6142 if (event.xmotion.window != windows->image.id)
6144 if (element != PointElement)
6146 line_info.x2=event.xmotion.x;
6147 line_info.y2=event.xmotion.y;
6148 rectangle_info.x=(ssize_t) event.xmotion.x;
6149 rectangle_info.y=(ssize_t) event.xmotion.y;
6152 coordinate_info[number_coordinates].x=event.xbutton.x;
6153 coordinate_info[number_coordinates].y=event.xbutton.y;
6154 number_coordinates++;
6155 if (number_coordinates < (int) max_coordinates)
6157 max_coordinates<<=1;
6158 coordinate_info=(XPoint *) ResizeQuantumMemory(coordinate_info,
6159 max_coordinates,sizeof(*coordinate_info));
6160 if (coordinate_info == (XPoint *) NULL)
6161 (void) ThrowMagickException(exception,GetMagickModule(),
6162 ResourceLimitError,"MemoryAllocationFailed","`%s'","...");
6169 Check boundary conditions.
6171 if (line_info.x2 < 0)
6174 if (line_info.x2 > (int) windows->image.width)
6175 line_info.x2=(short) windows->image.width;
6176 if (line_info.y2 < 0)
6179 if (line_info.y2 > (int) windows->image.height)
6180 line_info.y2=(short) windows->image.height;
6181 distance=(unsigned int)
6182 (((line_info.x2-line_info.x1+1)*(line_info.x2-line_info.x1+1))+
6183 ((line_info.y2-line_info.y1+1)*(line_info.y2-line_info.y1+1)));
6184 if ((((int) rectangle_info.x != x) && ((int) rectangle_info.y != y)) ||
6185 ((state & ExitState) != 0))
6187 if (rectangle_info.x < 0)
6190 if (rectangle_info.x > (ssize_t) windows->image.width)
6191 rectangle_info.x=(ssize_t) windows->image.width;
6192 if ((int) rectangle_info.x < x)
6193 rectangle_info.width=(unsigned int) (x-rectangle_info.x);
6196 rectangle_info.width=(unsigned int) (rectangle_info.x-x);
6197 rectangle_info.x=(ssize_t) x;
6199 if (rectangle_info.y < 0)
6202 if (rectangle_info.y > (ssize_t) windows->image.height)
6203 rectangle_info.y=(ssize_t) windows->image.height;
6204 if ((int) rectangle_info.y < y)
6205 rectangle_info.height=(unsigned int) (y-rectangle_info.y);
6208 rectangle_info.height=(unsigned int) (rectangle_info.y-y);
6209 rectangle_info.y=(ssize_t) y;
6212 } while ((state & ExitState) == 0);
6213 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
6214 if ((element == PointElement) || (element == PolygonElement) ||
6215 (element == FillPolygonElement))
6218 Determine polygon bounding box.
6220 rectangle_info.x=(ssize_t) coordinate_info->x;
6221 rectangle_info.y=(ssize_t) coordinate_info->y;
6222 x=coordinate_info->x;
6223 y=coordinate_info->y;
6224 for (i=1; i < number_coordinates; i++)
6226 if (coordinate_info[i].x > x)
6227 x=coordinate_info[i].x;
6228 if (coordinate_info[i].y > y)
6229 y=coordinate_info[i].y;
6230 if ((ssize_t) coordinate_info[i].x < rectangle_info.x)
6231 rectangle_info.x=MagickMax((ssize_t) coordinate_info[i].x,0);
6232 if ((ssize_t) coordinate_info[i].y < rectangle_info.y)
6233 rectangle_info.y=MagickMax((ssize_t) coordinate_info[i].y,0);
6235 rectangle_info.width=(size_t) (x-rectangle_info.x);
6236 rectangle_info.height=(size_t) (y-rectangle_info.y);
6237 for (i=0; i < number_coordinates; i++)
6239 coordinate_info[i].x-=rectangle_info.x;
6240 coordinate_info[i].y-=rectangle_info.y;
6247 if ((element == RectangleElement) ||
6248 (element == CircleElement) || (element == EllipseElement))
6250 rectangle_info.width--;
6251 rectangle_info.height--;
6254 Drawing is relative to image configuration.
6256 draw_info.x=(int) rectangle_info.x;
6257 draw_info.y=(int) rectangle_info.y;
6258 (void) XMagickCommand(display,resource_info,windows,SaveToUndoBufferCommand,
6260 width=(unsigned int) (*image)->columns;
6261 height=(unsigned int) (*image)->rows;
6264 if (windows->image.crop_geometry != (char *) NULL)
6265 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
6266 draw_info.x+=windows->image.x-(line_width/2);
6267 if (draw_info.x < 0)
6269 draw_info.x=(int) (width*draw_info.x/windows->image.ximage->width);
6270 draw_info.y+=windows->image.y-(line_width/2);
6271 if (draw_info.y < 0)
6273 draw_info.y=(int) height*draw_info.y/windows->image.ximage->height;
6274 draw_info.width=(unsigned int) rectangle_info.width+(line_width << 1);
6275 if (draw_info.width > (unsigned int) (*image)->columns)
6276 draw_info.width=(unsigned int) (*image)->columns;
6277 draw_info.height=(unsigned int) rectangle_info.height+(line_width << 1);
6278 if (draw_info.height > (unsigned int) (*image)->rows)
6279 draw_info.height=(unsigned int) (*image)->rows;
6280 (void) FormatLocaleString(draw_info.geometry,MaxTextExtent,"%ux%u%+d%+d",
6281 width*draw_info.width/windows->image.ximage->width,
6282 height*draw_info.height/windows->image.ximage->height,
6283 draw_info.x+x,draw_info.y+y);
6285 Initialize drawing attributes.
6287 draw_info.degrees=0.0;
6288 draw_info.element=element;
6289 draw_info.stipple=stipple;
6290 draw_info.line_width=line_width;
6291 draw_info.line_info=line_info;
6292 if (line_info.x1 > (int) (line_width/2))
6293 draw_info.line_info.x1=(short) line_width/2;
6294 if (line_info.y1 > (int) (line_width/2))
6295 draw_info.line_info.y1=(short) line_width/2;
6296 draw_info.line_info.x2=(short) (line_info.x2-line_info.x1+(line_width/2));
6297 draw_info.line_info.y2=(short) (line_info.y2-line_info.y1+(line_width/2));
6298 if ((draw_info.line_info.x2 < 0) && (draw_info.line_info.y2 < 0))
6300 draw_info.line_info.x2=(-draw_info.line_info.x2);
6301 draw_info.line_info.y2=(-draw_info.line_info.y2);
6303 if (draw_info.line_info.x2 < 0)
6305 draw_info.line_info.x2=(-draw_info.line_info.x2);
6306 Swap(draw_info.line_info.x1,draw_info.line_info.x2);
6308 if (draw_info.line_info.y2 < 0)
6310 draw_info.line_info.y2=(-draw_info.line_info.y2);
6311 Swap(draw_info.line_info.y1,draw_info.line_info.y2);
6313 draw_info.rectangle_info=rectangle_info;
6314 if (draw_info.rectangle_info.x > (ssize_t) (line_width/2))
6315 draw_info.rectangle_info.x=(ssize_t) line_width/2;
6316 if (draw_info.rectangle_info.y > (ssize_t) (line_width/2))
6317 draw_info.rectangle_info.y=(ssize_t) line_width/2;
6318 draw_info.number_coordinates=(unsigned int) number_coordinates;
6319 draw_info.coordinate_info=coordinate_info;
6320 windows->pixel_info->pen_color=windows->pixel_info->pen_colors[pen_id];
6322 Draw element on image.
6324 XSetCursorState(display,windows,MagickTrue);
6325 XCheckRefreshWindows(display,windows);
6326 status=XDrawImage(display,windows->pixel_info,&draw_info,*image);
6327 XSetCursorState(display,windows,MagickFalse);
6329 Update image colormap and return to image drawing.
6331 XConfigureImageColormap(display,resource_info,windows,*image);
6332 (void) XConfigureImage(display,resource_info,windows,*image,exception);
6334 XSetCursorState(display,windows,MagickFalse);
6335 coordinate_info=(XPoint *) RelinquishMagickMemory(coordinate_info);
6336 return(status != 0 ? MagickTrue : MagickFalse);
6340 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6344 + X D r a w P a n R e c t a n g l e %
6348 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6350 % XDrawPanRectangle() draws a rectangle in the pan window. The pan window
6351 % displays a zoom image and the rectangle shows which portion of the image is
6352 % displayed in the Image window.
6354 % The format of the XDrawPanRectangle method is:
6356 % XDrawPanRectangle(Display *display,XWindows *windows)
6358 % A description of each parameter follows:
6360 % o display: Specifies a connection to an X server; returned from
6363 % o windows: Specifies a pointer to a XWindows structure.
6366 static void XDrawPanRectangle(Display *display,XWindows *windows)
6375 Determine dimensions of the panning rectangle.
6377 scale_factor=(MagickRealType) windows->pan.width/windows->image.ximage->width;
6378 highlight_info.x=(ssize_t) (scale_factor*windows->image.x+0.5);
6379 highlight_info.width=(unsigned int) (scale_factor*windows->image.width+0.5);
6380 scale_factor=(MagickRealType)
6381 windows->pan.height/windows->image.ximage->height;
6382 highlight_info.y=(ssize_t) (scale_factor*windows->image.y+0.5);
6383 highlight_info.height=(unsigned int) (scale_factor*windows->image.height+0.5);
6385 Display the panning rectangle.
6387 (void) XClearWindow(display,windows->pan.id);
6388 XHighlightRectangle(display,windows->pan.id,windows->pan.annotate_context,
6393 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6397 + X I m a g e C a c h e %
6401 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6403 % XImageCache() handles the creation, manipulation, and destruction of the
6404 % image cache (undo and redo buffers).
6406 % The format of the XImageCache method is:
6408 % void XImageCache(Display *display,XResourceInfo *resource_info,
6409 % XWindows *windows,const CommandType command,Image **image,
6410 % ExceptionInfo *exception)
6412 % A description of each parameter follows:
6414 % o display: Specifies a connection to an X server; returned from
6417 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
6419 % o windows: Specifies a pointer to a XWindows structure.
6421 % o command: Specifies a command to perform.
6423 % o image: the image; XImageCache may transform the image and return a new
6426 % o exception: return any errors or warnings in this structure.
6429 static void XImageCache(Display *display,XResourceInfo *resource_info,
6430 XWindows *windows,const CommandType command,Image **image,
6431 ExceptionInfo *exception)
6437 *redo_image = (Image *) NULL,
6438 *undo_image = (Image *) NULL;
6442 case FreeBuffersCommand:
6445 Free memory from the undo and redo cache.
6447 while (undo_image != (Image *) NULL)
6449 cache_image=undo_image;
6450 undo_image=GetPreviousImageInList(undo_image);
6451 cache_image->list=DestroyImage(cache_image->list);
6452 cache_image=DestroyImage(cache_image);
6454 undo_image=NewImageList();
6455 if (redo_image != (Image *) NULL)
6456 redo_image=DestroyImage(redo_image);
6457 redo_image=NewImageList();
6463 image_geometry[MaxTextExtent];
6466 Undo the last image transformation.
6468 if (undo_image == (Image *) NULL)
6470 (void) XBell(display,0);
6473 cache_image=undo_image;
6474 undo_image=GetPreviousImageInList(undo_image);
6475 windows->image.window_changes.width=(int) cache_image->columns;
6476 windows->image.window_changes.height=(int) cache_image->rows;
6477 (void) FormatLocaleString(image_geometry,MaxTextExtent,"%dx%d!",
6478 windows->image.ximage->width,windows->image.ximage->height);
6479 (void) TransformImage(image,windows->image.crop_geometry,image_geometry);
6480 if (windows->image.crop_geometry != (char *) NULL)
6481 windows->image.crop_geometry=(char *)
6482 RelinquishMagickMemory(windows->image.crop_geometry);
6483 windows->image.crop_geometry=cache_image->geometry;
6484 if (redo_image != (Image *) NULL)
6485 redo_image=DestroyImage(redo_image);
6486 redo_image=(*image);
6487 *image=cache_image->list;
6488 cache_image=DestroyImage(cache_image);
6489 if (windows->image.orphan != MagickFalse)
6491 XConfigureImageColormap(display,resource_info,windows,*image);
6492 (void) XConfigureImage(display,resource_info,windows,*image,exception);
6498 case HalfSizeCommand:
6499 case OriginalSizeCommand:
6500 case DoubleSizeCommand:
6507 case RotateRightCommand:
6508 case RotateLeftCommand:
6513 case ContrastStretchCommand:
6514 case SigmoidalContrastCommand:
6515 case NormalizeCommand:
6516 case EqualizeCommand:
6518 case SaturationCommand:
6519 case BrightnessCommand:
6523 case GrayscaleCommand:
6525 case QuantizeCommand:
6526 case DespeckleCommand:
6528 case ReduceNoiseCommand:
6529 case AddNoiseCommand:
6530 case SharpenCommand:
6532 case ThresholdCommand:
6533 case EdgeDetectCommand:
6537 case SegmentCommand:
6538 case SolarizeCommand:
6539 case SepiaToneCommand:
6541 case ImplodeCommand:
6542 case VignetteCommand:
6544 case OilPaintCommand:
6545 case CharcoalDrawCommand:
6546 case AnnotateCommand:
6547 case AddBorderCommand:
6548 case AddFrameCommand:
6549 case CompositeCommand:
6550 case CommentCommand:
6552 case RegionofInterestCommand:
6553 case SaveToUndoBufferCommand:
6562 bytes=(ssize_t) ((*image)->columns*(*image)->rows*sizeof(PixelPacket));
6563 if (undo_image != (Image *) NULL)
6566 Ensure the undo cache has enough memory available.
6568 previous_image=undo_image;
6569 while (previous_image != (Image *) NULL)
6571 bytes+=previous_image->list->columns*previous_image->list->rows*
6572 sizeof(PixelPacket);
6573 if (bytes <= (ssize_t) (resource_info->undo_cache << 20))
6575 previous_image=GetPreviousImageInList(previous_image);
6578 bytes-=previous_image->list->columns*previous_image->list->rows*
6579 sizeof(PixelPacket);
6580 if (previous_image == undo_image)
6581 undo_image=NewImageList();
6583 previous_image->next->previous=NewImageList();
6586 while (previous_image != (Image *) NULL)
6589 Delete any excess memory from undo cache.
6591 cache_image=previous_image;
6592 previous_image=GetPreviousImageInList(previous_image);
6593 cache_image->list=DestroyImage(cache_image->list);
6594 cache_image=DestroyImage(cache_image);
6597 if (bytes > (ssize_t) (resource_info->undo_cache << 20))
6600 Save image before transformations are applied.
6602 cache_image=AcquireImage((ImageInfo *) NULL);
6603 if (cache_image == (Image *) NULL)
6605 XSetCursorState(display,windows,MagickTrue);
6606 XCheckRefreshWindows(display,windows);
6607 cache_image->list=CloneImage(*image,0,0,MagickTrue,exception);
6608 XSetCursorState(display,windows,MagickFalse);
6609 if (cache_image->list == (Image *) NULL)
6611 cache_image=DestroyImage(cache_image);
6614 cache_image->columns=(size_t) windows->image.ximage->width;
6615 cache_image->rows=(size_t) windows->image.ximage->height;
6616 cache_image->geometry=windows->image.crop_geometry;
6617 if (windows->image.crop_geometry != (char *) NULL)
6619 cache_image->geometry=AcquireString((char *) NULL);
6620 (void) CopyMagickString(cache_image->geometry,
6621 windows->image.crop_geometry,MaxTextExtent);
6623 if (undo_image == (Image *) NULL)
6625 undo_image=cache_image;
6628 undo_image->next=cache_image;
6629 undo_image->next->previous=undo_image;
6630 undo_image=undo_image->next;
6636 if (command == RedoCommand)
6639 Redo the last image transformation.
6641 if (redo_image == (Image *) NULL)
6643 (void) XBell(display,0);
6646 windows->image.window_changes.width=(int) redo_image->columns;
6647 windows->image.window_changes.height=(int) redo_image->rows;
6648 if (windows->image.crop_geometry != (char *) NULL)
6649 windows->image.crop_geometry=(char *)
6650 RelinquishMagickMemory(windows->image.crop_geometry);
6651 windows->image.crop_geometry=redo_image->geometry;
6652 *image=DestroyImage(*image);
6654 redo_image=NewImageList();
6655 if (windows->image.orphan != MagickFalse)
6657 XConfigureImageColormap(display,resource_info,windows,*image);
6658 (void) XConfigureImage(display,resource_info,windows,*image,exception);
6661 if (command != InfoCommand)
6666 XSetCursorState(display,windows,MagickTrue);
6667 XCheckRefreshWindows(display,windows);
6668 XDisplayImageInfo(display,resource_info,windows,undo_image,*image);
6669 XSetCursorState(display,windows,MagickFalse);
6673 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6677 + X I m a g e W i n d o w C o m m a n d %
6681 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6683 % XImageWindowCommand() makes a transform to the image or Image window as
6684 % specified by a user menu button or keyboard command.
6686 % The format of the XImageWindowCommand method is:
6688 % CommandType XImageWindowCommand(Display *display,
6689 % XResourceInfo *resource_info,XWindows *windows,
6690 % const MagickStatusType state,KeySym key_symbol,Image **image,
6691 % ExceptionInfo *exception)
6693 % A description of each parameter follows:
6695 % o nexus: Method XImageWindowCommand returns an image when the
6696 % user chooses 'Open Image' from the command menu. Otherwise a null
6697 % image is returned.
6699 % o display: Specifies a connection to an X server; returned from
6702 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
6704 % o windows: Specifies a pointer to a XWindows structure.
6706 % o state: key mask.
6708 % o key_symbol: Specifies a command to perform.
6710 % o image: the image; XImageWIndowCommand may transform the image and
6711 % return a new image pointer.
6713 % o exception: return any errors or warnings in this structure.
6716 static CommandType XImageWindowCommand(Display *display,
6717 XResourceInfo *resource_info,XWindows *windows,const MagickStatusType state,
6718 KeySym key_symbol,Image **image,ExceptionInfo *exception)
6721 delta[MaxTextExtent] = "";
6724 Digits[] = "01234567890";
6729 if ((key_symbol >= XK_0) && (key_symbol <= XK_9))
6731 if (((last_symbol < XK_0) || (last_symbol > XK_9)))
6734 resource_info->quantum=1;
6736 last_symbol=key_symbol;
6737 delta[strlen(delta)+1]='\0';
6738 delta[strlen(delta)]=Digits[key_symbol-XK_0];
6739 resource_info->quantum=StringToLong(delta);
6740 return(NullCommand);
6742 last_symbol=key_symbol;
6743 if (resource_info->immutable)
6746 Virtual image window has a restricted command set.
6751 return(InfoCommand);
6754 return(PrintCommand);
6756 return(NextCommand);
6759 return(QuitCommand);
6763 return(NullCommand);
6765 switch ((int) key_symbol)
6769 if ((state & ControlMask) == 0)
6771 return(OpenCommand);
6774 return(NextCommand);
6776 return(FormerCommand);
6779 if ((state & Mod1Mask) != 0)
6780 return(SwirlCommand);
6781 if ((state & ControlMask) == 0)
6782 return(ShearCommand);
6783 return(SaveCommand);
6788 if ((state & Mod1Mask) != 0)
6789 return(OilPaintCommand);
6790 if ((state & Mod4Mask) != 0)
6791 return(ColorCommand);
6792 if ((state & ControlMask) == 0)
6793 return(NullCommand);
6794 return(PrintCommand);
6798 if ((state & Mod4Mask) != 0)
6799 return(DrawCommand);
6800 if ((state & ControlMask) == 0)
6801 return(NullCommand);
6802 return(DeleteCommand);
6806 if ((state & ControlMask) == 0)
6807 return(NullCommand);
6808 return(SelectCommand);
6812 if ((state & ControlMask) == 0)
6813 return(NullCommand);
6818 return(QuitCommand);
6822 if ((state & ControlMask) == 0)
6823 return(NullCommand);
6824 return(UndoCommand);
6829 if ((state & ControlMask) == 0)
6830 return(RollCommand);
6831 return(RedoCommand);
6835 if ((state & ControlMask) == 0)
6836 return(NullCommand);
6841 if ((state & Mod1Mask) != 0)
6842 return(CharcoalDrawCommand);
6843 if ((state & ControlMask) == 0)
6844 return(CropCommand);
6845 return(CopyCommand);
6850 if ((state & Mod4Mask) != 0)
6851 return(CompositeCommand);
6852 if ((state & ControlMask) == 0)
6853 return(FlipCommand);
6854 return(PasteCommand);
6857 return(HalfSizeCommand);
6859 return(OriginalSizeCommand);
6861 return(DoubleSizeCommand);
6863 return(ResizeCommand);
6865 return(RefreshCommand);
6866 case XK_bracketleft:
6867 return(ChopCommand);
6869 return(FlopCommand);
6871 return(RotateRightCommand);
6873 return(RotateLeftCommand);
6875 return(RotateCommand);
6877 return(TrimCommand);
6881 return(SaturationCommand);
6883 return(BrightnessCommand);
6885 return(GammaCommand);
6887 return(SpiffCommand);
6889 return(DullCommand);
6891 return(NormalizeCommand);
6893 return(EqualizeCommand);
6895 return(NegateCommand);
6897 return(GrayscaleCommand);
6899 return(QuantizeCommand);
6901 return(DespeckleCommand);
6903 return(EmbossCommand);
6905 return(ReduceNoiseCommand);
6907 return(AddNoiseCommand);
6909 return(SharpenCommand);
6911 return(BlurCommand);
6913 return(ThresholdCommand);
6915 return(EdgeDetectCommand);
6917 return(SpreadCommand);
6919 return(ShadeCommand);
6921 return(RaiseCommand);
6923 return(SegmentCommand);
6926 if ((state & Mod1Mask) == 0)
6927 return(NullCommand);
6928 return(ImplodeCommand);
6932 if ((state & Mod1Mask) == 0)
6933 return(NullCommand);
6934 return(WaveCommand);
6938 if ((state & Mod4Mask) == 0)
6939 return(NullCommand);
6940 return(MatteCommand);
6944 if ((state & Mod4Mask) == 0)
6945 return(NullCommand);
6946 return(AddBorderCommand);
6950 if ((state & Mod4Mask) == 0)
6951 return(NullCommand);
6952 return(AddFrameCommand);
6956 if ((state & Mod4Mask) == 0)
6957 return(NullCommand);
6958 return(CommentCommand);
6962 if ((state & Mod1Mask) != 0)
6963 return(ApplyCommand);
6964 if ((state & Mod4Mask) != 0)
6965 return(AnnotateCommand);
6966 if ((state & ControlMask) == 0)
6967 return(NullCommand);
6968 return(RegionofInterestCommand);
6971 return(InfoCommand);
6973 return(ZoomCommand);
6976 if ((state & ShiftMask) == 0)
6977 return(NullCommand);
6978 return(ShowPreviewCommand);
6981 return(LaunchCommand);
6983 return(HelpCommand);
6985 return(BrowseDocumentationCommand);
6988 (void) XMapRaised(display,windows->command.id);
6989 return(NullCommand);
6996 XTranslateImage(display,windows,*image,key_symbol);
6997 return(NullCommand);
7008 if ((state & Mod1Mask) != 0)
7014 Trim one pixel from edge of image.
7018 crop_info.width=(size_t) windows->image.ximage->width;
7019 crop_info.height=(size_t) windows->image.ximage->height;
7020 if ((key_symbol == XK_Up) || (key_symbol == XK_KP_Up))
7022 if (resource_info->quantum >= (int) crop_info.height)
7023 resource_info->quantum=(int) crop_info.height-1;
7024 crop_info.height-=resource_info->quantum;
7026 if ((key_symbol == XK_Down) || (key_symbol == XK_KP_Down))
7028 if (resource_info->quantum >= (int) (crop_info.height-crop_info.y))
7029 resource_info->quantum=(int) (crop_info.height-crop_info.y-1);
7030 crop_info.y+=resource_info->quantum;
7031 crop_info.height-=resource_info->quantum;
7033 if ((key_symbol == XK_Left) || (key_symbol == XK_KP_Left))
7035 if (resource_info->quantum >= (int) crop_info.width)
7036 resource_info->quantum=(int) crop_info.width-1;
7037 crop_info.width-=resource_info->quantum;
7039 if ((key_symbol == XK_Right) || (key_symbol == XK_KP_Right))
7041 if (resource_info->quantum >= (int) (crop_info.width-crop_info.x))
7042 resource_info->quantum=(int) (crop_info.width-crop_info.x-1);
7043 crop_info.x+=resource_info->quantum;
7044 crop_info.width-=resource_info->quantum;
7046 if ((int) (windows->image.x+windows->image.width) >
7047 (int) crop_info.width)
7048 windows->image.x=(int) (crop_info.width-windows->image.width);
7049 if ((int) (windows->image.y+windows->image.height) >
7050 (int) crop_info.height)
7051 windows->image.y=(int) (crop_info.height-windows->image.height);
7052 XSetCropGeometry(display,windows,&crop_info,*image);
7053 windows->image.window_changes.width=(int) crop_info.width;
7054 windows->image.window_changes.height=(int) crop_info.height;
7055 (void) XSetWindowBackgroundPixmap(display,windows->image.id,None);
7056 (void) XConfigureImage(display,resource_info,windows,*image,
7058 return(NullCommand);
7060 XTranslateImage(display,windows,*image,key_symbol);
7061 return(NullCommand);
7064 return(NullCommand);
7066 return(NullCommand);
7070 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7074 + X M a g i c k C o m m a n d %
7078 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7080 % XMagickCommand() makes a transform to the image or Image window as
7081 % specified by a user menu button or keyboard command.
7083 % The format of the XMagickCommand method is:
7085 % Image *XMagickCommand(Display *display,XResourceInfo *resource_info,
7086 % XWindows *windows,const CommandType command,Image **image,
7087 % ExceptionInfo *exception)
7089 % A description of each parameter follows:
7091 % o display: Specifies a connection to an X server; returned from
7094 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
7096 % o windows: Specifies a pointer to a XWindows structure.
7098 % o command: Specifies a command to perform.
7100 % o image: the image; XMagickCommand may transform the image and return a
7101 % new image pointer.
7103 % o exception: return any errors or warnings in this structure.
7106 static Image *XMagickCommand(Display *display,XResourceInfo *resource_info,
7107 XWindows *windows,const CommandType command,Image **image,
7108 ExceptionInfo *exception)
7111 filename[MaxTextExtent],
7112 geometry[MaxTextExtent],
7113 modulate_factors[MaxTextExtent];
7142 color[MaxTextExtent] = "gray";
7149 Process user command.
7151 XCheckRefreshWindows(display,windows);
7152 XImageCache(display,resource_info,windows,command,image,exception);
7153 nexus=NewImageList();
7154 windows->image.window_changes.width=windows->image.ximage->width;
7155 windows->image.window_changes.height=windows->image.ximage->height;
7156 image_info=CloneImageInfo(resource_info->image_info);
7157 SetGeometryInfo(&geometry_info);
7158 GetQuantizeInfo(&quantize_info);
7166 nexus=XOpenImage(display,resource_info,windows,MagickFalse);
7174 for (i=0; i < resource_info->quantum; i++)
7175 XClientMessage(display,windows->image.id,windows->im_protocols,
7176 windows->im_next_image,CurrentTime);
7182 Display former image.
7184 for (i=0; i < resource_info->quantum; i++)
7185 XClientMessage(display,windows->image.id,windows->im_protocols,
7186 windows->im_former_image,CurrentTime);
7197 status=chdir(resource_info->home_directory);
7199 (void) ThrowMagickException(exception,GetMagickModule(),FileOpenError,
7200 "UnableToOpenFile","%s",resource_info->home_directory);
7201 nexus=XOpenImage(display,resource_info,windows,MagickTrue);
7209 status=XSaveImage(display,resource_info,windows,*image,exception);
7210 if (status == MagickFalse)
7212 XNoticeWidget(display,windows,"Unable to write X image:",
7213 (*image)->filename);
7223 status=XPrintImage(display,resource_info,windows,*image,exception);
7224 if (status == MagickFalse)
7226 XNoticeWidget(display,windows,"Unable to print X image:",
7227 (*image)->filename);
7235 filename[MaxTextExtent] = "\0";
7240 XFileBrowserWidget(display,windows,"Delete",filename);
7241 if (*filename == '\0')
7243 status=remove(filename) != 0 ? MagickTrue : MagickFalse;
7244 if (status != MagickFalse)
7245 XNoticeWidget(display,windows,"Unable to delete image file:",filename);
7254 color[MaxTextExtent] = "gray",
7255 geometry[MaxTextExtent] = "640x480";
7258 *format = "gradient";
7261 Query user for canvas geometry.
7263 status=XDialogWidget(display,windows,"New","Enter image geometry:",
7265 if (*geometry == '\0')
7269 XColorBrowserWidget(display,windows,"Select",color);
7275 (void) FormatLocaleString(image_info->filename,MaxTextExtent,
7276 "%s:%s",format,color);
7277 (void) CloneString(&image_info->size,geometry);
7278 nexus=ReadImage(image_info,exception);
7279 CatchException(exception);
7280 XClientMessage(display,windows->image.id,windows->im_protocols,
7281 windows->im_next_image,CurrentTime);
7284 case VisualDirectoryCommand:
7287 Visual Image directory.
7289 nexus=XVisualDirectoryImage(display,resource_info,windows,exception);
7297 if (resource_info->confirm_exit == MagickFalse)
7298 XClientMessage(display,windows->image.id,windows->im_protocols,
7299 windows->im_exit,CurrentTime);
7306 Confirm program exit.
7308 status=XConfirmWidget(display,windows,"Do you really want to exit",
7309 resource_info->client_name);
7311 XClientMessage(display,windows->image.id,windows->im_protocols,
7312 windows->im_exit,CurrentTime);
7321 (void) XCropImage(display,resource_info,windows,*image,CutMode,exception);
7329 (void) XCropImage(display,resource_info,windows,*image,CopyMode,
7338 status=XPasteImage(display,resource_info,windows,*image,exception);
7339 if (status == MagickFalse)
7341 XNoticeWidget(display,windows,"Unable to paste X image",
7342 (*image)->filename);
7347 case HalfSizeCommand:
7352 windows->image.window_changes.width=windows->image.ximage->width/2;
7353 windows->image.window_changes.height=windows->image.ximage->height/2;
7354 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7357 case OriginalSizeCommand:
7360 Original image size.
7362 windows->image.window_changes.width=(int) (*image)->columns;
7363 windows->image.window_changes.height=(int) (*image)->rows;
7364 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7367 case DoubleSizeCommand:
7370 Double the image size.
7372 windows->image.window_changes.width=windows->image.ximage->width << 1;
7373 windows->image.window_changes.height=windows->image.ximage->height << 1;
7374 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7393 width=(size_t) windows->image.ximage->width;
7394 height=(size_t) windows->image.ximage->height;
7397 (void) FormatLocaleString(geometry,MaxTextExtent,"%.20gx%.20g+0+0",
7398 (double) width,(double) height);
7399 status=XDialogWidget(display,windows,"Resize",
7400 "Enter resize geometry (e.g. 640x480, 200%):",geometry);
7401 if (*geometry == '\0')
7404 (void) ConcatenateMagickString(geometry,"!",MaxTextExtent);
7405 (void) ParseMetaGeometry(geometry,&x,&y,&width,&height);
7406 windows->image.window_changes.width=(int) width;
7407 windows->image.window_changes.height=(int) height;
7408 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7414 image_geometry[MaxTextExtent];
7416 if ((windows->image.crop_geometry == (char *) NULL) &&
7417 ((int) (*image)->columns == windows->image.ximage->width) &&
7418 ((int) (*image)->rows == windows->image.ximage->height))
7421 Apply size transforms to image.
7423 XSetCursorState(display,windows,MagickTrue);
7424 XCheckRefreshWindows(display,windows);
7426 Crop and/or scale displayed image.
7428 (void) FormatLocaleString(image_geometry,MaxTextExtent,"%dx%d!",
7429 windows->image.ximage->width,windows->image.ximage->height);
7430 (void) TransformImage(image,windows->image.crop_geometry,image_geometry);
7431 if (windows->image.crop_geometry != (char *) NULL)
7432 windows->image.crop_geometry=(char *)
7433 RelinquishMagickMemory(windows->image.crop_geometry);
7436 XConfigureImageColormap(display,resource_info,windows,*image);
7437 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7440 case RefreshCommand:
7442 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7445 case RestoreCommand:
7448 Restore Image window to its original size.
7450 if ((windows->image.width == (unsigned int) (*image)->columns) &&
7451 (windows->image.height == (unsigned int) (*image)->rows) &&
7452 (windows->image.crop_geometry == (char *) NULL))
7454 (void) XBell(display,0);
7457 windows->image.window_changes.width=(int) (*image)->columns;
7458 windows->image.window_changes.height=(int) (*image)->rows;
7459 if (windows->image.crop_geometry != (char *) NULL)
7461 windows->image.crop_geometry=(char *)
7462 RelinquishMagickMemory(windows->image.crop_geometry);
7463 windows->image.crop_geometry=(char *) NULL;
7467 XConfigureImageColormap(display,resource_info,windows,*image);
7468 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7476 (void) XCropImage(display,resource_info,windows,*image,CropMode,
7485 status=XChopImage(display,resource_info,windows,image,exception);
7486 if (status == MagickFalse)
7488 XNoticeWidget(display,windows,"Unable to cut X image",
7489 (*image)->filename);
7500 Flop image scanlines.
7502 XSetCursorState(display,windows,MagickTrue);
7503 XCheckRefreshWindows(display,windows);
7504 flop_image=FlopImage(*image,exception);
7505 if (flop_image != (Image *) NULL)
7507 *image=DestroyImage(*image);
7510 CatchException(exception);
7511 XSetCursorState(display,windows,MagickFalse);
7512 if (windows->image.crop_geometry != (char *) NULL)
7517 width=(unsigned int) (*image)->columns;
7518 height=(unsigned int) (*image)->rows;
7519 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,
7521 (void) FormatLocaleString(windows->image.crop_geometry,MaxTextExtent,
7522 "%ux%u%+d%+d",width,height,(int) (*image)->columns-(int) width-x,y);
7524 if (windows->image.orphan != MagickFalse)
7526 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7535 Flip image scanlines.
7537 XSetCursorState(display,windows,MagickTrue);
7538 XCheckRefreshWindows(display,windows);
7539 flip_image=FlipImage(*image,exception);
7540 if (flip_image != (Image *) NULL)
7542 *image=DestroyImage(*image);
7545 CatchException(exception);
7546 XSetCursorState(display,windows,MagickFalse);
7547 if (windows->image.crop_geometry != (char *) NULL)
7552 width=(unsigned int) (*image)->columns;
7553 height=(unsigned int) (*image)->rows;
7554 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,
7556 (void) FormatLocaleString(windows->image.crop_geometry,MaxTextExtent,
7557 "%ux%u%+d%+d",width,height,x,(int) (*image)->rows-(int) height-y);
7559 if (windows->image.orphan != MagickFalse)
7561 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7564 case RotateRightCommand:
7567 Rotate image 90 degrees clockwise.
7569 status=XRotateImage(display,resource_info,windows,90.0,image,exception);
7570 if (status == MagickFalse)
7572 XNoticeWidget(display,windows,"Unable to rotate X image",
7573 (*image)->filename);
7578 case RotateLeftCommand:
7581 Rotate image 90 degrees counter-clockwise.
7583 status=XRotateImage(display,resource_info,windows,-90.0,image,exception);
7584 if (status == MagickFalse)
7586 XNoticeWidget(display,windows,"Unable to rotate X image",
7587 (*image)->filename);
7597 status=XRotateImage(display,resource_info,windows,0.0,image,exception);
7598 if (status == MagickFalse)
7600 XNoticeWidget(display,windows,"Unable to rotate X image",
7601 (*image)->filename);
7612 geometry[MaxTextExtent] = "45.0x45.0";
7615 Query user for shear color and geometry.
7617 XColorBrowserWidget(display,windows,"Select",color);
7620 (void) XDialogWidget(display,windows,"Shear","Enter shear geometry:",
7622 if (*geometry == '\0')
7627 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image,
7629 XSetCursorState(display,windows,MagickTrue);
7630 XCheckRefreshWindows(display,windows);
7631 (void) QueryColorDatabase(color,&(*image)->background_color,
7633 flags=ParseGeometry(geometry,&geometry_info);
7634 if ((flags & SigmaValue) == 0)
7635 geometry_info.sigma=geometry_info.rho;
7636 shear_image=ShearImage(*image,geometry_info.rho,geometry_info.sigma,
7638 if (shear_image != (Image *) NULL)
7640 *image=DestroyImage(*image);
7643 CatchException(exception);
7644 XSetCursorState(display,windows,MagickFalse);
7645 if (windows->image.orphan != MagickFalse)
7647 windows->image.window_changes.width=(int) (*image)->columns;
7648 windows->image.window_changes.height=(int) (*image)->rows;
7649 XConfigureImageColormap(display,resource_info,windows,*image);
7650 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7659 geometry[MaxTextExtent] = "+2+2";
7662 Query user for the roll geometry.
7664 (void) XDialogWidget(display,windows,"Roll","Enter roll geometry:",
7666 if (*geometry == '\0')
7671 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image,
7673 XSetCursorState(display,windows,MagickTrue);
7674 XCheckRefreshWindows(display,windows);
7675 (void) ParsePageGeometry(*image,geometry,&page_geometry,
7677 roll_image=RollImage(*image,page_geometry.x,page_geometry.y,
7679 if (roll_image != (Image *) NULL)
7681 *image=DestroyImage(*image);
7684 CatchException(exception);
7685 XSetCursorState(display,windows,MagickFalse);
7686 if (windows->image.orphan != MagickFalse)
7688 windows->image.window_changes.width=(int) (*image)->columns;
7689 windows->image.window_changes.height=(int) (*image)->rows;
7690 XConfigureImageColormap(display,resource_info,windows,*image);
7691 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7697 fuzz[MaxTextExtent];
7700 Query user for the fuzz factor.
7702 (void) FormatLocaleString(fuzz,MaxTextExtent,"%g%%",100.0*
7703 (*image)->fuzz/(QuantumRange+1.0));
7704 (void) XDialogWidget(display,windows,"Trim","Enter fuzz factor:",fuzz);
7707 (*image)->fuzz=SiPrefixToDouble(fuzz,(double) QuantumRange+1.0);
7711 status=XTrimImage(display,resource_info,windows,*image,exception);
7712 if (status == MagickFalse)
7714 XNoticeWidget(display,windows,"Unable to trim X image",
7715 (*image)->filename);
7723 hue_percent[MaxTextExtent] = "110";
7726 Query user for percent hue change.
7728 (void) XDialogWidget(display,windows,"Apply",
7729 "Enter percent change in image hue (0-200):",hue_percent);
7730 if (*hue_percent == '\0')
7735 XSetCursorState(display,windows,MagickTrue);
7736 XCheckRefreshWindows(display,windows);
7737 (void) CopyMagickString(modulate_factors,"100.0/100.0/",MaxTextExtent);
7738 (void) ConcatenateMagickString(modulate_factors,hue_percent,
7740 (void) ModulateImage(*image,modulate_factors,exception);
7741 XSetCursorState(display,windows,MagickFalse);
7742 if (windows->image.orphan != MagickFalse)
7744 XConfigureImageColormap(display,resource_info,windows,*image);
7745 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7748 case SaturationCommand:
7751 saturation_percent[MaxTextExtent] = "110";
7754 Query user for percent saturation change.
7756 (void) XDialogWidget(display,windows,"Apply",
7757 "Enter percent change in color saturation (0-200):",saturation_percent);
7758 if (*saturation_percent == '\0')
7761 Vary color saturation.
7763 XSetCursorState(display,windows,MagickTrue);
7764 XCheckRefreshWindows(display,windows);
7765 (void) CopyMagickString(modulate_factors,"100.0/",MaxTextExtent);
7766 (void) ConcatenateMagickString(modulate_factors,saturation_percent,
7768 (void) ModulateImage(*image,modulate_factors,exception);
7769 XSetCursorState(display,windows,MagickFalse);
7770 if (windows->image.orphan != MagickFalse)
7772 XConfigureImageColormap(display,resource_info,windows,*image);
7773 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7776 case BrightnessCommand:
7779 brightness_percent[MaxTextExtent] = "110";
7782 Query user for percent brightness change.
7784 (void) XDialogWidget(display,windows,"Apply",
7785 "Enter percent change in color brightness (0-200):",brightness_percent);
7786 if (*brightness_percent == '\0')
7789 Vary the color brightness.
7791 XSetCursorState(display,windows,MagickTrue);
7792 XCheckRefreshWindows(display,windows);
7793 (void) CopyMagickString(modulate_factors,brightness_percent,
7795 (void) ModulateImage(*image,modulate_factors,exception);
7796 XSetCursorState(display,windows,MagickFalse);
7797 if (windows->image.orphan != MagickFalse)
7799 XConfigureImageColormap(display,resource_info,windows,*image);
7800 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7806 factor[MaxTextExtent] = "1.6";
7809 Query user for gamma value.
7811 (void) XDialogWidget(display,windows,"Gamma",
7812 "Enter gamma value (e.g. 1.2):",factor);
7813 if (*factor == '\0')
7816 Gamma correct image.
7818 XSetCursorState(display,windows,MagickTrue);
7819 XCheckRefreshWindows(display,windows);
7820 (void) GammaImage(*image,atof(factor),exception);
7821 XSetCursorState(display,windows,MagickFalse);
7822 if (windows->image.orphan != MagickFalse)
7824 XConfigureImageColormap(display,resource_info,windows,*image);
7825 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7831 Sharpen the image contrast.
7833 XSetCursorState(display,windows,MagickTrue);
7834 XCheckRefreshWindows(display,windows);
7835 (void) ContrastImage(*image,MagickTrue,exception);
7836 XSetCursorState(display,windows,MagickFalse);
7837 if (windows->image.orphan != MagickFalse)
7839 XConfigureImageColormap(display,resource_info,windows,*image);
7840 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7846 Dull the image contrast.
7848 XSetCursorState(display,windows,MagickTrue);
7849 XCheckRefreshWindows(display,windows);
7850 (void) ContrastImage(*image,MagickFalse,exception);
7851 XSetCursorState(display,windows,MagickFalse);
7852 if (windows->image.orphan != MagickFalse)
7854 XConfigureImageColormap(display,resource_info,windows,*image);
7855 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7858 case ContrastStretchCommand:
7865 levels[MaxTextExtent] = "1%";
7868 Query user for gamma value.
7870 (void) XDialogWidget(display,windows,"Contrast Stretch",
7871 "Enter black and white points:",levels);
7872 if (*levels == '\0')
7875 Contrast stretch image.
7877 XSetCursorState(display,windows,MagickTrue);
7878 XCheckRefreshWindows(display,windows);
7879 flags=ParseGeometry(levels,&geometry_info);
7880 black_point=geometry_info.rho;
7881 white_point=(flags & SigmaValue) != 0 ? geometry_info.sigma : black_point;
7882 if ((flags & PercentValue) != 0)
7884 black_point*=(double) (*image)->columns*(*image)->rows/100.0;
7885 white_point*=(double) (*image)->columns*(*image)->rows/100.0;
7887 white_point=(MagickRealType) (*image)->columns*(*image)->rows-white_point;
7888 (void) ContrastStretchImage(*image,black_point,white_point,
7890 XSetCursorState(display,windows,MagickFalse);
7891 if (windows->image.orphan != MagickFalse)
7893 XConfigureImageColormap(display,resource_info,windows,*image);
7894 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7897 case SigmoidalContrastCommand:
7906 levels[MaxTextExtent] = "3x50%";
7909 Query user for gamma value.
7911 (void) XDialogWidget(display,windows,"Sigmoidal Contrast",
7912 "Enter contrast and midpoint:",levels);
7913 if (*levels == '\0')
7916 Contrast stretch image.
7918 XSetCursorState(display,windows,MagickTrue);
7919 XCheckRefreshWindows(display,windows);
7920 flags=ParseGeometry(levels,&geometry_info);
7921 if ((flags & SigmaValue) == 0)
7922 geometry_info.sigma=1.0*QuantumRange/2.0;
7923 if ((flags & PercentValue) != 0)
7924 geometry_info.sigma=1.0*QuantumRange*geometry_info.sigma/100.0;
7925 (void) SigmoidalContrastImage(*image,MagickTrue,geometry_info.rho,
7926 geometry_info.sigma,exception);
7927 XSetCursorState(display,windows,MagickFalse);
7928 if (windows->image.orphan != MagickFalse)
7930 XConfigureImageColormap(display,resource_info,windows,*image);
7931 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7934 case NormalizeCommand:
7937 Perform histogram normalization on the image.
7939 XSetCursorState(display,windows,MagickTrue);
7940 XCheckRefreshWindows(display,windows);
7941 (void) NormalizeImage(*image,exception);
7942 XSetCursorState(display,windows,MagickFalse);
7943 if (windows->image.orphan != MagickFalse)
7945 XConfigureImageColormap(display,resource_info,windows,*image);
7946 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7949 case EqualizeCommand:
7952 Perform histogram equalization on the image.
7954 XSetCursorState(display,windows,MagickTrue);
7955 XCheckRefreshWindows(display,windows);
7956 (void) EqualizeImage(*image,exception);
7957 XSetCursorState(display,windows,MagickFalse);
7958 if (windows->image.orphan != MagickFalse)
7960 XConfigureImageColormap(display,resource_info,windows,*image);
7961 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7967 Negate colors in image.
7969 XSetCursorState(display,windows,MagickTrue);
7970 XCheckRefreshWindows(display,windows);
7971 (void) NegateImage(*image,MagickFalse,exception);
7972 XSetCursorState(display,windows,MagickFalse);
7973 if (windows->image.orphan != MagickFalse)
7975 XConfigureImageColormap(display,resource_info,windows,*image);
7976 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7979 case GrayscaleCommand:
7982 Convert image to grayscale.
7984 XSetCursorState(display,windows,MagickTrue);
7985 XCheckRefreshWindows(display,windows);
7986 (void) SetImageType(*image,(*image)->matte == MagickFalse ?
7987 GrayscaleType : GrayscaleMatteType,exception);
7988 XSetCursorState(display,windows,MagickFalse);
7989 if (windows->image.orphan != MagickFalse)
7991 XConfigureImageColormap(display,resource_info,windows,*image);
7992 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8001 filename[MaxTextExtent] = "\0";
8004 Request image file name from user.
8006 XFileBrowserWidget(display,windows,"Map",filename);
8007 if (*filename == '\0')
8012 XSetCursorState(display,windows,MagickTrue);
8013 XCheckRefreshWindows(display,windows);
8014 (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
8015 affinity_image=ReadImage(image_info,exception);
8016 if (affinity_image != (Image *) NULL)
8018 (void) RemapImage(&quantize_info,*image,affinity_image,exception);
8019 affinity_image=DestroyImage(affinity_image);
8021 CatchException(exception);
8022 XSetCursorState(display,windows,MagickFalse);
8023 if (windows->image.orphan != MagickFalse)
8025 XConfigureImageColormap(display,resource_info,windows,*image);
8026 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8029 case QuantizeCommand:
8035 colors[MaxTextExtent] = "256";
8038 Query user for maximum number of colors.
8040 status=XDialogWidget(display,windows,"Quantize",
8041 "Maximum number of colors:",colors);
8042 if (*colors == '\0')
8045 Color reduce the image.
8047 XSetCursorState(display,windows,MagickTrue);
8048 XCheckRefreshWindows(display,windows);
8049 quantize_info.number_colors=StringToUnsignedLong(colors);
8050 quantize_info.dither=status != 0 ? MagickTrue : MagickFalse;
8051 (void) QuantizeImage(&quantize_info,*image,exception);
8052 XSetCursorState(display,windows,MagickFalse);
8053 if (windows->image.orphan != MagickFalse)
8055 XConfigureImageColormap(display,resource_info,windows,*image);
8056 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8059 case DespeckleCommand:
8067 XSetCursorState(display,windows,MagickTrue);
8068 XCheckRefreshWindows(display,windows);
8069 despeckle_image=DespeckleImage(*image,exception);
8070 if (despeckle_image != (Image *) NULL)
8072 *image=DestroyImage(*image);
8073 *image=despeckle_image;
8075 CatchException(exception);
8076 XSetCursorState(display,windows,MagickFalse);
8077 if (windows->image.orphan != MagickFalse)
8079 XConfigureImageColormap(display,resource_info,windows,*image);
8080 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8089 radius[MaxTextExtent] = "0.0x1.0";
8092 Query user for emboss radius.
8094 (void) XDialogWidget(display,windows,"Emboss",
8095 "Enter the emboss radius and standard deviation:",radius);
8096 if (*radius == '\0')
8099 Reduce noise in the image.
8101 XSetCursorState(display,windows,MagickTrue);
8102 XCheckRefreshWindows(display,windows);
8103 flags=ParseGeometry(radius,&geometry_info);
8104 if ((flags & SigmaValue) == 0)
8105 geometry_info.sigma=1.0;
8106 emboss_image=EmbossImage(*image,geometry_info.rho,geometry_info.sigma,
8108 if (emboss_image != (Image *) NULL)
8110 *image=DestroyImage(*image);
8111 *image=emboss_image;
8113 CatchException(exception);
8114 XSetCursorState(display,windows,MagickFalse);
8115 if (windows->image.orphan != MagickFalse)
8117 XConfigureImageColormap(display,resource_info,windows,*image);
8118 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8121 case ReduceNoiseCommand:
8127 radius[MaxTextExtent] = "0";
8130 Query user for noise radius.
8132 (void) XDialogWidget(display,windows,"Reduce Noise",
8133 "Enter the noise radius:",radius);
8134 if (*radius == '\0')
8137 Reduce noise in the image.
8139 XSetCursorState(display,windows,MagickTrue);
8140 XCheckRefreshWindows(display,windows);
8141 flags=ParseGeometry(radius,&geometry_info);
8142 noise_image=StatisticImage(*image,NonpeakStatistic,(size_t)
8143 geometry_info.rho,(size_t) geometry_info.rho,exception);
8144 if (noise_image != (Image *) NULL)
8146 *image=DestroyImage(*image);
8149 CatchException(exception);
8150 XSetCursorState(display,windows,MagickFalse);
8151 if (windows->image.orphan != MagickFalse)
8153 XConfigureImageColormap(display,resource_info,windows,*image);
8154 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8157 case AddNoiseCommand:
8166 noise_type[MaxTextExtent] = "Gaussian";
8169 Add noise to the image.
8171 noises=GetCommandOptions(MagickNoiseOptions);
8172 if (noises == (char **) NULL)
8174 XListBrowserWidget(display,windows,&windows->widget,
8175 (const char **) noises,"Add Noise",
8176 "Select a type of noise to add to your image:",noise_type);
8177 noises=DestroyStringList(noises);
8178 if (*noise_type == '\0')
8180 XSetCursorState(display,windows,MagickTrue);
8181 XCheckRefreshWindows(display,windows);
8182 noise_image=AddNoiseImage(*image,(NoiseType) ParseCommandOption(
8183 MagickNoiseOptions,MagickFalse,noise_type),exception);
8184 if (noise_image != (Image *) NULL)
8186 *image=DestroyImage(*image);
8189 CatchException(exception);
8190 XSetCursorState(display,windows,MagickFalse);
8191 if (windows->image.orphan != MagickFalse)
8193 XConfigureImageColormap(display,resource_info,windows,*image);
8194 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8197 case SharpenCommand:
8203 radius[MaxTextExtent] = "0.0x1.0";
8206 Query user for sharpen radius.
8208 (void) XDialogWidget(display,windows,"Sharpen",
8209 "Enter the sharpen radius and standard deviation:",radius);
8210 if (*radius == '\0')
8213 Sharpen image scanlines.
8215 XSetCursorState(display,windows,MagickTrue);
8216 XCheckRefreshWindows(display,windows);
8217 flags=ParseGeometry(radius,&geometry_info);
8218 sharp_image=SharpenImage(*image,geometry_info.rho,geometry_info.sigma,
8219 geometry_info.xi,exception);
8220 if (sharp_image != (Image *) NULL)
8222 *image=DestroyImage(*image);
8225 CatchException(exception);
8226 XSetCursorState(display,windows,MagickFalse);
8227 if (windows->image.orphan != MagickFalse)
8229 XConfigureImageColormap(display,resource_info,windows,*image);
8230 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8239 radius[MaxTextExtent] = "0.0x1.0";
8242 Query user for blur radius.
8244 (void) XDialogWidget(display,windows,"Blur",
8245 "Enter the blur radius and standard deviation:",radius);
8246 if (*radius == '\0')
8251 XSetCursorState(display,windows,MagickTrue);
8252 XCheckRefreshWindows(display,windows);
8253 flags=ParseGeometry(radius,&geometry_info);
8254 blur_image=BlurImage(*image,geometry_info.rho,geometry_info.sigma,
8255 geometry_info.xi,exception);
8256 if (blur_image != (Image *) NULL)
8258 *image=DestroyImage(*image);
8261 CatchException(exception);
8262 XSetCursorState(display,windows,MagickFalse);
8263 if (windows->image.orphan != MagickFalse)
8265 XConfigureImageColormap(display,resource_info,windows,*image);
8266 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8269 case ThresholdCommand:
8275 factor[MaxTextExtent] = "128";
8278 Query user for threshold value.
8280 (void) XDialogWidget(display,windows,"Threshold",
8281 "Enter threshold value:",factor);
8282 if (*factor == '\0')
8285 Gamma correct image.
8287 XSetCursorState(display,windows,MagickTrue);
8288 XCheckRefreshWindows(display,windows);
8289 threshold=SiPrefixToDouble(factor,QuantumRange);
8290 (void) BilevelImage(*image,threshold);
8291 XSetCursorState(display,windows,MagickFalse);
8292 if (windows->image.orphan != MagickFalse)
8294 XConfigureImageColormap(display,resource_info,windows,*image);
8295 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8298 case EdgeDetectCommand:
8304 radius[MaxTextExtent] = "0";
8307 Query user for edge factor.
8309 (void) XDialogWidget(display,windows,"Detect Edges",
8310 "Enter the edge detect radius:",radius);
8311 if (*radius == '\0')
8314 Detect edge in image.
8316 XSetCursorState(display,windows,MagickTrue);
8317 XCheckRefreshWindows(display,windows);
8318 flags=ParseGeometry(radius,&geometry_info);
8319 edge_image=EdgeImage(*image,geometry_info.rho,geometry_info.sigma,
8321 if (edge_image != (Image *) NULL)
8323 *image=DestroyImage(*image);
8326 CatchException(exception);
8327 XSetCursorState(display,windows,MagickFalse);
8328 if (windows->image.orphan != MagickFalse)
8330 XConfigureImageColormap(display,resource_info,windows,*image);
8331 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8340 amount[MaxTextExtent] = "2";
8343 Query user for spread amount.
8345 (void) XDialogWidget(display,windows,"Spread",
8346 "Enter the displacement amount:",amount);
8347 if (*amount == '\0')
8350 Displace image pixels by a random amount.
8352 XSetCursorState(display,windows,MagickTrue);
8353 XCheckRefreshWindows(display,windows);
8354 flags=ParseGeometry(amount,&geometry_info);
8355 spread_image=EdgeImage(*image,geometry_info.rho,geometry_info.sigma,
8357 if (spread_image != (Image *) NULL)
8359 *image=DestroyImage(*image);
8360 *image=spread_image;
8362 CatchException(exception);
8363 XSetCursorState(display,windows,MagickFalse);
8364 if (windows->image.orphan != MagickFalse)
8366 XConfigureImageColormap(display,resource_info,windows,*image);
8367 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8379 geometry[MaxTextExtent] = "30x30";
8382 Query user for the shade geometry.
8384 status=XDialogWidget(display,windows,"Shade",
8385 "Enter the azimuth and elevation of the light source:",geometry);
8386 if (*geometry == '\0')
8391 XSetCursorState(display,windows,MagickTrue);
8392 XCheckRefreshWindows(display,windows);
8393 flags=ParseGeometry(geometry,&geometry_info);
8394 if ((flags & SigmaValue) == 0)
8395 geometry_info.sigma=1.0;
8396 shade_image=ShadeImage(*image,status != 0 ? MagickFalse : MagickTrue,
8397 geometry_info.rho,geometry_info.sigma,exception);
8398 if (shade_image != (Image *) NULL)
8400 *image=DestroyImage(*image);
8403 CatchException(exception);
8404 XSetCursorState(display,windows,MagickFalse);
8405 if (windows->image.orphan != MagickFalse)
8407 XConfigureImageColormap(display,resource_info,windows,*image);
8408 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8414 bevel_width[MaxTextExtent] = "10";
8417 Query user for bevel width.
8419 (void) XDialogWidget(display,windows,"Raise","Bevel width:",bevel_width);
8420 if (*bevel_width == '\0')
8425 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image,
8427 XSetCursorState(display,windows,MagickTrue);
8428 XCheckRefreshWindows(display,windows);
8429 (void) ParsePageGeometry(*image,bevel_width,&page_geometry,
8431 (void) RaiseImage(*image,&page_geometry,MagickTrue,exception);
8432 XSetCursorState(display,windows,MagickFalse);
8433 if (windows->image.orphan != MagickFalse)
8435 XConfigureImageColormap(display,resource_info,windows,*image);
8436 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8439 case SegmentCommand:
8442 threshold[MaxTextExtent] = "1.0x1.5";
8445 Query user for smoothing threshold.
8447 (void) XDialogWidget(display,windows,"Segment","Smooth threshold:",
8449 if (*threshold == '\0')
8454 XSetCursorState(display,windows,MagickTrue);
8455 XCheckRefreshWindows(display,windows);
8456 flags=ParseGeometry(threshold,&geometry_info);
8457 if ((flags & SigmaValue) == 0)
8458 geometry_info.sigma=1.0;
8459 (void) SegmentImage(*image,RGBColorspace,MagickFalse,geometry_info.rho,
8460 geometry_info.sigma,exception);
8461 XSetCursorState(display,windows,MagickFalse);
8462 if (windows->image.orphan != MagickFalse)
8464 XConfigureImageColormap(display,resource_info,windows,*image);
8465 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8468 case SepiaToneCommand:
8477 factor[MaxTextExtent] = "80%";
8480 Query user for sepia-tone factor.
8482 (void) XDialogWidget(display,windows,"Sepia Tone",
8483 "Enter the sepia tone factor (0 - 99.9%):",factor);
8484 if (*factor == '\0')
8487 Sepia tone image pixels.
8489 XSetCursorState(display,windows,MagickTrue);
8490 XCheckRefreshWindows(display,windows);
8491 threshold=SiPrefixToDouble(factor,QuantumRange);
8492 sepia_image=SepiaToneImage(*image,threshold,exception);
8493 if (sepia_image != (Image *) NULL)
8495 *image=DestroyImage(*image);
8498 CatchException(exception);
8499 XSetCursorState(display,windows,MagickFalse);
8500 if (windows->image.orphan != MagickFalse)
8502 XConfigureImageColormap(display,resource_info,windows,*image);
8503 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8506 case SolarizeCommand:
8512 factor[MaxTextExtent] = "60%";
8515 Query user for solarize factor.
8517 (void) XDialogWidget(display,windows,"Solarize",
8518 "Enter the solarize factor (0 - 99.9%):",factor);
8519 if (*factor == '\0')
8522 Solarize image pixels.
8524 XSetCursorState(display,windows,MagickTrue);
8525 XCheckRefreshWindows(display,windows);
8526 threshold=SiPrefixToDouble(factor,QuantumRange);
8527 (void) SolarizeImage(*image,threshold,exception);
8528 XSetCursorState(display,windows,MagickFalse);
8529 if (windows->image.orphan != MagickFalse)
8531 XConfigureImageColormap(display,resource_info,windows,*image);
8532 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8541 degrees[MaxTextExtent] = "60";
8544 Query user for swirl angle.
8546 (void) XDialogWidget(display,windows,"Swirl","Enter the swirl angle:",
8548 if (*degrees == '\0')
8551 Swirl image pixels about the center.
8553 XSetCursorState(display,windows,MagickTrue);
8554 XCheckRefreshWindows(display,windows);
8555 flags=ParseGeometry(degrees,&geometry_info);
8556 swirl_image=SwirlImage(*image,geometry_info.rho,(*image)->interpolate,
8558 if (swirl_image != (Image *) NULL)
8560 *image=DestroyImage(*image);
8563 CatchException(exception);
8564 XSetCursorState(display,windows,MagickFalse);
8565 if (windows->image.orphan != MagickFalse)
8567 XConfigureImageColormap(display,resource_info,windows,*image);
8568 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8571 case ImplodeCommand:
8577 factor[MaxTextExtent] = "0.3";
8580 Query user for implode factor.
8582 (void) XDialogWidget(display,windows,"Implode",
8583 "Enter the implosion/explosion factor (-1.0 - 1.0):",factor);
8584 if (*factor == '\0')
8587 Implode image pixels about the center.
8589 XSetCursorState(display,windows,MagickTrue);
8590 XCheckRefreshWindows(display,windows);
8591 flags=ParseGeometry(factor,&geometry_info);
8592 implode_image=ImplodeImage(*image,geometry_info.rho,(*image)->interpolate,
8594 if (implode_image != (Image *) NULL)
8596 *image=DestroyImage(*image);
8597 *image=implode_image;
8599 CatchException(exception);
8600 XSetCursorState(display,windows,MagickFalse);
8601 if (windows->image.orphan != MagickFalse)
8603 XConfigureImageColormap(display,resource_info,windows,*image);
8604 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8607 case VignetteCommand:
8613 geometry[MaxTextExtent] = "0x20";
8616 Query user for the vignette geometry.
8618 (void) XDialogWidget(display,windows,"Vignette",
8619 "Enter the radius, sigma, and x and y offsets:",geometry);
8620 if (*geometry == '\0')
8623 Soften the edges of the image in vignette style
8625 XSetCursorState(display,windows,MagickTrue);
8626 XCheckRefreshWindows(display,windows);
8627 flags=ParseGeometry(geometry,&geometry_info);
8628 if ((flags & SigmaValue) == 0)
8629 geometry_info.sigma=1.0;
8630 if ((flags & XiValue) == 0)
8631 geometry_info.xi=0.1*(*image)->columns;
8632 if ((flags & PsiValue) == 0)
8633 geometry_info.psi=0.1*(*image)->rows;
8634 vignette_image=VignetteImage(*image,geometry_info.rho,geometry_info.sigma,
8635 (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t) ceil(geometry_info.psi-
8637 if (vignette_image != (Image *) NULL)
8639 *image=DestroyImage(*image);
8640 *image=vignette_image;
8642 CatchException(exception);
8643 XSetCursorState(display,windows,MagickFalse);
8644 if (windows->image.orphan != MagickFalse)
8646 XConfigureImageColormap(display,resource_info,windows,*image);
8647 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8656 geometry[MaxTextExtent] = "25x150";
8659 Query user for the wave geometry.
8661 (void) XDialogWidget(display,windows,"Wave",
8662 "Enter the amplitude and length of the wave:",geometry);
8663 if (*geometry == '\0')
8666 Alter an image along a sine wave.
8668 XSetCursorState(display,windows,MagickTrue);
8669 XCheckRefreshWindows(display,windows);
8670 flags=ParseGeometry(geometry,&geometry_info);
8671 if ((flags & SigmaValue) == 0)
8672 geometry_info.sigma=1.0;
8673 wave_image=WaveImage(*image,geometry_info.rho,geometry_info.sigma,
8674 (*image)->interpolate,exception);
8675 if (wave_image != (Image *) NULL)
8677 *image=DestroyImage(*image);
8680 CatchException(exception);
8681 XSetCursorState(display,windows,MagickFalse);
8682 if (windows->image.orphan != MagickFalse)
8684 XConfigureImageColormap(display,resource_info,windows,*image);
8685 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8688 case OilPaintCommand:
8694 radius[MaxTextExtent] = "0";
8697 Query user for circular neighborhood radius.
8699 (void) XDialogWidget(display,windows,"Oil Paint",
8700 "Enter the mask radius:",radius);
8701 if (*radius == '\0')
8704 OilPaint image scanlines.
8706 XSetCursorState(display,windows,MagickTrue);
8707 XCheckRefreshWindows(display,windows);
8708 flags=ParseGeometry(radius,&geometry_info);
8709 paint_image=OilPaintImage(*image,geometry_info.rho,geometry_info.sigma,
8711 if (paint_image != (Image *) NULL)
8713 *image=DestroyImage(*image);
8716 CatchException(exception);
8717 XSetCursorState(display,windows,MagickFalse);
8718 if (windows->image.orphan != MagickFalse)
8720 XConfigureImageColormap(display,resource_info,windows,*image);
8721 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8724 case CharcoalDrawCommand:
8730 radius[MaxTextExtent] = "0x1";
8733 Query user for charcoal radius.
8735 (void) XDialogWidget(display,windows,"Charcoal Draw",
8736 "Enter the charcoal radius and sigma:",radius);
8737 if (*radius == '\0')
8742 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image,
8744 XSetCursorState(display,windows,MagickTrue);
8745 XCheckRefreshWindows(display,windows);
8746 flags=ParseGeometry(radius,&geometry_info);
8747 if ((flags & SigmaValue) == 0)
8748 geometry_info.sigma=geometry_info.rho;
8749 charcoal_image=CharcoalImage(*image,geometry_info.rho,geometry_info.sigma,
8750 geometry_info.xi,exception);
8751 if (charcoal_image != (Image *) NULL)
8753 *image=DestroyImage(*image);
8754 *image=charcoal_image;
8756 CatchException(exception);
8757 XSetCursorState(display,windows,MagickFalse);
8758 if (windows->image.orphan != MagickFalse)
8760 XConfigureImageColormap(display,resource_info,windows,*image);
8761 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8764 case AnnotateCommand:
8767 Annotate the image with text.
8769 status=XAnnotateEditImage(display,resource_info,windows,*image,exception);
8770 if (status == MagickFalse)
8772 XNoticeWidget(display,windows,"Unable to annotate X image",
8773 (*image)->filename);
8783 status=XDrawEditImage(display,resource_info,windows,image,exception);
8784 if (status == MagickFalse)
8786 XNoticeWidget(display,windows,"Unable to draw on the X image",
8787 (*image)->filename);
8797 status=XColorEditImage(display,resource_info,windows,image,exception);
8798 if (status == MagickFalse)
8800 XNoticeWidget(display,windows,"Unable to pixel edit X image",
8801 (*image)->filename);
8811 status=XMatteEditImage(display,resource_info,windows,image,exception);
8812 if (status == MagickFalse)
8814 XNoticeWidget(display,windows,"Unable to matte edit X image",
8815 (*image)->filename);
8820 case CompositeCommand:
8825 status=XCompositeImage(display,resource_info,windows,*image,
8827 if (status == MagickFalse)
8829 XNoticeWidget(display,windows,"Unable to composite X image",
8830 (*image)->filename);
8835 case AddBorderCommand:
8841 geometry[MaxTextExtent] = "6x6";
8844 Query user for border color and geometry.
8846 XColorBrowserWidget(display,windows,"Select",color);
8849 (void) XDialogWidget(display,windows,"Add Border",
8850 "Enter border geometry:",geometry);
8851 if (*geometry == '\0')
8854 Add a border to the image.
8856 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image,
8858 XSetCursorState(display,windows,MagickTrue);
8859 XCheckRefreshWindows(display,windows);
8860 (void) QueryColorDatabase(color,&(*image)->border_color,
8862 (void) ParsePageGeometry(*image,geometry,&page_geometry,
8864 border_image=BorderImage(*image,&page_geometry,(*image)->compose,
8866 if (border_image != (Image *) NULL)
8868 *image=DestroyImage(*image);
8869 *image=border_image;
8871 CatchException(exception);
8872 XSetCursorState(display,windows,MagickFalse);
8873 if (windows->image.orphan != MagickFalse)
8875 windows->image.window_changes.width=(int) (*image)->columns;
8876 windows->image.window_changes.height=(int) (*image)->rows;
8877 XConfigureImageColormap(display,resource_info,windows,*image);
8878 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8881 case AddFrameCommand:
8890 geometry[MaxTextExtent] = "6x6";
8893 Query user for frame color and geometry.
8895 XColorBrowserWidget(display,windows,"Select",color);
8898 (void) XDialogWidget(display,windows,"Add Frame","Enter frame geometry:",
8900 if (*geometry == '\0')
8903 Surround image with an ornamental border.
8905 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image,
8907 XSetCursorState(display,windows,MagickTrue);
8908 XCheckRefreshWindows(display,windows);
8909 (void) QueryColorDatabase(color,&(*image)->matte_color,
8911 (void) ParsePageGeometry(*image,geometry,&page_geometry,
8913 frame_info.width=page_geometry.width;
8914 frame_info.height=page_geometry.height;
8915 frame_info.outer_bevel=page_geometry.x;
8916 frame_info.inner_bevel=page_geometry.y;
8917 frame_info.x=(ssize_t) frame_info.width;
8918 frame_info.y=(ssize_t) frame_info.height;
8919 frame_info.width=(*image)->columns+2*frame_info.width;
8920 frame_info.height=(*image)->rows+2*frame_info.height;
8921 frame_image=FrameImage(*image,&frame_info,(*image)->compose,exception);
8922 if (frame_image != (Image *) NULL)
8924 *image=DestroyImage(*image);
8927 CatchException(exception);
8928 XSetCursorState(display,windows,MagickFalse);
8929 if (windows->image.orphan != MagickFalse)
8931 windows->image.window_changes.width=(int) (*image)->columns;
8932 windows->image.window_changes.height=(int) (*image)->rows;
8933 XConfigureImageColormap(display,resource_info,windows,*image);
8934 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8937 case CommentCommand:
8951 unique_file=AcquireUniqueFileResource(image_info->filename);
8952 if (unique_file == -1)
8953 XNoticeWidget(display,windows,"Unable to edit image comment",
8954 image_info->filename);
8955 value=GetImageProperty(*image,"comment");
8956 if (value == (char *) NULL)
8957 unique_file=close(unique_file)-1;
8963 file=fdopen(unique_file,"w");
8964 if (file == (FILE *) NULL)
8966 XNoticeWidget(display,windows,"Unable to edit image comment",
8967 image_info->filename);
8970 for (p=value; *p != '\0'; p++)
8971 (void) fputc((int) *p,file);
8972 (void) fputc('\n',file);
8973 (void) fclose(file);
8975 XSetCursorState(display,windows,MagickTrue);
8976 XCheckRefreshWindows(display,windows);
8977 status=InvokeDelegate(image_info,*image,"edit",(char *) NULL,
8979 if (status == MagickFalse)
8980 XNoticeWidget(display,windows,"Unable to edit image comment",
8987 comment=FileToString(image_info->filename,~0UL,exception);
8988 if (comment != (char *) NULL)
8990 (void) SetImageProperty(*image,"comment",comment);
8991 (*image)->taint=MagickTrue;
8994 (void) RelinquishUniqueFileResource(image_info->filename);
8995 XSetCursorState(display,windows,MagickFalse);
9003 XSetCursorState(display,windows,MagickTrue);
9004 XCheckRefreshWindows(display,windows);
9005 (void) AcquireUniqueFilename(filename);
9006 (void) FormatLocaleString((*image)->filename,MaxTextExtent,"launch:%s",
9008 status=WriteImage(image_info,*image,exception);
9009 if (status == MagickFalse)
9010 XNoticeWidget(display,windows,"Unable to launch image editor",
9014 nexus=ReadImage(resource_info->image_info,exception);
9015 CatchException(exception);
9016 XClientMessage(display,windows->image.id,windows->im_protocols,
9017 windows->im_next_image,CurrentTime);
9019 (void) RelinquishUniqueFileResource(filename);
9020 XSetCursorState(display,windows,MagickFalse);
9023 case RegionofInterestCommand:
9026 Apply an image processing technique to a region of interest.
9028 (void) XROIImage(display,resource_info,windows,image,exception);
9038 if (windows->magnify.mapped != MagickFalse)
9039 (void) XRaiseWindow(display,windows->magnify.id);
9045 XSetCursorState(display,windows,MagickTrue);
9046 (void) XMapRaised(display,windows->magnify.id);
9047 XSetCursorState(display,windows,MagickFalse);
9051 case ShowPreviewCommand:
9060 preview_type[MaxTextExtent] = "Gamma";
9063 Select preview type from menu.
9065 previews=GetCommandOptions(MagickPreviewOptions);
9066 if (previews == (char **) NULL)
9068 XListBrowserWidget(display,windows,&windows->widget,
9069 (const char **) previews,"Preview",
9070 "Select an enhancement, effect, or F/X:",preview_type);
9071 previews=DestroyStringList(previews);
9072 if (*preview_type == '\0')
9077 XSetCursorState(display,windows,MagickTrue);
9078 XCheckRefreshWindows(display,windows);
9079 image_info->preview_type=(PreviewType)
9080 ParseCommandOption(MagickPreviewOptions,MagickFalse,preview_type);
9081 image_info->group=(ssize_t) windows->image.id;
9082 (void) DeleteImageProperty(*image,"label");
9083 (void) SetImageProperty(*image,"label","Preview");
9084 (void) AcquireUniqueFilename(filename);
9085 (void) FormatLocaleString((*image)->filename,MaxTextExtent,"preview:%s",
9087 status=WriteImage(image_info,*image,exception);
9088 (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
9089 preview_image=ReadImage(image_info,exception);
9090 (void) RelinquishUniqueFileResource(filename);
9091 if (preview_image == (Image *) NULL)
9093 (void) FormatLocaleString(preview_image->filename,MaxTextExtent,"show:%s",
9095 status=WriteImage(image_info,preview_image,exception);
9096 preview_image=DestroyImage(preview_image);
9097 if (status == MagickFalse)
9098 XNoticeWidget(display,windows,"Unable to show image preview",
9099 (*image)->filename);
9100 XDelay(display,1500);
9101 XSetCursorState(display,windows,MagickFalse);
9104 case ShowHistogramCommand:
9110 Show image histogram.
9112 XSetCursorState(display,windows,MagickTrue);
9113 XCheckRefreshWindows(display,windows);
9114 image_info->group=(ssize_t) windows->image.id;
9115 (void) DeleteImageProperty(*image,"label");
9116 (void) SetImageProperty(*image,"label","Histogram");
9117 (void) AcquireUniqueFilename(filename);
9118 (void) FormatLocaleString((*image)->filename,MaxTextExtent,"histogram:%s",
9120 status=WriteImage(image_info,*image,exception);
9121 (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
9122 histogram_image=ReadImage(image_info,exception);
9123 (void) RelinquishUniqueFileResource(filename);
9124 if (histogram_image == (Image *) NULL)
9126 (void) FormatLocaleString(histogram_image->filename,MaxTextExtent,
9127 "show:%s",filename);
9128 status=WriteImage(image_info,histogram_image,exception);
9129 histogram_image=DestroyImage(histogram_image);
9130 if (status == MagickFalse)
9131 XNoticeWidget(display,windows,"Unable to show histogram",
9132 (*image)->filename);
9133 XDelay(display,1500);
9134 XSetCursorState(display,windows,MagickFalse);
9137 case ShowMatteCommand:
9142 if ((*image)->matte == MagickFalse)
9144 XNoticeWidget(display,windows,
9145 "Image does not have any matte information",(*image)->filename);
9151 XSetCursorState(display,windows,MagickTrue);
9152 XCheckRefreshWindows(display,windows);
9153 image_info->group=(ssize_t) windows->image.id;
9154 (void) DeleteImageProperty(*image,"label");
9155 (void) SetImageProperty(*image,"label","Matte");
9156 (void) AcquireUniqueFilename(filename);
9157 (void) FormatLocaleString((*image)->filename,MaxTextExtent,"matte:%s",
9159 status=WriteImage(image_info,*image,exception);
9160 (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
9161 matte_image=ReadImage(image_info,exception);
9162 (void) RelinquishUniqueFileResource(filename);
9163 if (matte_image == (Image *) NULL)
9165 (void) FormatLocaleString(matte_image->filename,MaxTextExtent,"show:%s",
9167 status=WriteImage(image_info,matte_image,exception);
9168 matte_image=DestroyImage(matte_image);
9169 if (status == MagickFalse)
9170 XNoticeWidget(display,windows,"Unable to show matte",
9171 (*image)->filename);
9172 XDelay(display,1500);
9173 XSetCursorState(display,windows,MagickFalse);
9176 case BackgroundCommand:
9181 status=XBackgroundImage(display,resource_info,windows,image,exception);
9182 if (status == MagickFalse)
9184 nexus=CloneImage(*image,0,0,MagickTrue,exception);
9185 if (nexus != (Image *) NULL)
9186 XClientMessage(display,windows->image.id,windows->im_protocols,
9187 windows->im_next_image,CurrentTime);
9190 case SlideShowCommand:
9193 delay[MaxTextExtent] = "5";
9196 Display next image after pausing.
9198 (void) XDialogWidget(display,windows,"Slide Show",
9199 "Pause how many 1/100ths of a second between images:",delay);
9202 resource_info->delay=StringToUnsignedLong(delay);
9203 XClientMessage(display,windows->image.id,windows->im_protocols,
9204 windows->im_next_image,CurrentTime);
9207 case PreferencesCommand:
9210 Set user preferences.
9212 status=XPreferencesWidget(display,resource_info,windows);
9213 if (status == MagickFalse)
9215 nexus=CloneImage(*image,0,0,MagickTrue,exception);
9216 if (nexus != (Image *) NULL)
9217 XClientMessage(display,windows->image.id,windows->im_protocols,
9218 windows->im_next_image,CurrentTime);
9224 User requested help.
9226 XTextViewWidget(display,resource_info,windows,MagickFalse,
9227 "Help Viewer - Display",DisplayHelp);
9230 case BrowseDocumentationCommand:
9240 Browse the ImageMagick documentation.
9242 root_window=XRootWindow(display,XDefaultScreen(display));
9243 mozilla_atom=XInternAtom(display,"_MOZILLA_VERSION",MagickFalse);
9244 mozilla_window=XWindowByProperty(display,root_window,mozilla_atom);
9245 if (mozilla_window != (Window) NULL)
9248 command[MaxTextExtent],
9252 Display documentation using Netscape remote control.
9254 url=GetMagickHomeURL();
9255 (void) FormatLocaleString(command,MaxTextExtent,
9256 "openurl(%s,new-tab)",url);
9257 url=DestroyString(url);
9258 mozilla_atom=XInternAtom(display,"_MOZILLA_COMMAND",MagickFalse);
9259 (void) XChangeProperty(display,mozilla_window,mozilla_atom,XA_STRING,
9260 8,PropModeReplace,(unsigned char *) command,(int) strlen(command));
9261 XSetCursorState(display,windows,MagickFalse);
9264 XSetCursorState(display,windows,MagickTrue);
9265 XCheckRefreshWindows(display,windows);
9266 status=InvokeDelegate(image_info,*image,"browse",(char *) NULL,
9268 if (status == MagickFalse)
9269 XNoticeWidget(display,windows,"Unable to browse documentation",
9271 XDelay(display,1500);
9272 XSetCursorState(display,windows,MagickFalse);
9275 case VersionCommand:
9277 XNoticeWidget(display,windows,GetMagickVersion((size_t *) NULL),
9278 GetMagickCopyright());
9281 case SaveToUndoBufferCommand:
9285 (void) XBell(display,0);
9289 image_info=DestroyImageInfo(image_info);
9294 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9298 + X M a g n i f y I m a g e %
9302 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9304 % XMagnifyImage() magnifies portions of the image as indicated by the pointer.
9305 % The magnified portion is displayed in a separate window.
9307 % The format of the XMagnifyImage method is:
9309 % void XMagnifyImage(Display *display,XWindows *windows,XEvent *event)
9311 % A description of each parameter follows:
9313 % o display: Specifies a connection to an X server; returned from
9316 % o windows: Specifies a pointer to a XWindows structure.
9318 % o event: Specifies a pointer to a XEvent structure. If it is NULL,
9319 % the entire image is refreshed.
9322 static void XMagnifyImage(Display *display,XWindows *windows,XEvent *event)
9325 text[MaxTextExtent];
9335 Update magnified image until the mouse button is released.
9337 (void) XCheckDefineCursor(display,windows->image.id,windows->magnify.cursor);
9341 windows->magnify.x=(int) windows->image.x+x;
9342 windows->magnify.y=(int) windows->image.y+y;
9346 Map and unmap Info widget as text cursor crosses its boundaries.
9348 if (windows->info.mapped != MagickFalse)
9350 if ((x < (int) (windows->info.x+windows->info.width)) &&
9351 (y < (int) (windows->info.y+windows->info.height)))
9352 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
9355 if ((x > (int) (windows->info.x+windows->info.width)) ||
9356 (y > (int) (windows->info.y+windows->info.height)))
9357 (void) XMapWindow(display,windows->info.id);
9358 if (windows->info.mapped != MagickFalse)
9361 Display pointer position.
9363 (void) FormatLocaleString(text,MaxTextExtent," %+d%+d ",
9364 windows->magnify.x,windows->magnify.y);
9365 XInfoWidget(display,windows,text);
9368 Wait for next event.
9370 XScreenEvent(display,windows,event);
9371 switch (event->type)
9378 User has finished magnifying image.
9397 Check boundary conditions.
9402 if (x >= (int) windows->image.width)
9403 x=(int) windows->image.width-1;
9407 if (y >= (int) windows->image.height)
9408 y=(int) windows->image.height-1;
9409 } while ((state & ExitState) == 0);
9411 Display magnified image.
9413 XSetCursorState(display,windows,MagickFalse);
9417 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9421 + X M a g n i f y W i n d o w C o m m a n d %
9425 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9427 % XMagnifyWindowCommand() moves the image within an Magnify window by one
9428 % pixel as specified by the key symbol.
9430 % The format of the XMagnifyWindowCommand method is:
9432 % void XMagnifyWindowCommand(Display *display,XWindows *windows,
9433 % const MagickStatusType state,const KeySym key_symbol)
9435 % A description of each parameter follows:
9437 % o display: Specifies a connection to an X server; returned from
9440 % o windows: Specifies a pointer to a XWindows structure.
9442 % o state: key mask.
9444 % o key_symbol: Specifies a KeySym which indicates which side of the image
9448 static void XMagnifyWindowCommand(Display *display,XWindows *windows,
9449 const MagickStatusType state,const KeySym key_symbol)
9455 User specified a magnify factor or position.
9458 if ((state & Mod1Mask) != 0)
9460 switch ((int) key_symbol)
9464 (void) XWithdrawWindow(display,windows->magnify.id,
9465 windows->magnify.screen);
9471 windows->magnify.x=(int) windows->image.width/2;
9472 windows->magnify.y=(int) windows->image.height/2;
9478 if (windows->magnify.x > 0)
9479 windows->magnify.x-=quantum;
9485 if (windows->magnify.y > 0)
9486 windows->magnify.y-=quantum;
9492 if (windows->magnify.x < (int) (windows->image.ximage->width-1))
9493 windows->magnify.x+=quantum;
9499 if (windows->magnify.y < (int) (windows->image.ximage->height-1))
9500 windows->magnify.y+=quantum;
9514 windows->magnify.data=(key_symbol-XK_0);
9528 windows->magnify.data=(key_symbol-XK_KP_0);
9534 XMakeMagnifyImage(display,windows);
9538 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9542 + X M a k e P a n I m a g e %
9546 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9548 % XMakePanImage() creates a thumbnail of the image and displays it in the Pan
9551 % The format of the XMakePanImage method is:
9553 % void XMakePanImage(Display *display,XResourceInfo *resource_info,
9554 % XWindows *windows,Image *image,ExceptionInfo *exception)
9556 % A description of each parameter follows:
9558 % o display: Specifies a connection to an X server; returned from
9561 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
9563 % o windows: Specifies a pointer to a XWindows structure.
9565 % o image: the image.
9567 % o exception: return any errors or warnings in this structure.
9570 static void XMakePanImage(Display *display,XResourceInfo *resource_info,
9571 XWindows *windows,Image *image,ExceptionInfo *exception)
9577 Create and display image for panning icon.
9579 XSetCursorState(display,windows,MagickTrue);
9580 XCheckRefreshWindows(display,windows);
9581 windows->pan.x=(int) windows->image.x;
9582 windows->pan.y=(int) windows->image.y;
9583 status=XMakeImage(display,resource_info,&windows->pan,image,
9584 windows->pan.width,windows->pan.height,exception);
9585 if (status == MagickFalse)
9586 ThrowXWindowFatalException(ResourceLimitError,
9587 "MemoryAllocationFailed",image->filename);
9588 (void) XSetWindowBackgroundPixmap(display,windows->pan.id,
9589 windows->pan.pixmap);
9590 (void) XClearWindow(display,windows->pan.id);
9591 XDrawPanRectangle(display,windows);
9592 XSetCursorState(display,windows,MagickFalse);
9596 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9600 + X M a t t a E d i t I m a g e %
9604 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9606 % XMatteEditImage() allows the user to interactively change the Matte channel
9607 % of an image. If the image is PseudoClass it is promoted to DirectClass
9608 % before the matte information is stored.
9610 % The format of the XMatteEditImage method is:
9612 % MagickBooleanType XMatteEditImage(Display *display,
9613 % XResourceInfo *resource_info,XWindows *windows,Image **image,
9614 % ExceptionInfo *exception)
9616 % A description of each parameter follows:
9618 % o display: Specifies a connection to an X server; returned from
9621 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
9623 % o windows: Specifies a pointer to a XWindows structure.
9625 % o image: the image; returned from ReadImage.
9627 % o exception: return any errors or warnings in this structure.
9630 static MagickBooleanType XMatteEditImage(Display *display,
9631 XResourceInfo *resource_info,XWindows *windows,Image **image,
9632 ExceptionInfo *exception)
9635 matte[MaxTextExtent] = "0";
9650 static const ModeType
9651 MatteEditCommands[] =
9654 MatteEditBorderCommand,
9655 MatteEditFuzzCommand,
9656 MatteEditValueCommand,
9657 MatteEditUndoCommand,
9658 MatteEditHelpCommand,
9659 MatteEditDismissCommand
9663 method = PointMethod;
9666 border_color = { 0, 0, 0, 0, 0, 0 };
9669 command[MaxTextExtent],
9670 text[MaxTextExtent];
9702 (void) CloneString(&windows->command.name,"Matte Edit");
9703 windows->command.data=4;
9704 (void) XCommandWidget(display,windows,MatteEditMenu,(XEvent *) NULL);
9705 (void) XMapRaised(display,windows->command.id);
9706 XClientMessage(display,windows->image.id,windows->im_protocols,
9707 windows->im_update_widget,CurrentTime);
9711 cursor=XMakeCursor(display,windows->image.id,windows->map_info->colormap,
9712 resource_info->background_color,resource_info->foreground_color);
9713 (void) XCheckDefineCursor(display,windows->image.id,cursor);
9715 Track pointer until button 1 is pressed.
9717 XQueryPosition(display,windows->image.id,&x,&y);
9718 (void) XSelectInput(display,windows->image.id,
9719 windows->image.attributes.event_mask | PointerMotionMask);
9723 if (windows->info.mapped != MagickFalse)
9726 Display pointer position.
9728 (void) FormatLocaleString(text,MaxTextExtent," %+d%+d ",
9729 x+windows->image.x,y+windows->image.y);
9730 XInfoWidget(display,windows,text);
9733 Wait for next event.
9735 XScreenEvent(display,windows,&event);
9736 if (event.xany.window == windows->command.id)
9739 Select a command from the Command widget.
9741 id=XCommandWidget(display,windows,MatteEditMenu,&event);
9744 (void) XCheckDefineCursor(display,windows->image.id,cursor);
9747 switch (MatteEditCommands[id])
9749 case MatteEditMethod:
9755 Select a method from the pop-up menu.
9757 methods=GetCommandOptions(MagickMethodOptions);
9758 if (methods == (char **) NULL)
9760 entry=XMenuWidget(display,windows,MatteEditMenu[id],
9761 (const char **) methods,command);
9763 method=(PaintMethod) ParseCommandOption(MagickMethodOptions,
9764 MagickFalse,methods[entry]);
9765 methods=DestroyStringList(methods);
9768 case MatteEditBorderCommand:
9771 *ColorMenu[MaxNumberPens];
9777 Initialize menu selections.
9779 for (i=0; i < (int) (MaxNumberPens-2); i++)
9780 ColorMenu[i]=resource_info->pen_colors[i];
9781 ColorMenu[MaxNumberPens-2]="Browser...";
9782 ColorMenu[MaxNumberPens-1]=(const char *) NULL;
9784 Select a pen color from the pop-up menu.
9786 pen_number=XMenuWidget(display,windows,MatteEditMenu[id],
9787 (const char **) ColorMenu,command);
9790 if (pen_number == (MaxNumberPens-2))
9793 color_name[MaxTextExtent] = "gray";
9796 Select a pen color from a dialog.
9798 resource_info->pen_colors[pen_number]=color_name;
9799 XColorBrowserWidget(display,windows,"Select",color_name);
9800 if (*color_name == '\0')
9806 (void) XParseColor(display,windows->map_info->colormap,
9807 resource_info->pen_colors[pen_number],&border_color);
9810 case MatteEditFuzzCommand:
9813 fuzz[MaxTextExtent];
9828 Select a command from the pop-up menu.
9830 entry=XMenuWidget(display,windows,MatteEditMenu[id],FuzzMenu,
9836 (*image)->fuzz=SiPrefixToDouble(FuzzMenu[entry],1.0*
9840 (void) CopyMagickString(fuzz,"20%",MaxTextExtent);
9841 (void) XDialogWidget(display,windows,"Ok",
9842 "Enter fuzz factor (0.0 - 99.9%):",fuzz);
9845 (void) ConcatenateMagickString(fuzz,"%",MaxTextExtent);
9846 (*image)->fuzz=SiPrefixToDouble(fuzz,1.0*QuantumRange+1.0);
9849 case MatteEditValueCommand:
9852 message[MaxTextExtent];
9864 Select a command from the pop-up menu.
9866 entry=XMenuWidget(display,windows,MatteEditMenu[id],MatteMenu,
9872 (void) FormatLocaleString(matte,MaxTextExtent,QuantumFormat,
9874 if (LocaleCompare(MatteMenu[entry],"Transparent") == 0)
9875 (void) FormatLocaleString(matte,MaxTextExtent,QuantumFormat,
9876 (Quantum) TransparentAlpha);
9879 (void) FormatLocaleString(message,MaxTextExtent,
9880 "Enter matte value (0 - " QuantumFormat "):",(Quantum)
9882 (void) XDialogWidget(display,windows,"Matte",message,matte);
9887 case MatteEditUndoCommand:
9889 (void) XMagickCommand(display,resource_info,windows,UndoCommand,
9893 case MatteEditHelpCommand:
9895 XTextViewWidget(display,resource_info,windows,MagickFalse,
9896 "Help Viewer - Matte Edit",ImageMatteEditHelp);
9899 case MatteEditDismissCommand:
9911 (void) XCheckDefineCursor(display,windows->image.id,cursor);
9918 if (event.xbutton.button != Button1)
9920 if ((event.xbutton.window != windows->image.id) &&
9921 (event.xbutton.window != windows->magnify.id))
9928 (void) XMagickCommand(display,resource_info,windows,
9929 SaveToUndoBufferCommand,image,exception);
9930 state|=UpdateConfigurationState;
9935 if (event.xbutton.button != Button1)
9937 if ((event.xbutton.window != windows->image.id) &&
9938 (event.xbutton.window != windows->magnify.id))
9941 Update colormap information.
9945 XConfigureImageColormap(display,resource_info,windows,*image);
9946 (void) XConfigureImage(display,resource_info,windows,*image,exception);
9947 XInfoWidget(display,windows,text);
9948 (void) XCheckDefineCursor(display,windows->image.id,cursor);
9949 state&=(~UpdateConfigurationState);
9957 command[MaxTextExtent];
9962 if (event.xkey.window == windows->magnify.id)
9967 window=windows->magnify.id;
9968 while (XCheckWindowEvent(display,window,KeyPressMask,&event)) ;
9970 if (event.xkey.window != windows->image.id)
9973 Respond to a user key press.
9975 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
9976 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
9977 switch ((int) key_symbol)
9991 XTextViewWidget(display,resource_info,windows,MagickFalse,
9992 "Help Viewer - Matte Edit",ImageMatteEditHelp);
9997 (void) XBell(display,0);
10006 Map and unmap Info widget as cursor crosses its boundaries.
10010 if (windows->info.mapped != MagickFalse)
10012 if ((x < (int) (windows->info.x+windows->info.width)) &&
10013 (y < (int) (windows->info.y+windows->info.height)))
10014 (void) XWithdrawWindow(display,windows->info.id,
10015 windows->info.screen);
10018 if ((x > (int) (windows->info.x+windows->info.width)) ||
10019 (y > (int) (windows->info.y+windows->info.height)))
10020 (void) XMapWindow(display,windows->info.id);
10026 if (event.xany.window == windows->magnify.id)
10028 x=windows->magnify.x-windows->image.x;
10029 y=windows->magnify.y-windows->image.y;
10033 if ((state & UpdateConfigurationState) != 0)
10043 Matte edit is relative to image configuration.
10045 (void) XClearArea(display,windows->image.id,x_offset,y_offset,1,1,
10047 XPutPixel(windows->image.ximage,x_offset,y_offset,
10048 windows->pixel_info->background_color.pixel);
10049 width=(unsigned int) (*image)->columns;
10050 height=(unsigned int) (*image)->rows;
10053 if (windows->image.crop_geometry != (char *) NULL)
10054 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,
10056 x_offset=(int) (width*(windows->image.x+x_offset)/
10057 windows->image.ximage->width+x);
10058 y_offset=(int) (height*(windows->image.y+y_offset)/
10059 windows->image.ximage->height+y);
10060 if ((x_offset < 0) || (y_offset < 0))
10062 if ((x_offset >= (int) (*image)->columns) ||
10063 (y_offset >= (int) (*image)->rows))
10065 if (SetImageStorageClass(*image,DirectClass,exception) == MagickFalse)
10066 return(MagickFalse);
10067 (*image)->matte=MagickTrue;
10068 image_view=AcquireCacheView(*image);
10075 Update matte information using point algorithm.
10077 q=GetCacheViewAuthenticPixels(image_view,(ssize_t) x_offset,
10078 (ssize_t) y_offset,1,1,exception);
10079 if (q == (Quantum *) NULL)
10081 SetPixelAlpha(*image,(Quantum) StringToLong(matte),q);
10082 (void) SyncCacheViewAuthenticPixels(image_view,exception);
10085 case ReplaceMethod:
10092 Update matte information using replace algorithm.
10094 (void) GetOneCacheViewVirtualPixel(image_view,(ssize_t) x_offset,
10095 (ssize_t) y_offset,&target,exception);
10096 for (y=0; y < (int) (*image)->rows; y++)
10098 q=GetCacheViewAuthenticPixels(image_view,0,(ssize_t) y,
10099 (*image)->columns,1,exception);
10100 if (q == (Quantum *) NULL)
10102 for (x=0; x < (int) (*image)->columns; x++)
10104 GetPixelPacket(*image,q,&pixel);
10105 if (IsFuzzyEquivalencePixelPacket(*image,&pixel,&target))
10106 SetPixelAlpha(*image,(Quantum) StringToLong(matte),q);
10107 q+=GetPixelChannels(*image);
10109 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
10114 case FloodfillMethod:
10115 case FillToBorderMethod:
10127 Update matte information using floodfill algorithm.
10129 (void) GetOneVirtualMagickPixel(*image,(ssize_t) x_offset,
10130 (ssize_t) y_offset,&target,exception);
10131 if (method == FillToBorderMethod)
10133 target.red=(MagickRealType) ScaleShortToQuantum(
10135 target.green=(MagickRealType) ScaleShortToQuantum(
10136 border_color.green);
10137 target.blue=(MagickRealType) ScaleShortToQuantum(
10138 border_color.blue);
10140 draw_info=CloneDrawInfo(resource_info->image_info,
10141 (DrawInfo *) NULL);
10142 draw_info->fill.alpha=ClampToQuantum(InterpretLocaleValue(matte,
10144 channel_mask=SetPixelChannelMask(*image,AlphaChannel);
10145 (void) FloodfillPaintImage(*image,draw_info,&target,(ssize_t)
10146 x_offset,(ssize_t) y_offset,method == FloodfillMethod ?
10147 MagickFalse : MagickTrue,exception);
10148 (void) SetPixelChannelMap(*image,channel_mask);
10149 draw_info=DestroyDrawInfo(draw_info);
10155 Update matte information using reset algorithm.
10157 if (SetImageStorageClass(*image,DirectClass,exception) == MagickFalse)
10158 return(MagickFalse);
10159 for (y=0; y < (int) (*image)->rows; y++)
10161 q=QueueCacheViewAuthenticPixels(image_view,0,(ssize_t) y,
10162 (*image)->columns,1,exception);
10163 if (q == (Quantum *) NULL)
10165 for (x=0; x < (int) (*image)->columns; x++)
10167 SetPixelAlpha(*image,(Quantum) StringToLong(matte),q);
10168 q+=GetPixelChannels(*image);
10170 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
10173 if (StringToLong(matte) == (long) OpaqueAlpha)
10174 (*image)->matte=MagickFalse;
10178 image_view=DestroyCacheView(image_view);
10179 state&=(~UpdateConfigurationState);
10181 } while ((state & ExitState) == 0);
10182 (void) XSelectInput(display,windows->image.id,
10183 windows->image.attributes.event_mask);
10184 XSetCursorState(display,windows,MagickFalse);
10185 (void) XFreeCursor(display,cursor);
10186 return(MagickTrue);
10190 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10194 + X O p e n I m a g e %
10198 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10200 % XOpenImage() loads an image from a file.
10202 % The format of the XOpenImage method is:
10204 % Image *XOpenImage(Display *display,XResourceInfo *resource_info,
10205 % XWindows *windows,const unsigned int command)
10207 % A description of each parameter follows:
10209 % o display: Specifies a connection to an X server; returned from
10212 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
10214 % o windows: Specifies a pointer to a XWindows structure.
10216 % o command: A value other than zero indicates that the file is selected
10217 % from the command line argument list.
10220 static Image *XOpenImage(Display *display,XResourceInfo *resource_info,
10221 XWindows *windows,const MagickBooleanType command)
10236 filename[MaxTextExtent] = "\0";
10239 Request file name from user.
10241 if (command == MagickFalse)
10242 XFileBrowserWidget(display,windows,"Open",filename);
10258 Select next image from the command line.
10260 status=XGetCommand(display,windows->image.id,&files,&count);
10263 ThrowXWindowFatalException(XServerError,"UnableToGetProperty","...");
10264 return((Image *) NULL);
10266 filelist=(char **) AcquireQuantumMemory((size_t) count,sizeof(*filelist));
10267 if (filelist == (char **) NULL)
10269 ThrowXWindowFatalException(ResourceLimitError,
10270 "MemoryAllocationFailed","...");
10271 (void) XFreeStringList(files);
10272 return((Image *) NULL);
10275 for (i=1; i < count; i++)
10276 if (*files[i] != '-')
10277 filelist[j++]=files[i];
10278 filelist[j]=(char *) NULL;
10279 XListBrowserWidget(display,windows,&windows->widget,
10280 (const char **) filelist,"Load","Select Image to Load:",filename);
10281 filelist=(char **) RelinquishMagickMemory(filelist);
10282 (void) XFreeStringList(files);
10284 if (*filename == '\0')
10285 return((Image *) NULL);
10286 image_info=CloneImageInfo(resource_info->image_info);
10287 (void) SetImageInfoProgressMonitor(image_info,(MagickProgressMonitor) NULL,
10289 (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
10290 exception=AcquireExceptionInfo();
10291 (void) SetImageInfo(image_info,0,exception);
10292 if (LocaleCompare(image_info->magick,"X") == 0)
10295 seconds[MaxTextExtent];
10298 User may want to delay the X server screen grab.
10300 (void) CopyMagickString(seconds,"0",MaxTextExtent);
10301 (void) XDialogWidget(display,windows,"Grab","Enter any delay in seconds:",
10303 if (*seconds == '\0')
10304 return((Image *) NULL);
10305 XDelay(display,(size_t) (1000*StringToLong(seconds)));
10307 magick_info=GetMagickInfo(image_info->magick,exception);
10308 if ((magick_info != (const MagickInfo *) NULL) &&
10309 (magick_info->raw != MagickFalse))
10312 geometry[MaxTextExtent];
10315 Request image size from the user.
10317 (void) CopyMagickString(geometry,"512x512",MaxTextExtent);
10318 if (image_info->size != (char *) NULL)
10319 (void) CopyMagickString(geometry,image_info->size,MaxTextExtent);
10320 (void) XDialogWidget(display,windows,"Load","Enter the image geometry:",
10322 (void) CloneString(&image_info->size,geometry);
10327 XSetCursorState(display,windows,MagickTrue);
10328 XCheckRefreshWindows(display,windows);
10329 (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
10330 nexus=ReadImage(image_info,exception);
10331 CatchException(exception);
10332 XSetCursorState(display,windows,MagickFalse);
10333 if (nexus != (Image *) NULL)
10334 XClientMessage(display,windows->image.id,windows->im_protocols,
10335 windows->im_next_image,CurrentTime);
10343 Unknown image format.
10345 text=FileToString(filename,~0,exception);
10346 if (text == (char *) NULL)
10347 return((Image *) NULL);
10348 textlist=StringToList(text);
10349 if (textlist != (char **) NULL)
10352 title[MaxTextExtent];
10357 (void) FormatLocaleString(title,MaxTextExtent,
10358 "Unknown format: %s",filename);
10359 XTextViewWidget(display,resource_info,windows,MagickTrue,title,
10360 (const char **) textlist);
10361 for (i=0; textlist[i] != (char *) NULL; i++)
10362 textlist[i]=DestroyString(textlist[i]);
10363 textlist=(char **) RelinquishMagickMemory(textlist);
10365 text=DestroyString(text);
10367 exception=DestroyExceptionInfo(exception);
10368 image_info=DestroyImageInfo(image_info);
10373 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10377 + X P a n I m a g e %
10381 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10383 % XPanImage() pans the image until the mouse button is released.
10385 % The format of the XPanImage method is:
10387 % void XPanImage(Display *display,XWindows *windows,XEvent *event)
10389 % A description of each parameter follows:
10391 % o display: Specifies a connection to an X server; returned from
10394 % o windows: Specifies a pointer to a XWindows structure.
10396 % o event: Specifies a pointer to a XEvent structure. If it is NULL,
10397 % the entire image is refreshed.
10400 static void XPanImage(Display *display,XWindows *windows,XEvent *event)
10403 text[MaxTextExtent];
10421 if ((windows->image.ximage->width > (int) windows->image.width) &&
10422 (windows->image.ximage->height > (int) windows->image.height))
10423 cursor=XCreateFontCursor(display,XC_fleur);
10425 if (windows->image.ximage->width > (int) windows->image.width)
10426 cursor=XCreateFontCursor(display,XC_sb_h_double_arrow);
10428 if (windows->image.ximage->height > (int) windows->image.height)
10429 cursor=XCreateFontCursor(display,XC_sb_v_double_arrow);
10431 cursor=XCreateFontCursor(display,XC_arrow);
10432 (void) XCheckDefineCursor(display,windows->pan.id,cursor);
10434 Pan image as pointer moves until the mouse button is released.
10436 x_factor=(MagickRealType) windows->image.ximage->width/windows->pan.width;
10437 y_factor=(MagickRealType) windows->image.ximage->height/windows->pan.height;
10438 pan_info.width=windows->pan.width*windows->image.width/
10439 windows->image.ximage->width;
10440 pan_info.height=windows->pan.height*windows->image.height/
10441 windows->image.ximage->height;
10444 state=UpdateConfigurationState;
10447 switch (event->type)
10452 User choose an initial pan location.
10454 pan_info.x=(ssize_t) event->xbutton.x;
10455 pan_info.y=(ssize_t) event->xbutton.y;
10456 state|=UpdateConfigurationState;
10459 case ButtonRelease:
10462 User has finished panning the image.
10464 pan_info.x=(ssize_t) event->xbutton.x;
10465 pan_info.y=(ssize_t) event->xbutton.y;
10466 state|=UpdateConfigurationState | ExitState;
10471 pan_info.x=(ssize_t) event->xmotion.x;
10472 pan_info.y=(ssize_t) event->xmotion.y;
10473 state|=UpdateConfigurationState;
10478 if ((state & UpdateConfigurationState) != 0)
10481 Check boundary conditions.
10483 if (pan_info.x < (ssize_t) (pan_info.width/2))
10486 pan_info.x=(ssize_t) (x_factor*(pan_info.x-(pan_info.width/2)));
10487 if (pan_info.x < 0)
10490 if ((int) (pan_info.x+windows->image.width) >
10491 windows->image.ximage->width)
10492 pan_info.x=(ssize_t)
10493 (windows->image.ximage->width-windows->image.width);
10494 if (pan_info.y < (ssize_t) (pan_info.height/2))
10497 pan_info.y=(ssize_t) (y_factor*(pan_info.y-(pan_info.height/2)));
10498 if (pan_info.y < 0)
10501 if ((int) (pan_info.y+windows->image.height) >
10502 windows->image.ximage->height)
10503 pan_info.y=(ssize_t)
10504 (windows->image.ximage->height-windows->image.height);
10505 if ((windows->image.x != (int) pan_info.x) ||
10506 (windows->image.y != (int) pan_info.y))
10509 Display image pan offset.
10511 windows->image.x=(int) pan_info.x;
10512 windows->image.y=(int) pan_info.y;
10513 (void) FormatLocaleString(text,MaxTextExtent," %ux%u%+d%+d ",
10514 windows->image.width,windows->image.height,windows->image.x,
10516 XInfoWidget(display,windows,text);
10518 Refresh Image window.
10520 XDrawPanRectangle(display,windows);
10521 XRefreshWindow(display,&windows->image,(XEvent *) NULL);
10523 state&=(~UpdateConfigurationState);
10526 Wait for next event.
10528 if ((state & ExitState) == 0)
10529 XScreenEvent(display,windows,event);
10530 } while ((state & ExitState) == 0);
10534 (void) XCheckDefineCursor(display,windows->pan.id,windows->pan.cursor);
10535 (void) XFreeCursor(display,cursor);
10536 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
10540 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10544 + X P a s t e I m a g e %
10548 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10550 % XPasteImage() pastes an image previously saved with XCropImage in the X
10551 % window image at a location the user chooses with the pointer.
10553 % The format of the XPasteImage method is:
10555 % MagickBooleanType XPasteImage(Display *display,
10556 % XResourceInfo *resource_info,XWindows *windows,Image *image,
10557 % ExceptionInfo *exception)
10559 % A description of each parameter follows:
10561 % o display: Specifies a connection to an X server; returned from
10564 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
10566 % o windows: Specifies a pointer to a XWindows structure.
10568 % o image: the image; returned from ReadImage.
10570 % o exception: return any errors or warnings in this structure.
10573 static MagickBooleanType XPasteImage(Display *display,
10574 XResourceInfo *resource_info,XWindows *windows,Image *image,
10575 ExceptionInfo *exception)
10586 static const ModeType
10589 PasteOperatorsCommand,
10591 PasteDismissCommand
10594 static CompositeOperator
10595 compose = CopyCompositeOp;
10598 text[MaxTextExtent];
10632 if (resource_info->copy_image == (Image *) NULL)
10633 return(MagickFalse);
10634 paste_image=CloneImage(resource_info->copy_image,0,0,MagickTrue,exception);
10636 Map Command widget.
10638 (void) CloneString(&windows->command.name,"Paste");
10639 windows->command.data=1;
10640 (void) XCommandWidget(display,windows,PasteMenu,(XEvent *) NULL);
10641 (void) XMapRaised(display,windows->command.id);
10642 XClientMessage(display,windows->image.id,windows->im_protocols,
10643 windows->im_update_widget,CurrentTime);
10645 Track pointer until button 1 is pressed.
10647 XSetCursorState(display,windows,MagickFalse);
10648 XQueryPosition(display,windows->image.id,&x,&y);
10649 (void) XSelectInput(display,windows->image.id,
10650 windows->image.attributes.event_mask | PointerMotionMask);
10651 paste_info.x=(ssize_t) windows->image.x+x;
10652 paste_info.y=(ssize_t) windows->image.y+y;
10653 paste_info.width=0;
10654 paste_info.height=0;
10655 cursor=XCreateFontCursor(display,XC_ul_angle);
10656 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
10657 state=DefaultState;
10660 if (windows->info.mapped != MagickFalse)
10663 Display pointer position.
10665 (void) FormatLocaleString(text,MaxTextExtent," %+ld%+ld ",
10666 (long) paste_info.x,(long) paste_info.y);
10667 XInfoWidget(display,windows,text);
10669 highlight_info=paste_info;
10670 highlight_info.x=paste_info.x-windows->image.x;
10671 highlight_info.y=paste_info.y-windows->image.y;
10672 XHighlightRectangle(display,windows->image.id,
10673 windows->image.highlight_context,&highlight_info);
10675 Wait for next event.
10677 XScreenEvent(display,windows,&event);
10678 XHighlightRectangle(display,windows->image.id,
10679 windows->image.highlight_context,&highlight_info);
10680 if (event.xany.window == windows->command.id)
10683 Select a command from the Command widget.
10685 id=XCommandWidget(display,windows,PasteMenu,&event);
10688 switch (PasteCommands[id])
10690 case PasteOperatorsCommand:
10693 command[MaxTextExtent],
10697 Select a command from the pop-up menu.
10699 operators=GetCommandOptions(MagickComposeOptions);
10700 if (operators == (char **) NULL)
10702 entry=XMenuWidget(display,windows,PasteMenu[id],
10703 (const char **) operators,command);
10705 compose=(CompositeOperator) ParseCommandOption(
10706 MagickComposeOptions,MagickFalse,operators[entry]);
10707 operators=DestroyStringList(operators);
10710 case PasteHelpCommand:
10712 XTextViewWidget(display,resource_info,windows,MagickFalse,
10713 "Help Viewer - Image Composite",ImagePasteHelp);
10716 case PasteDismissCommand:
10721 state|=EscapeState;
10730 switch (event.type)
10734 if (image->debug != MagickFalse)
10735 (void) LogMagickEvent(X11Event,GetMagickModule(),
10736 "Button Press: 0x%lx %u +%d+%d",event.xbutton.window,
10737 event.xbutton.button,event.xbutton.x,event.xbutton.y);
10738 if (event.xbutton.button != Button1)
10740 if (event.xbutton.window != windows->image.id)
10743 Paste rectangle is relative to image configuration.
10745 width=(unsigned int) image->columns;
10746 height=(unsigned int) image->rows;
10749 if (windows->image.crop_geometry != (char *) NULL)
10750 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,
10752 scale_factor=(MagickRealType) windows->image.ximage->width/width;
10753 paste_info.width=(unsigned int) (scale_factor*paste_image->columns+0.5);
10754 scale_factor=(MagickRealType) windows->image.ximage->height/height;
10755 paste_info.height=(unsigned int) (scale_factor*paste_image->rows+0.5);
10756 (void) XCheckDefineCursor(display,windows->image.id,cursor);
10757 paste_info.x=(ssize_t) windows->image.x+event.xbutton.x;
10758 paste_info.y=(ssize_t) windows->image.y+event.xbutton.y;
10761 case ButtonRelease:
10763 if (image->debug != MagickFalse)
10764 (void) LogMagickEvent(X11Event,GetMagickModule(),
10765 "Button Release: 0x%lx %u +%d+%d",event.xbutton.window,
10766 event.xbutton.button,event.xbutton.x,event.xbutton.y);
10767 if (event.xbutton.button != Button1)
10769 if (event.xbutton.window != windows->image.id)
10771 if ((paste_info.width != 0) && (paste_info.height != 0))
10774 User has selected the location of the paste image.
10776 paste_info.x=(ssize_t) windows->image.x+event.xbutton.x;
10777 paste_info.y=(ssize_t) windows->image.y+event.xbutton.y;
10787 command[MaxTextExtent];
10795 if (event.xkey.window != windows->image.id)
10798 Respond to a user key press.
10800 length=XLookupString((XKeyEvent *) &event.xkey,command,(int)
10801 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
10802 *(command+length)='\0';
10803 if (image->debug != MagickFalse)
10804 (void) LogMagickEvent(X11Event,GetMagickModule(),
10805 "Key press: 0x%lx (%s)",(long) key_symbol,command);
10806 switch ((int) key_symbol)
10814 paste_image=DestroyImage(paste_image);
10815 state|=EscapeState;
10822 (void) XSetFunction(display,windows->image.highlight_context,
10824 XTextViewWidget(display,resource_info,windows,MagickFalse,
10825 "Help Viewer - Image Composite",ImagePasteHelp);
10826 (void) XSetFunction(display,windows->image.highlight_context,
10832 (void) XBell(display,0);
10841 Map and unmap Info widget as text cursor crosses its boundaries.
10845 if (windows->info.mapped != MagickFalse)
10847 if ((x < (int) (windows->info.x+windows->info.width)) &&
10848 (y < (int) (windows->info.y+windows->info.height)))
10849 (void) XWithdrawWindow(display,windows->info.id,
10850 windows->info.screen);
10853 if ((x > (int) (windows->info.x+windows->info.width)) ||
10854 (y > (int) (windows->info.y+windows->info.height)))
10855 (void) XMapWindow(display,windows->info.id);
10856 paste_info.x=(ssize_t) windows->image.x+x;
10857 paste_info.y=(ssize_t) windows->image.y+y;
10862 if (image->debug != MagickFalse)
10863 (void) LogMagickEvent(X11Event,GetMagickModule(),"Event type: %d",
10868 } while ((state & ExitState) == 0);
10869 (void) XSelectInput(display,windows->image.id,
10870 windows->image.attributes.event_mask);
10871 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
10872 XSetCursorState(display,windows,MagickFalse);
10873 (void) XFreeCursor(display,cursor);
10874 if ((state & EscapeState) != 0)
10875 return(MagickTrue);
10877 Image pasting is relative to image configuration.
10879 XSetCursorState(display,windows,MagickTrue);
10880 XCheckRefreshWindows(display,windows);
10881 width=(unsigned int) image->columns;
10882 height=(unsigned int) image->rows;
10885 if (windows->image.crop_geometry != (char *) NULL)
10886 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
10887 scale_factor=(MagickRealType) width/windows->image.ximage->width;
10889 paste_info.x=(ssize_t) (scale_factor*paste_info.x+0.5);
10890 paste_info.width=(unsigned int) (scale_factor*paste_info.width+0.5);
10891 scale_factor=(MagickRealType) height/windows->image.ximage->height;
10893 paste_info.y=(ssize_t) (scale_factor*paste_info.y*scale_factor+0.5);
10894 paste_info.height=(unsigned int) (scale_factor*paste_info.height+0.5);
10896 Paste image with X Image window.
10898 (void) CompositeImage(image,compose,paste_image,paste_info.x,paste_info.y);
10899 paste_image=DestroyImage(paste_image);
10900 XSetCursorState(display,windows,MagickFalse);
10902 Update image colormap.
10904 XConfigureImageColormap(display,resource_info,windows,image);
10905 (void) XConfigureImage(display,resource_info,windows,image,exception);
10906 return(MagickTrue);
10910 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10914 + X P r i n t I m a g e %
10918 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10920 % XPrintImage() prints an image to a Postscript printer.
10922 % The format of the XPrintImage method is:
10924 % MagickBooleanType XPrintImage(Display *display,
10925 % XResourceInfo *resource_info,XWindows *windows,Image *image,
10926 % ExceptionInfo *exception)
10928 % A description of each parameter follows:
10930 % o display: Specifies a connection to an X server; returned from
10933 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
10935 % o windows: Specifies a pointer to a XWindows structure.
10937 % o image: the image.
10939 % o exception: return any errors or warnings in this structure.
10942 static MagickBooleanType XPrintImage(Display *display,
10943 XResourceInfo *resource_info,XWindows *windows,Image *image,
10944 ExceptionInfo *exception)
10947 filename[MaxTextExtent],
10948 geometry[MaxTextExtent];
10960 Request Postscript page geometry from user.
10962 image_info=CloneImageInfo(resource_info->image_info);
10963 (void) FormatLocaleString(geometry,MaxTextExtent,"Letter");
10964 if (image_info->page != (char *) NULL)
10965 (void) CopyMagickString(geometry,image_info->page,MaxTextExtent);
10966 XListBrowserWidget(display,windows,&windows->widget,PageSizes,"Select",
10967 "Select Postscript Page Geometry:",geometry);
10968 if (*geometry == '\0')
10969 return(MagickTrue);
10970 image_info->page=GetPageGeometry(geometry);
10972 Apply image transforms.
10974 XSetCursorState(display,windows,MagickTrue);
10975 XCheckRefreshWindows(display,windows);
10976 print_image=CloneImage(image,0,0,MagickTrue,exception);
10977 if (print_image == (Image *) NULL)
10978 return(MagickFalse);
10979 (void) FormatLocaleString(geometry,MaxTextExtent,"%dx%d!",
10980 windows->image.ximage->width,windows->image.ximage->height);
10981 (void) TransformImage(&print_image,windows->image.crop_geometry,geometry);
10985 (void) AcquireUniqueFilename(filename);
10986 (void) FormatLocaleString(print_image->filename,MaxTextExtent,"print:%s",
10988 status=WriteImage(image_info,print_image,exception);
10989 (void) RelinquishUniqueFileResource(filename);
10990 print_image=DestroyImage(print_image);
10991 image_info=DestroyImageInfo(image_info);
10992 XSetCursorState(display,windows,MagickFalse);
10993 return(status != 0 ? MagickTrue : MagickFalse);
10997 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
11001 + X R O I I m a g e %
11005 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
11007 % XROIImage() applies an image processing technique to a region of interest.
11009 % The format of the XROIImage method is:
11011 % MagickBooleanType XROIImage(Display *display,
11012 % XResourceInfo *resource_info,XWindows *windows,Image **image,
11013 % ExceptionInfo *exception)
11015 % A description of each parameter follows:
11017 % o display: Specifies a connection to an X server; returned from
11020 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
11022 % o windows: Specifies a pointer to a XWindows structure.
11024 % o image: the image; returned from ReadImage.
11026 % o exception: return any errors or warnings in this structure.
11029 static MagickBooleanType XROIImage(Display *display,
11030 XResourceInfo *resource_info,XWindows *windows,Image **image,
11031 ExceptionInfo *exception)
11033 #define ApplyMenus 7
11083 "Contrast Stretch...",
11084 "Sigmoidal Contrast...",
11118 "Charcoal Draw...",
11121 *MiscellanyMenu[] =
11132 **Menus[ApplyMenus] =
11143 static const CommandType
11166 TransformCommands[] =
11170 RotateRightCommand,
11173 EnhanceCommands[] =
11181 ContrastStretchCommand,
11182 SigmoidalContrastCommand,
11190 EffectsCommands[] =
11194 ReduceNoiseCommand,
11213 CharcoalDrawCommand
11215 MiscellanyCommands[] =
11219 ShowPreviewCommand,
11220 ShowHistogramCommand,
11229 static const CommandType
11230 *Commands[ApplyMenus] =
11242 command[MaxTextExtent],
11243 text[MaxTextExtent];
11263 MagickProgressMonitor
11282 Map Command widget.
11284 (void) CloneString(&windows->command.name,"ROI");
11285 windows->command.data=0;
11286 (void) XCommandWidget(display,windows,ROIMenu,(XEvent *) NULL);
11287 (void) XMapRaised(display,windows->command.id);
11288 XClientMessage(display,windows->image.id,windows->im_protocols,
11289 windows->im_update_widget,CurrentTime);
11291 Track pointer until button 1 is pressed.
11293 XQueryPosition(display,windows->image.id,&x,&y);
11294 (void) XSelectInput(display,windows->image.id,
11295 windows->image.attributes.event_mask | PointerMotionMask);
11296 roi_info.x=(ssize_t) windows->image.x+x;
11297 roi_info.y=(ssize_t) windows->image.y+y;
11300 cursor=XCreateFontCursor(display,XC_fleur);
11301 state=DefaultState;
11304 if (windows->info.mapped != MagickFalse)
11307 Display pointer position.
11309 (void) FormatLocaleString(text,MaxTextExtent," %+ld%+ld ",
11310 (long) roi_info.x,(long) roi_info.y);
11311 XInfoWidget(display,windows,text);
11314 Wait for next event.
11316 XScreenEvent(display,windows,&event);
11317 if (event.xany.window == windows->command.id)
11320 Select a command from the Command widget.
11322 id=XCommandWidget(display,windows,ROIMenu,&event);
11325 switch (ROICommands[id])
11327 case ROIHelpCommand:
11329 XTextViewWidget(display,resource_info,windows,MagickFalse,
11330 "Help Viewer - Region of Interest",ImageROIHelp);
11333 case ROIDismissCommand:
11338 state|=EscapeState;
11347 switch (event.type)
11351 if (event.xbutton.button != Button1)
11353 if (event.xbutton.window != windows->image.id)
11356 Note first corner of region of interest rectangle-- exit loop.
11358 (void) XCheckDefineCursor(display,windows->image.id,cursor);
11359 roi_info.x=(ssize_t) windows->image.x+event.xbutton.x;
11360 roi_info.y=(ssize_t) windows->image.y+event.xbutton.y;
11364 case ButtonRelease:
11373 if (event.xkey.window != windows->image.id)
11376 Respond to a user key press.
11378 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
11379 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
11380 switch ((int) key_symbol)
11388 state|=EscapeState;
11395 XTextViewWidget(display,resource_info,windows,MagickFalse,
11396 "Help Viewer - Region of Interest",ImageROIHelp);
11401 (void) XBell(display,0);
11410 Map and unmap Info widget as text cursor crosses its boundaries.
11414 if (windows->info.mapped != MagickFalse)
11416 if ((x < (int) (windows->info.x+windows->info.width)) &&
11417 (y < (int) (windows->info.y+windows->info.height)))
11418 (void) XWithdrawWindow(display,windows->info.id,
11419 windows->info.screen);
11422 if ((x > (int) (windows->info.x+windows->info.width)) ||
11423 (y > (int) (windows->info.y+windows->info.height)))
11424 (void) XMapWindow(display,windows->info.id);
11425 roi_info.x=(ssize_t) windows->image.x+x;
11426 roi_info.y=(ssize_t) windows->image.y+y;
11432 } while ((state & ExitState) == 0);
11433 (void) XSelectInput(display,windows->image.id,
11434 windows->image.attributes.event_mask);
11435 if ((state & EscapeState) != 0)
11438 User want to exit without region of interest.
11440 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
11441 (void) XFreeCursor(display,cursor);
11442 return(MagickTrue);
11444 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
11448 Size rectangle as pointer moves until the mouse button is released.
11450 x=(int) roi_info.x;
11451 y=(int) roi_info.y;
11454 state=DefaultState;
11457 highlight_info=roi_info;
11458 highlight_info.x=roi_info.x-windows->image.x;
11459 highlight_info.y=roi_info.y-windows->image.y;
11460 if ((highlight_info.width > 3) && (highlight_info.height > 3))
11463 Display info and draw region of interest rectangle.
11465 if (windows->info.mapped == MagickFalse)
11466 (void) XMapWindow(display,windows->info.id);
11467 (void) FormatLocaleString(text,MaxTextExtent,
11468 " %.20gx%.20g%+.20g%+.20g",(double) roi_info.width,(double)
11469 roi_info.height,(double) roi_info.x,(double) roi_info.y);
11470 XInfoWidget(display,windows,text);
11471 XHighlightRectangle(display,windows->image.id,
11472 windows->image.highlight_context,&highlight_info);
11475 if (windows->info.mapped != MagickFalse)
11476 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
11478 Wait for next event.
11480 XScreenEvent(display,windows,&event);
11481 if ((highlight_info.width > 3) && (highlight_info.height > 3))
11482 XHighlightRectangle(display,windows->image.id,
11483 windows->image.highlight_context,&highlight_info);
11484 switch (event.type)
11488 roi_info.x=(ssize_t) windows->image.x+event.xbutton.x;
11489 roi_info.y=(ssize_t) windows->image.y+event.xbutton.y;
11492 case ButtonRelease:
11495 User has committed to region of interest rectangle.
11497 roi_info.x=(ssize_t) windows->image.x+event.xbutton.x;
11498 roi_info.y=(ssize_t) windows->image.y+event.xbutton.y;
11499 XSetCursorState(display,windows,MagickFalse);
11501 if (LocaleCompare(windows->command.name,"Apply") == 0)
11503 (void) CloneString(&windows->command.name,"Apply");
11504 windows->command.data=ApplyMenus;
11505 (void) XCommandWidget(display,windows,ApplyMenu,(XEvent *) NULL);
11512 roi_info.x=(ssize_t) windows->image.x+event.xmotion.x;
11513 roi_info.y=(ssize_t) windows->image.y+event.xmotion.y;
11518 if ((((int) roi_info.x != x) && ((int) roi_info.y != y)) ||
11519 ((state & ExitState) != 0))
11522 Check boundary conditions.
11524 if (roi_info.x < 0)
11527 if (roi_info.x > (ssize_t) windows->image.ximage->width)
11528 roi_info.x=(ssize_t) windows->image.ximage->width;
11529 if ((int) roi_info.x < x)
11530 roi_info.width=(unsigned int) (x-roi_info.x);
11533 roi_info.width=(unsigned int) (roi_info.x-x);
11534 roi_info.x=(ssize_t) x;
11536 if (roi_info.y < 0)
11539 if (roi_info.y > (ssize_t) windows->image.ximage->height)
11540 roi_info.y=(ssize_t) windows->image.ximage->height;
11541 if ((int) roi_info.y < y)
11542 roi_info.height=(unsigned int) (y-roi_info.y);
11545 roi_info.height=(unsigned int) (roi_info.y-y);
11546 roi_info.y=(ssize_t) y;
11549 } while ((state & ExitState) == 0);
11551 Wait for user to grab a corner of the rectangle or press return.
11553 state=DefaultState;
11554 command_type=NullCommand;
11555 (void) XMapWindow(display,windows->info.id);
11558 if (windows->info.mapped != MagickFalse)
11561 Display pointer position.
11563 (void) FormatLocaleString(text,MaxTextExtent,
11564 " %.20gx%.20g%+.20g%+.20g",(double) roi_info.width,(double)
11565 roi_info.height,(double) roi_info.x,(double) roi_info.y);
11566 XInfoWidget(display,windows,text);
11568 highlight_info=roi_info;
11569 highlight_info.x=roi_info.x-windows->image.x;
11570 highlight_info.y=roi_info.y-windows->image.y;
11571 if ((highlight_info.width <= 3) || (highlight_info.height <= 3))
11573 state|=EscapeState;
11577 if ((state & UpdateRegionState) != 0)
11579 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
11580 switch (command_type)
11585 (void) XMagickCommand(display,resource_info,windows,command_type,
11592 Region of interest is relative to image configuration.
11594 progress_monitor=SetImageProgressMonitor(*image,
11595 (MagickProgressMonitor) NULL,(*image)->client_data);
11596 crop_info=roi_info;
11597 width=(unsigned int) (*image)->columns;
11598 height=(unsigned int) (*image)->rows;
11601 if (windows->image.crop_geometry != (char *) NULL)
11602 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,
11604 scale_factor=(MagickRealType) width/windows->image.ximage->width;
11606 crop_info.x=(ssize_t) (scale_factor*crop_info.x+0.5);
11607 crop_info.width=(unsigned int) (scale_factor*crop_info.width+0.5);
11608 scale_factor=(MagickRealType)
11609 height/windows->image.ximage->height;
11611 crop_info.y=(ssize_t) (scale_factor*crop_info.y+0.5);
11612 crop_info.height=(unsigned int)
11613 (scale_factor*crop_info.height+0.5);
11614 roi_image=CropImage(*image,&crop_info,exception);
11615 (void) SetImageProgressMonitor(*image,progress_monitor,
11616 (*image)->client_data);
11617 if (roi_image == (Image *) NULL)
11620 Apply image processing technique to the region of interest.
11622 windows->image.orphan=MagickTrue;
11623 (void) XMagickCommand(display,resource_info,windows,command_type,
11624 &roi_image,exception);
11625 progress_monitor=SetImageProgressMonitor(*image,
11626 (MagickProgressMonitor) NULL,(*image)->client_data);
11627 (void) XMagickCommand(display,resource_info,windows,
11628 SaveToUndoBufferCommand,image,exception);
11629 windows->image.orphan=MagickFalse;
11630 (void) CompositeImage(*image,CopyCompositeOp,roi_image,
11631 crop_info.x,crop_info.y);
11632 roi_image=DestroyImage(roi_image);
11633 (void) SetImageProgressMonitor(*image,progress_monitor,
11634 (*image)->client_data);
11638 if (command_type != InfoCommand)
11640 XConfigureImageColormap(display,resource_info,windows,*image);
11641 (void) XConfigureImage(display,resource_info,windows,*image,exception);
11643 XCheckRefreshWindows(display,windows);
11644 XInfoWidget(display,windows,text);
11645 (void) XSetFunction(display,windows->image.highlight_context,
11647 state&=(~UpdateRegionState);
11649 XHighlightRectangle(display,windows->image.id,
11650 windows->image.highlight_context,&highlight_info);
11651 XScreenEvent(display,windows,&event);
11652 if (event.xany.window == windows->command.id)
11655 Select a command from the Command widget.
11657 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
11658 command_type=NullCommand;
11659 id=XCommandWidget(display,windows,ApplyMenu,&event);
11662 (void) CopyMagickString(command,ApplyMenu[id],MaxTextExtent);
11663 command_type=ApplyCommands[id];
11664 if (id < ApplyMenus)
11667 Select a command from a pop-up menu.
11669 entry=XMenuWidget(display,windows,ApplyMenu[id],
11670 (const char **) Menus[id],command);
11673 (void) CopyMagickString(command,Menus[id][entry],
11675 command_type=Commands[id][entry];
11679 (void) XSetFunction(display,windows->image.highlight_context,
11681 XHighlightRectangle(display,windows->image.id,
11682 windows->image.highlight_context,&highlight_info);
11683 if (command_type == HelpCommand)
11685 (void) XSetFunction(display,windows->image.highlight_context,
11687 XTextViewWidget(display,resource_info,windows,MagickFalse,
11688 "Help Viewer - Region of Interest",ImageROIHelp);
11689 (void) XSetFunction(display,windows->image.highlight_context,
11693 if (command_type == QuitCommand)
11698 state|=EscapeState;
11702 if (command_type != NullCommand)
11703 state|=UpdateRegionState;
11706 XHighlightRectangle(display,windows->image.id,
11707 windows->image.highlight_context,&highlight_info);
11708 switch (event.type)
11712 x=windows->image.x;
11713 y=windows->image.y;
11714 if (event.xbutton.button != Button1)
11716 if (event.xbutton.window != windows->image.id)
11718 x=windows->image.x+event.xbutton.x;
11719 y=windows->image.y+event.xbutton.y;
11720 if ((x < (int) (roi_info.x+RoiDelta)) &&
11721 (x > (int) (roi_info.x-RoiDelta)) &&
11722 (y < (int) (roi_info.y+RoiDelta)) &&
11723 (y > (int) (roi_info.y-RoiDelta)))
11725 roi_info.x=(ssize_t) (roi_info.x+roi_info.width);
11726 roi_info.y=(ssize_t) (roi_info.y+roi_info.height);
11727 state|=UpdateConfigurationState;
11730 if ((x < (int) (roi_info.x+RoiDelta)) &&
11731 (x > (int) (roi_info.x-RoiDelta)) &&
11732 (y < (int) (roi_info.y+roi_info.height+RoiDelta)) &&
11733 (y > (int) (roi_info.y+roi_info.height-RoiDelta)))
11735 roi_info.x=(ssize_t) (roi_info.x+roi_info.width);
11736 state|=UpdateConfigurationState;
11739 if ((x < (int) (roi_info.x+roi_info.width+RoiDelta)) &&
11740 (x > (int) (roi_info.x+roi_info.width-RoiDelta)) &&
11741 (y < (int) (roi_info.y+RoiDelta)) &&
11742 (y > (int) (roi_info.y-RoiDelta)))
11744 roi_info.y=(ssize_t) (roi_info.y+roi_info.height);
11745 state|=UpdateConfigurationState;
11748 if ((x < (int) (roi_info.x+roi_info.width+RoiDelta)) &&
11749 (x > (int) (roi_info.x+roi_info.width-RoiDelta)) &&
11750 (y < (int) (roi_info.y+roi_info.height+RoiDelta)) &&
11751 (y > (int) (roi_info.y+roi_info.height-RoiDelta)))
11753 state|=UpdateConfigurationState;
11757 case ButtonRelease:
11759 if (event.xbutton.window == windows->pan.id)
11760 if ((highlight_info.x != crop_info.x-windows->image.x) ||
11761 (highlight_info.y != crop_info.y-windows->image.y))
11762 XHighlightRectangle(display,windows->image.id,
11763 windows->image.highlight_context,&highlight_info);
11764 (void) XSetSelectionOwner(display,XA_PRIMARY,windows->image.id,
11765 event.xbutton.time);
11770 if (event.xexpose.window == windows->image.id)
11771 if (event.xexpose.count == 0)
11773 event.xexpose.x=(int) highlight_info.x;
11774 event.xexpose.y=(int) highlight_info.y;
11775 event.xexpose.width=(int) highlight_info.width;
11776 event.xexpose.height=(int) highlight_info.height;
11777 XRefreshWindow(display,&windows->image,&event);
11779 if (event.xexpose.window == windows->info.id)
11780 if (event.xexpose.count == 0)
11781 XInfoWidget(display,windows,text);
11789 if (event.xkey.window != windows->image.id)
11792 Respond to a user key press.
11794 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
11795 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
11796 switch ((int) key_symbol)
11803 state|=EscapeState;
11812 roi_info.x=(ssize_t) (windows->image.width/2L-roi_info.width/2L);
11813 roi_info.y=(ssize_t) (windows->image.height/2L-
11814 roi_info.height/2L);
11846 (void) XSetFunction(display,windows->image.highlight_context,
11848 XTextViewWidget(display,resource_info,windows,MagickFalse,
11849 "Help Viewer - Region of Interest",ImageROIHelp);
11850 (void) XSetFunction(display,windows->image.highlight_context,
11856 command_type=XImageWindowCommand(display,resource_info,windows,
11857 event.xkey.state,key_symbol,image,exception);
11858 if (command_type != NullCommand)
11859 state|=UpdateRegionState;
11863 (void) XSetSelectionOwner(display,XA_PRIMARY,windows->image.id,
11871 if (event.xbutton.window != windows->image.id)
11874 Map and unmap Info widget as text cursor crosses its boundaries.
11878 if (windows->info.mapped != MagickFalse)
11880 if ((x < (int) (windows->info.x+windows->info.width)) &&
11881 (y < (int) (windows->info.y+windows->info.height)))
11882 (void) XWithdrawWindow(display,windows->info.id,
11883 windows->info.screen);
11886 if ((x > (int) (windows->info.x+windows->info.width)) ||
11887 (y > (int) (windows->info.y+windows->info.height)))
11888 (void) XMapWindow(display,windows->info.id);
11889 roi_info.x=(ssize_t) windows->image.x+event.xmotion.x;
11890 roi_info.y=(ssize_t) windows->image.y+event.xmotion.y;
11893 case SelectionRequest:
11898 XSelectionRequestEvent
11902 Set primary selection.
11904 (void) FormatLocaleString(text,MaxTextExtent,
11905 "%.20gx%.20g%+.20g%+.20g",(double) roi_info.width,(double)
11906 roi_info.height,(double) roi_info.x,(double) roi_info.y);
11907 request=(&(event.xselectionrequest));
11908 (void) XChangeProperty(request->display,request->requestor,
11909 request->property,request->target,8,PropModeReplace,
11910 (unsigned char *) text,(int) strlen(text));
11911 notify.type=SelectionNotify;
11912 notify.display=request->display;
11913 notify.requestor=request->requestor;
11914 notify.selection=request->selection;
11915 notify.target=request->target;
11916 notify.time=request->time;
11917 if (request->property == None)
11918 notify.property=request->target;
11920 notify.property=request->property;
11921 (void) XSendEvent(request->display,request->requestor,False,0,
11922 (XEvent *) ¬ify);
11927 if ((state & UpdateConfigurationState) != 0)
11929 (void) XPutBackEvent(display,&event);
11930 (void) XCheckDefineCursor(display,windows->image.id,cursor);
11933 } while ((state & ExitState) == 0);
11934 } while ((state & ExitState) == 0);
11935 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
11936 XSetCursorState(display,windows,MagickFalse);
11937 if ((state & EscapeState) != 0)
11938 return(MagickTrue);
11939 return(MagickTrue);
11943 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
11947 + X R o t a t e I m a g e %
11951 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
11953 % XRotateImage() rotates the X image. If the degrees parameter if zero, the
11954 % rotation angle is computed from the slope of a line drawn by the user.
11956 % The format of the XRotateImage method is:
11958 % MagickBooleanType XRotateImage(Display *display,
11959 % XResourceInfo *resource_info,XWindows *windows,double degrees,
11960 % Image **image,ExceptionInfo *exception)
11962 % A description of each parameter follows:
11964 % o display: Specifies a connection to an X server; returned from
11967 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
11969 % o windows: Specifies a pointer to a XWindows structure.
11971 % o degrees: Specifies the number of degrees to rotate the image.
11973 % o image: the image.
11975 % o exception: return any errors or warnings in this structure.
11978 static MagickBooleanType XRotateImage(Display *display,
11979 XResourceInfo *resource_info,XWindows *windows,double degrees,Image **image,
11980 ExceptionInfo *exception)
11993 direction = HorizontalRotateCommand;
11995 static const ModeType
11996 DirectionCommands[] =
11998 HorizontalRotateCommand,
11999 VerticalRotateCommand
12003 RotateColorCommand,
12004 RotateDirectionCommand,
12006 RotateDismissCommand
12009 static unsigned int
12013 command[MaxTextExtent],
12014 text[MaxTextExtent];
12025 normalized_degrees;
12035 if (degrees == 0.0)
12050 Map Command widget.
12052 (void) CloneString(&windows->command.name,"Rotate");
12053 windows->command.data=2;
12054 (void) XCommandWidget(display,windows,RotateMenu,(XEvent *) NULL);
12055 (void) XMapRaised(display,windows->command.id);
12056 XClientMessage(display,windows->image.id,windows->im_protocols,
12057 windows->im_update_widget,CurrentTime);
12059 Wait for first button press.
12061 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
12062 XQueryPosition(display,windows->image.id,&x,&y);
12067 state=DefaultState;
12070 XHighlightLine(display,windows->image.id,
12071 windows->image.highlight_context,&rotate_info);
12073 Wait for next event.
12075 XScreenEvent(display,windows,&event);
12076 XHighlightLine(display,windows->image.id,
12077 windows->image.highlight_context,&rotate_info);
12078 if (event.xany.window == windows->command.id)
12081 Select a command from the Command widget.
12083 id=XCommandWidget(display,windows,RotateMenu,&event);
12086 (void) XSetFunction(display,windows->image.highlight_context,
12088 switch (RotateCommands[id])
12090 case RotateColorCommand:
12093 *ColorMenu[MaxNumberPens];
12102 Initialize menu selections.
12104 for (i=0; i < (int) (MaxNumberPens-2); i++)
12105 ColorMenu[i]=resource_info->pen_colors[i];
12106 ColorMenu[MaxNumberPens-2]="Browser...";
12107 ColorMenu[MaxNumberPens-1]=(const char *) NULL;
12109 Select a pen color from the pop-up menu.
12111 pen_number=XMenuWidget(display,windows,RotateMenu[id],
12112 (const char **) ColorMenu,command);
12113 if (pen_number < 0)
12115 if (pen_number == (MaxNumberPens-2))
12118 color_name[MaxTextExtent] = "gray";
12121 Select a pen color from a dialog.
12123 resource_info->pen_colors[pen_number]=color_name;
12124 XColorBrowserWidget(display,windows,"Select",color_name);
12125 if (*color_name == '\0')
12131 (void) XParseColor(display,windows->map_info->colormap,
12132 resource_info->pen_colors[pen_number],&color);
12133 XBestPixel(display,windows->map_info->colormap,(XColor *) NULL,
12134 (unsigned int) MaxColors,&color);
12135 windows->pixel_info->pen_colors[pen_number]=color;
12136 pen_id=(unsigned int) pen_number;
12139 case RotateDirectionCommand:
12150 Select a command from the pop-up menu.
12152 id=XMenuWidget(display,windows,RotateMenu[id],
12153 Directions,command);
12155 direction=DirectionCommands[id];
12158 case RotateHelpCommand:
12160 XTextViewWidget(display,resource_info,windows,MagickFalse,
12161 "Help Viewer - Image Rotation",ImageRotateHelp);
12164 case RotateDismissCommand:
12169 state|=EscapeState;
12176 (void) XSetFunction(display,windows->image.highlight_context,
12180 switch (event.type)
12184 if (event.xbutton.button != Button1)
12186 if (event.xbutton.window != windows->image.id)
12191 (void) XSetFunction(display,windows->image.highlight_context,
12193 rotate_info.x1=event.xbutton.x;
12194 rotate_info.y1=event.xbutton.y;
12198 case ButtonRelease:
12205 command[MaxTextExtent];
12210 if (event.xkey.window != windows->image.id)
12213 Respond to a user key press.
12215 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
12216 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
12217 switch ((int) key_symbol)
12225 state|=EscapeState;
12232 (void) XSetFunction(display,windows->image.highlight_context,
12234 XTextViewWidget(display,resource_info,windows,MagickFalse,
12235 "Help Viewer - Image Rotation",ImageRotateHelp);
12236 (void) XSetFunction(display,windows->image.highlight_context,
12242 (void) XBell(display,0);
12250 rotate_info.x1=event.xmotion.x;
12251 rotate_info.y1=event.xmotion.y;
12254 rotate_info.x2=rotate_info.x1;
12255 rotate_info.y2=rotate_info.y1;
12256 if (direction == HorizontalRotateCommand)
12257 rotate_info.x2+=32;
12259 rotate_info.y2-=32;
12260 } while ((state & ExitState) == 0);
12261 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
12262 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
12263 if ((state & EscapeState) != 0)
12264 return(MagickTrue);
12266 Draw line as pointer moves until the mouse button is released.
12269 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
12270 state=DefaultState;
12276 Display info and draw rotation line.
12278 if (windows->info.mapped == MagickFalse)
12279 (void) XMapWindow(display,windows->info.id);
12280 (void) FormatLocaleString(text,MaxTextExtent," %g",
12281 direction == VerticalRotateCommand ? degrees-90.0 : degrees);
12282 XInfoWidget(display,windows,text);
12283 XHighlightLine(display,windows->image.id,
12284 windows->image.highlight_context,&rotate_info);
12287 if (windows->info.mapped != MagickFalse)
12288 (void) XWithdrawWindow(display,windows->info.id,
12289 windows->info.screen);
12291 Wait for next event.
12293 XScreenEvent(display,windows,&event);
12295 XHighlightLine(display,windows->image.id,
12296 windows->image.highlight_context,&rotate_info);
12297 switch (event.type)
12301 case ButtonRelease:
12304 User has committed to rotation line.
12306 rotate_info.x2=event.xbutton.x;
12307 rotate_info.y2=event.xbutton.y;
12315 rotate_info.x2=event.xmotion.x;
12316 rotate_info.y2=event.xmotion.y;
12322 Check boundary conditions.
12324 if (rotate_info.x2 < 0)
12327 if (rotate_info.x2 > (int) windows->image.width)
12328 rotate_info.x2=(short) windows->image.width;
12329 if (rotate_info.y2 < 0)
12332 if (rotate_info.y2 > (int) windows->image.height)
12333 rotate_info.y2=(short) windows->image.height;
12335 Compute rotation angle from the slope of the line.
12338 distance=(unsigned int)
12339 ((rotate_info.x2-rotate_info.x1+1)*(rotate_info.x2-rotate_info.x1+1))+
12340 ((rotate_info.y2-rotate_info.y1+1)*(rotate_info.y2-rotate_info.y1+1));
12342 degrees=RadiansToDegrees(-atan2((double) (rotate_info.y2-
12343 rotate_info.y1),(double) (rotate_info.x2-rotate_info.x1)));
12344 } while ((state & ExitState) == 0);
12345 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
12346 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
12348 return(MagickTrue);
12350 if (direction == VerticalRotateCommand)
12352 if (degrees == 0.0)
12353 return(MagickTrue);
12357 normalized_degrees=degrees;
12358 while (normalized_degrees < -45.0)
12359 normalized_degrees+=360.0;
12360 for (rotations=0; normalized_degrees > 45.0; rotations++)
12361 normalized_degrees-=90.0;
12362 if (normalized_degrees != 0.0)
12363 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image,
12365 XSetCursorState(display,windows,MagickTrue);
12366 XCheckRefreshWindows(display,windows);
12367 (*image)->background_color.red=ScaleShortToQuantum(
12368 windows->pixel_info->pen_colors[pen_id].red);
12369 (*image)->background_color.green=ScaleShortToQuantum(
12370 windows->pixel_info->pen_colors[pen_id].green);
12371 (*image)->background_color.blue=ScaleShortToQuantum(
12372 windows->pixel_info->pen_colors[pen_id].blue);
12373 rotate_image=RotateImage(*image,degrees,exception);
12374 XSetCursorState(display,windows,MagickFalse);
12375 if (rotate_image == (Image *) NULL)
12376 return(MagickFalse);
12377 *image=DestroyImage(*image);
12378 *image=rotate_image;
12379 if (windows->image.crop_geometry != (char *) NULL)
12382 Rotate crop geometry.
12384 width=(unsigned int) (*image)->columns;
12385 height=(unsigned int) (*image)->rows;
12386 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
12387 switch (rotations % 4)
12397 (void) FormatLocaleString(windows->image.crop_geometry,MaxTextExtent,
12398 "%ux%u%+d%+d",height,width,(int) (*image)->columns-
12405 Rotate 180 degrees.
12407 (void) FormatLocaleString(windows->image.crop_geometry,MaxTextExtent,
12408 "%ux%u%+d%+d",width,height,(int) width-x,(int) height-y);
12414 Rotate 270 degrees.
12416 (void) FormatLocaleString(windows->image.crop_geometry,MaxTextExtent,
12417 "%ux%u%+d%+d",height,width,y,(int) (*image)->rows-(int) width-x);
12422 if (windows->image.orphan != MagickFalse)
12423 return(MagickTrue);
12424 if (normalized_degrees != 0.0)
12427 Update image colormap.
12429 windows->image.window_changes.width=(int) (*image)->columns;
12430 windows->image.window_changes.height=(int) (*image)->rows;
12431 if (windows->image.crop_geometry != (char *) NULL)
12434 Obtain dimensions of image from crop geometry.
12436 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,
12438 windows->image.window_changes.width=(int) width;
12439 windows->image.window_changes.height=(int) height;
12441 XConfigureImageColormap(display,resource_info,windows,*image);
12444 if (((rotations % 4) == 1) || ((rotations % 4) == 3))
12446 windows->image.window_changes.width=windows->image.ximage->height;
12447 windows->image.window_changes.height=windows->image.ximage->width;
12450 Update image configuration.
12452 (void) XConfigureImage(display,resource_info,windows,*image,exception);
12453 return(MagickTrue);
12457 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12461 + X S a v e I m a g e %
12465 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12467 % XSaveImage() saves an image to a file.
12469 % The format of the XSaveImage method is:
12471 % MagickBooleanType XSaveImage(Display *display,
12472 % XResourceInfo *resource_info,XWindows *windows,Image *image,
12473 % ExceptionInfo *exception)
12475 % A description of each parameter follows:
12477 % o display: Specifies a connection to an X server; returned from
12480 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
12482 % o windows: Specifies a pointer to a XWindows structure.
12484 % o image: the image.
12486 % o exception: return any errors or warnings in this structure.
12489 static MagickBooleanType XSaveImage(Display *display,
12490 XResourceInfo *resource_info,XWindows *windows,Image *image,
12491 ExceptionInfo *exception)
12494 filename[MaxTextExtent],
12495 geometry[MaxTextExtent];
12507 Request file name from user.
12509 if (resource_info->write_filename != (char *) NULL)
12510 (void) CopyMagickString(filename,resource_info->write_filename,
12515 path[MaxTextExtent];
12520 GetPathComponent(image->filename,HeadPath,path);
12521 GetPathComponent(image->filename,TailPath,filename);
12524 status=chdir(path);
12526 (void) ThrowMagickException(exception,GetMagickModule(),
12527 FileOpenError,"UnableToOpenFile","%s",path);
12530 XFileBrowserWidget(display,windows,"Save",filename);
12531 if (*filename == '\0')
12532 return(MagickTrue);
12533 if (IsPathAccessible(filename) != MagickFalse)
12539 File exists-- seek user's permission before overwriting.
12541 status=XConfirmWidget(display,windows,"Overwrite",filename);
12543 return(MagickTrue);
12545 image_info=CloneImageInfo(resource_info->image_info);
12546 (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
12547 (void) SetImageInfo(image_info,1,exception);
12548 if ((LocaleCompare(image_info->magick,"JPEG") == 0) ||
12549 (LocaleCompare(image_info->magick,"JPG") == 0))
12552 quality[MaxTextExtent];
12558 Request JPEG quality from user.
12560 (void) FormatLocaleString(quality,MaxTextExtent,"%.20g",(double)
12562 status=XDialogWidget(display,windows,"Save","Enter JPEG quality:",
12564 if (*quality == '\0')
12565 return(MagickTrue);
12566 image->quality=StringToUnsignedLong(quality);
12567 image_info->interlace=status != 0 ? NoInterlace : PlaneInterlace;
12569 if ((LocaleCompare(image_info->magick,"EPS") == 0) ||
12570 (LocaleCompare(image_info->magick,"PDF") == 0) ||
12571 (LocaleCompare(image_info->magick,"PS") == 0) ||
12572 (LocaleCompare(image_info->magick,"PS2") == 0))
12575 geometry[MaxTextExtent];
12578 Request page geometry from user.
12580 (void) CopyMagickString(geometry,PSPageGeometry,MaxTextExtent);
12581 if (LocaleCompare(image_info->magick,"PDF") == 0)
12582 (void) CopyMagickString(geometry,PSPageGeometry,MaxTextExtent);
12583 if (image_info->page != (char *) NULL)
12584 (void) CopyMagickString(geometry,image_info->page,MaxTextExtent);
12585 XListBrowserWidget(display,windows,&windows->widget,PageSizes,"Select",
12586 "Select page geometry:",geometry);
12587 if (*geometry != '\0')
12588 image_info->page=GetPageGeometry(geometry);
12591 Apply image transforms.
12593 XSetCursorState(display,windows,MagickTrue);
12594 XCheckRefreshWindows(display,windows);
12595 save_image=CloneImage(image,0,0,MagickTrue,exception);
12596 if (save_image == (Image *) NULL)
12597 return(MagickFalse);
12598 (void) FormatLocaleString(geometry,MaxTextExtent,"%dx%d!",
12599 windows->image.ximage->width,windows->image.ximage->height);
12600 (void) TransformImage(&save_image,windows->image.crop_geometry,geometry);
12604 (void) CopyMagickString(save_image->filename,filename,MaxTextExtent);
12605 status=WriteImage(image_info,save_image,exception);
12606 if (status != MagickFalse)
12607 image->taint=MagickFalse;
12608 save_image=DestroyImage(save_image);
12609 image_info=DestroyImageInfo(image_info);
12610 XSetCursorState(display,windows,MagickFalse);
12611 return(status != 0 ? MagickTrue : MagickFalse);
12615 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12619 + X S c r e e n E v e n t %
12623 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12625 % XScreenEvent() handles global events associated with the Pan and Magnify
12628 % The format of the XScreenEvent function is:
12630 % void XScreenEvent(Display *display,XWindows *windows,XEvent *event)
12632 % A description of each parameter follows:
12634 % o display: Specifies a pointer to the Display structure; returned from
12637 % o windows: Specifies a pointer to a XWindows structure.
12639 % o event: Specifies a pointer to a X11 XEvent structure.
12644 #if defined(__cplusplus) || defined(c_plusplus)
12648 static int XPredicate(Display *magick_unused(display),XEvent *event,char *data)
12653 windows=(XWindows *) data;
12654 if ((event->type == ClientMessage) &&
12655 (event->xclient.window == windows->image.id))
12656 return(MagickFalse);
12657 return(MagickTrue);
12660 #if defined(__cplusplus) || defined(c_plusplus)
12664 static void XScreenEvent(Display *display,XWindows *windows,XEvent *event)
12670 (void) XIfEvent(display,event,XPredicate,(char *) windows);
12671 if (event->xany.window == windows->command.id)
12673 switch (event->type)
12676 case ButtonRelease:
12678 if ((event->xbutton.button == Button3) &&
12679 (event->xbutton.state & Mod1Mask))
12682 Convert Alt-Button3 to Button2.
12684 event->xbutton.button=Button2;
12685 event->xbutton.state&=(~Mod1Mask);
12687 if (event->xbutton.window == windows->backdrop.id)
12689 (void) XSetInputFocus(display,event->xbutton.window,RevertToParent,
12690 event->xbutton.time);
12693 if (event->xbutton.window == windows->pan.id)
12695 XPanImage(display,windows,event);
12698 if (event->xbutton.window == windows->image.id)
12699 if (event->xbutton.button == Button2)
12702 Update magnified image.
12704 x=event->xbutton.x;
12705 y=event->xbutton.y;
12709 if (x >= (int) windows->image.width)
12710 x=(int) (windows->image.width-1);
12711 windows->magnify.x=(int) windows->image.x+x;
12715 if (y >= (int) windows->image.height)
12716 y=(int) (windows->image.height-1);
12717 windows->magnify.y=windows->image.y+y;
12718 if (windows->magnify.mapped == MagickFalse)
12719 (void) XMapRaised(display,windows->magnify.id);
12720 XMakeMagnifyImage(display,windows);
12721 if (event->type == ButtonRelease)
12722 (void) XWithdrawWindow(display,windows->info.id,
12723 windows->info.screen);
12728 case ClientMessage:
12731 If client window delete message, exit.
12733 if (event->xclient.message_type != windows->wm_protocols)
12735 if (*event->xclient.data.l != (long) windows->wm_delete_window)
12737 if (event->xclient.window == windows->magnify.id)
12739 (void) XWithdrawWindow(display,windows->magnify.id,
12740 windows->magnify.screen);
12745 case ConfigureNotify:
12747 if (event->xconfigure.window == windows->magnify.id)
12753 Magnify window has a new configuration.
12755 windows->magnify.width=(unsigned int) event->xconfigure.width;
12756 windows->magnify.height=(unsigned int) event->xconfigure.height;
12757 if (windows->magnify.mapped == MagickFalse)
12760 while ((int) magnify <= event->xconfigure.width)
12762 while ((int) magnify <= event->xconfigure.height)
12765 if (((int) magnify != event->xconfigure.width) ||
12766 ((int) magnify != event->xconfigure.height))
12771 window_changes.width=(int) magnify;
12772 window_changes.height=(int) magnify;
12773 (void) XReconfigureWMWindow(display,windows->magnify.id,
12774 windows->magnify.screen,(unsigned int) (CWWidth | CWHeight),
12778 XMakeMagnifyImage(display,windows);
12785 if (event->xexpose.window == windows->image.id)
12787 XRefreshWindow(display,&windows->image,event);
12790 if (event->xexpose.window == windows->pan.id)
12791 if (event->xexpose.count == 0)
12793 XDrawPanRectangle(display,windows);
12796 if (event->xexpose.window == windows->magnify.id)
12797 if (event->xexpose.count == 0)
12799 XMakeMagnifyImage(display,windows);
12807 command[MaxTextExtent];
12812 if (event->xkey.window != windows->magnify.id)
12815 Respond to a user key press.
12817 (void) XLookupString((XKeyEvent *) &event->xkey,command,(int)
12818 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
12819 XMagnifyWindowCommand(display,windows,event->xkey.state,key_symbol);
12824 if (event->xmap.window == windows->magnify.id)
12826 windows->magnify.mapped=MagickTrue;
12827 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
12830 if (event->xmap.window == windows->info.id)
12832 windows->info.mapped=MagickTrue;
12839 while (XCheckMaskEvent(display,ButtonMotionMask,event)) ;
12840 if (event->xmotion.window == windows->image.id)
12841 if (windows->magnify.mapped != MagickFalse)
12844 Update magnified image.
12846 x=event->xmotion.x;
12847 y=event->xmotion.y;
12851 if (x >= (int) windows->image.width)
12852 x=(int) (windows->image.width-1);
12853 windows->magnify.x=(int) windows->image.x+x;
12857 if (y >= (int) windows->image.height)
12858 y=(int) (windows->image.height-1);
12859 windows->magnify.y=windows->image.y+y;
12860 XMakeMagnifyImage(display,windows);
12866 if (event->xunmap.window == windows->magnify.id)
12868 windows->magnify.mapped=MagickFalse;
12871 if (event->xunmap.window == windows->info.id)
12873 windows->info.mapped=MagickFalse;
12884 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12888 + X S e t C r o p G e o m e t r y %
12892 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12894 % XSetCropGeometry() accepts a cropping geometry relative to the Image window
12895 % and translates it to a cropping geometry relative to the image.
12897 % The format of the XSetCropGeometry method is:
12899 % void XSetCropGeometry(Display *display,XWindows *windows,
12900 % RectangleInfo *crop_info,Image *image)
12902 % A description of each parameter follows:
12904 % o display: Specifies a connection to an X server; returned from
12907 % o windows: Specifies a pointer to a XWindows structure.
12909 % o crop_info: A pointer to a RectangleInfo that defines a region of the
12910 % Image window to crop.
12912 % o image: the image.
12915 static void XSetCropGeometry(Display *display,XWindows *windows,
12916 RectangleInfo *crop_info,Image *image)
12919 text[MaxTextExtent];
12932 if (windows->info.mapped != MagickFalse)
12935 Display info on cropping rectangle.
12937 (void) FormatLocaleString(text,MaxTextExtent," %.20gx%.20g%+.20g%+.20g",
12938 (double) crop_info->width,(double) crop_info->height,(double)
12939 crop_info->x,(double) crop_info->y);
12940 XInfoWidget(display,windows,text);
12943 Cropping geometry is relative to any previous crop geometry.
12947 width=(unsigned int) image->columns;
12948 height=(unsigned int) image->rows;
12949 if (windows->image.crop_geometry != (char *) NULL)
12950 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
12952 windows->image.crop_geometry=AcquireString((char *) NULL);
12954 Define the crop geometry string from the cropping rectangle.
12956 scale_factor=(MagickRealType) width/windows->image.ximage->width;
12957 if (crop_info->x > 0)
12958 x+=(int) (scale_factor*crop_info->x+0.5);
12959 width=(unsigned int) (scale_factor*crop_info->width+0.5);
12962 scale_factor=(MagickRealType) height/windows->image.ximage->height;
12963 if (crop_info->y > 0)
12964 y+=(int) (scale_factor*crop_info->y+0.5);
12965 height=(unsigned int) (scale_factor*crop_info->height+0.5);
12968 (void) FormatLocaleString(windows->image.crop_geometry,MaxTextExtent,
12969 "%ux%u%+d%+d",width,height,x,y);
12973 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12977 + X T i l e I m a g e %
12981 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12983 % XTileImage() loads or deletes a selected tile from a visual image directory.
12984 % The load or delete command is chosen from a menu.
12986 % The format of the XTileImage method is:
12988 % Image *XTileImage(Display *display,XResourceInfo *resource_info,
12989 % XWindows *windows,Image *image,XEvent *event,ExceptionInfo *exception)
12991 % A description of each parameter follows:
12993 % o tile_image: XTileImage reads or deletes the tile image
12994 % and returns it. A null image is returned if an error occurs.
12996 % o display: Specifies a connection to an X server; returned from
12999 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
13001 % o windows: Specifies a pointer to a XWindows structure.
13003 % o image: the image; returned from ReadImage.
13005 % o event: Specifies a pointer to a XEvent structure. If it is NULL,
13006 % the entire image is refreshed.
13008 % o exception: return any errors or warnings in this structure.
13011 static Image *XTileImage(Display *display,XResourceInfo *resource_info,
13012 XWindows *windows,Image *image,XEvent *event,ExceptionInfo *exception)
13025 static const ModeType
13036 command[MaxTextExtent],
13037 filename[MaxTextExtent];
13064 Tile image is relative to montage image configuration.
13068 width=(unsigned int) image->columns;
13069 height=(unsigned int) image->rows;
13070 if (windows->image.crop_geometry != (char *) NULL)
13071 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
13072 scale_factor=(MagickRealType) width/windows->image.ximage->width;
13073 event->xbutton.x+=windows->image.x;
13074 event->xbutton.x=(int) (scale_factor*event->xbutton.x+x+0.5);
13075 scale_factor=(MagickRealType) height/windows->image.ximage->height;
13076 event->xbutton.y+=windows->image.y;
13077 event->xbutton.y=(int) (scale_factor*event->xbutton.y+y+0.5);
13079 Determine size and location of each tile in the visual image directory.
13081 width=(unsigned int) image->columns;
13082 height=(unsigned int) image->rows;
13085 (void) XParseGeometry(image->montage,&x,&y,&width,&height);
13086 tile=((event->xbutton.y-y)/height)*(((int) image->columns-x)/width)+
13087 (event->xbutton.x-x)/width;
13091 Button press is outside any tile.
13093 (void) XBell(display,0);
13094 return((Image *) NULL);
13097 Determine file name from the tile directory.
13099 p=image->directory;
13100 for (i=tile; (i != 0) && (*p != '\0'); )
13109 Button press is outside any tile.
13111 (void) XBell(display,0);
13112 return((Image *) NULL);
13115 Select a command from the pop-up menu.
13117 id=XMenuWidget(display,windows,"Tile Verb",VerbMenu,command);
13119 return((Image *) NULL);
13121 while ((*q != '\n') && (*q != '\0'))
13123 (void) CopyMagickString(filename,p,(size_t) (q-p+1));
13125 Perform command for the selected tile.
13127 XSetCursorState(display,windows,MagickTrue);
13128 XCheckRefreshWindows(display,windows);
13129 tile_image=NewImageList();
13130 switch (TileCommands[id])
13132 case TileLoadCommand:
13137 XCheckRefreshWindows(display,windows);
13138 (void) CopyMagickString(resource_info->image_info->magick,"MIFF",
13140 (void) CopyMagickString(resource_info->image_info->filename,filename,
13142 tile_image=ReadImage(resource_info->image_info,exception);
13143 CatchException(exception);
13144 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
13147 case TileNextCommand:
13150 Display next image.
13152 XClientMessage(display,windows->image.id,windows->im_protocols,
13153 windows->im_next_image,CurrentTime);
13156 case TileFormerCommand:
13159 Display former image.
13161 XClientMessage(display,windows->image.id,windows->im_protocols,
13162 windows->im_former_image,CurrentTime);
13165 case TileDeleteCommand:
13170 if (IsPathAccessible(filename) == MagickFalse)
13172 XNoticeWidget(display,windows,"Image file does not exist:",filename);
13175 status=XConfirmWidget(display,windows,"Really delete tile",filename);
13178 status=remove(filename) != 0 ? MagickTrue : MagickFalse;
13179 if (status != MagickFalse)
13181 XNoticeWidget(display,windows,"Unable to delete image file:",
13186 case TileUpdateCommand:
13202 Ensure all the images exist.
13205 for (p=image->directory; *p != '\0'; p++)
13211 while ((*q != '\n') && (*q != '\0'))
13213 (void) CopyMagickString(filename,p,(size_t) (q-p+1));
13215 if (IsPathAccessible(filename) != MagickFalse)
13221 Overwrite tile with background color.
13223 x_offset=(int) (width*(tile % (((int) image->columns-x)/width))+x);
13224 y_offset=(int) (height*(tile/(((int) image->columns-x)/width))+y);
13225 image_view=AcquireCacheView(image);
13226 (void) GetOneCacheViewVirtualPixel(image_view,0,0,&pixel,exception);
13227 for (i=0; i < (int) height; i++)
13229 s=GetCacheViewAuthenticPixels(image_view,(ssize_t) x_offset,(ssize_t)
13230 y_offset+i,width,1,exception);
13231 if (s == (Quantum *) NULL)
13233 for (j=0; j < (int) width; j++)
13235 SetPixelPacket(image,&pixel,s);
13236 s+=GetPixelChannels(image);
13238 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
13241 image_view=DestroyCacheView(image_view);
13244 windows->image.window_changes.width=(int) image->columns;
13245 windows->image.window_changes.height=(int) image->rows;
13246 XConfigureImageColormap(display,resource_info,windows,image);
13247 (void) XConfigureImage(display,resource_info,windows,image,exception);
13253 XSetCursorState(display,windows,MagickFalse);
13254 return(tile_image);
13258 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13262 + X T r a n s l a t e I m a g e %
13266 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13268 % XTranslateImage() translates the image within an Image window by one pixel
13269 % as specified by the key symbol. If the image has a `montage string the
13270 % translation is respect to the width and height contained within the string.
13272 % The format of the XTranslateImage method is:
13274 % void XTranslateImage(Display *display,XWindows *windows,
13275 % Image *image,const KeySym key_symbol)
13277 % A description of each parameter follows:
13279 % o display: Specifies a connection to an X server; returned from
13282 % o windows: Specifies a pointer to a XWindows structure.
13284 % o image: the image.
13286 % o key_symbol: Specifies a KeySym which indicates which side of the image
13290 static void XTranslateImage(Display *display,XWindows *windows,
13291 Image *image,const KeySym key_symbol)
13294 text[MaxTextExtent];
13305 User specified a pan position offset.
13307 x_offset=windows->image.width;
13308 y_offset=windows->image.height;
13309 if (image->montage != (char *) NULL)
13310 (void) XParseGeometry(image->montage,&x,&y,&x_offset,&y_offset);
13311 switch ((int) key_symbol)
13316 windows->image.x=(int) windows->image.width/2;
13317 windows->image.y=(int) windows->image.height/2;
13323 windows->image.x-=x_offset;
13330 windows->image.y-=y_offset;
13336 windows->image.x+=x_offset;
13343 windows->image.y+=y_offset;
13350 Check boundary conditions.
13352 if (windows->image.x < 0)
13353 windows->image.x=0;
13355 if ((int) (windows->image.x+windows->image.width) >
13356 windows->image.ximage->width)
13357 windows->image.x=(int) windows->image.ximage->width-windows->image.width;
13358 if (windows->image.y < 0)
13359 windows->image.y=0;
13361 if ((int) (windows->image.y+windows->image.height) >
13362 windows->image.ximage->height)
13363 windows->image.y=(int) windows->image.ximage->height-windows->image.height;
13365 Refresh Image window.
13367 (void) FormatLocaleString(text,MaxTextExtent," %ux%u%+d%+d ",
13368 windows->image.width,windows->image.height,windows->image.x,
13370 XInfoWidget(display,windows,text);
13371 XCheckRefreshWindows(display,windows);
13372 XDrawPanRectangle(display,windows);
13373 XRefreshWindow(display,&windows->image,(XEvent *) NULL);
13374 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
13378 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13382 + X T r i m I m a g e %
13386 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13388 % XTrimImage() trims the edges from the Image window.
13390 % The format of the XTrimImage method is:
13392 % MagickBooleanType XTrimImage(Display *display,
13393 % XResourceInfo *resource_info,XWindows *windows,Image *image,
13394 % ExceptionInfo *exception)
13396 % A description of each parameter follows:
13398 % o display: Specifies a connection to an X server; returned from
13401 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
13403 % o windows: Specifies a pointer to a XWindows structure.
13405 % o image: the image.
13407 % o exception: return any errors or warnings in this structure.
13410 static MagickBooleanType XTrimImage(Display *display,
13411 XResourceInfo *resource_info,XWindows *windows,Image *image,
13412 ExceptionInfo *exception)
13426 Trim edges from image.
13428 XSetCursorState(display,windows,MagickTrue);
13429 XCheckRefreshWindows(display,windows);
13431 Crop the left edge.
13433 background=XGetPixel(windows->image.ximage,0,0);
13434 trim_info.width=(size_t) windows->image.ximage->width;
13435 for (x=0; x < windows->image.ximage->width; x++)
13437 for (y=0; y < windows->image.ximage->height; y++)
13439 pixel=XGetPixel(windows->image.ximage,x,y);
13440 if (pixel != background)
13443 if (y < windows->image.ximage->height)
13446 trim_info.x=(ssize_t) x;
13447 if (trim_info.x == (ssize_t) windows->image.ximage->width)
13449 XSetCursorState(display,windows,MagickFalse);
13450 return(MagickFalse);
13453 Crop the right edge.
13455 background=XGetPixel(windows->image.ximage,windows->image.ximage->width-1,0);
13456 for (x=windows->image.ximage->width-1; x != 0; x--)
13458 for (y=0; y < windows->image.ximage->height; y++)
13460 pixel=XGetPixel(windows->image.ximage,x,y);
13461 if (pixel != background)
13464 if (y < windows->image.ximage->height)
13467 trim_info.width=(size_t) (x-trim_info.x+1);
13471 background=XGetPixel(windows->image.ximage,0,0);
13472 trim_info.height=(size_t) windows->image.ximage->height;
13473 for (y=0; y < windows->image.ximage->height; y++)
13475 for (x=0; x < windows->image.ximage->width; x++)
13477 pixel=XGetPixel(windows->image.ximage,x,y);
13478 if (pixel != background)
13481 if (x < windows->image.ximage->width)
13484 trim_info.y=(ssize_t) y;
13486 Crop the bottom edge.
13488 background=XGetPixel(windows->image.ximage,0,windows->image.ximage->height-1);
13489 for (y=windows->image.ximage->height-1; y != 0; y--)
13491 for (x=0; x < windows->image.ximage->width; x++)
13493 pixel=XGetPixel(windows->image.ximage,x,y);
13494 if (pixel != background)
13497 if (x < windows->image.ximage->width)
13500 trim_info.height=(size_t) y-trim_info.y+1;
13501 if (((unsigned int) trim_info.width != windows->image.width) ||
13502 ((unsigned int) trim_info.height != windows->image.height))
13505 Reconfigure Image window as defined by the trimming rectangle.
13507 XSetCropGeometry(display,windows,&trim_info,image);
13508 windows->image.window_changes.width=(int) trim_info.width;
13509 windows->image.window_changes.height=(int) trim_info.height;
13510 (void) XConfigureImage(display,resource_info,windows,image,exception);
13512 XSetCursorState(display,windows,MagickFalse);
13513 return(MagickTrue);
13517 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13521 + X V i s u a l D i r e c t o r y I m a g e %
13525 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13527 % XVisualDirectoryImage() creates a Visual Image Directory.
13529 % The format of the XVisualDirectoryImage method is:
13531 % Image *XVisualDirectoryImage(Display *display,
13532 % XResourceInfo *resource_info,XWindows *windows,
13533 % ExceptionInfo *exception)
13535 % A description of each parameter follows:
13537 % o display: Specifies a connection to an X server; returned from
13540 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
13542 % o windows: Specifies a pointer to a XWindows structure.
13544 % o exception: return any errors or warnings in this structure.
13547 static Image *XVisualDirectoryImage(Display *display,
13548 XResourceInfo *resource_info,XWindows *windows,ExceptionInfo *exception)
13550 #define TileImageTag "Scale/Image"
13551 #define XClientName "montage"
13584 filename[MaxTextExtent] = "\0",
13585 filenames[MaxTextExtent] = "*";
13588 background_resources;
13591 Request file name from user.
13593 XFileBrowserWidget(display,windows,"Directory",filenames);
13594 if (*filenames == '\0')
13595 return((Image *) NULL);
13597 Expand the filenames.
13599 filelist=(char **) AcquireMagickMemory(sizeof(*filelist));
13600 if (filelist == (char **) NULL)
13602 ThrowXWindowFatalException(ResourceLimitError,"MemoryAllocationFailed",
13604 return((Image *) NULL);
13607 filelist[0]=filenames;
13608 status=ExpandFilenames(&number_files,&filelist);
13609 if ((status == MagickFalse) || (number_files == 0))
13611 if (number_files == 0)
13612 ThrowXWindowFatalException(ImageError,"NoImagesWereFound",filenames)
13614 ThrowXWindowFatalException(ResourceLimitError,"MemoryAllocationFailed",
13616 return((Image *) NULL);
13619 Set image background resources.
13621 background_resources=(*resource_info);
13622 background_resources.window_id=AcquireString("");
13623 (void) FormatLocaleString(background_resources.window_id,MaxTextExtent,
13624 "0x%lx",windows->image.id);
13625 background_resources.backdrop=MagickTrue;
13627 Read each image and convert them to a tile.
13629 backdrop=(windows->visual_info->klass == TrueColor) ||
13630 (windows->visual_info->klass == DirectColor) ? MagickTrue : MagickFalse;
13631 read_info=CloneImageInfo(resource_info->image_info);
13632 (void) SetImageOption(read_info,"jpeg:size","120x120");
13633 (void) CloneString(&read_info->size,DefaultTileGeometry);
13634 (void) SetImageInfoProgressMonitor(read_info,(MagickProgressMonitor) NULL,
13636 images=NewImageList();
13637 XSetCursorState(display,windows,MagickTrue);
13638 XCheckRefreshWindows(display,windows);
13639 for (i=0; i < (int) number_files; i++)
13641 (void) CopyMagickString(read_info->filename,filelist[i],MaxTextExtent);
13642 filelist[i]=DestroyString(filelist[i]);
13643 *read_info->magick='\0';
13644 next_image=ReadImage(read_info,exception);
13645 CatchException(exception);
13646 if (next_image != (Image *) NULL)
13648 (void) DeleteImageProperty(next_image,"label");
13649 (void) SetImageProperty(next_image,"label",InterpretImageProperties(
13650 read_info,next_image,DefaultTileLabel,exception));
13651 (void) ParseRegionGeometry(next_image,read_info->size,&geometry,
13653 thumbnail_image=ThumbnailImage(next_image,geometry.width,
13654 geometry.height,exception);
13655 if (thumbnail_image != (Image *) NULL)
13657 next_image=DestroyImage(next_image);
13658 next_image=thumbnail_image;
13662 (void) XDisplayBackgroundImage(display,&background_resources,
13663 next_image,exception);
13664 XSetCursorState(display,windows,MagickTrue);
13666 AppendImageToList(&images,next_image);
13667 if (images->progress_monitor != (MagickProgressMonitor) NULL)
13672 proceed=SetImageProgress(images,LoadImageTag,(MagickOffsetType) i,
13673 (MagickSizeType) number_files);
13674 if (proceed == MagickFalse)
13679 filelist=(char **) RelinquishMagickMemory(filelist);
13680 if (images == (Image *) NULL)
13682 read_info=DestroyImageInfo(read_info);
13683 XSetCursorState(display,windows,MagickFalse);
13684 ThrowXWindowFatalException(ImageError,"NoImagesWereLoaded",filenames);
13685 return((Image *) NULL);
13688 Create the Visual Image Directory.
13690 montage_info=CloneMontageInfo(read_info,(MontageInfo *) NULL);
13691 montage_info->pointsize=10;
13692 if (resource_info->font != (char *) NULL)
13693 (void) CloneString(&montage_info->font,resource_info->font);
13694 (void) CopyMagickString(montage_info->filename,filename,MaxTextExtent);
13695 montage_image=MontageImageList(read_info,montage_info,GetFirstImageInList(
13696 images),exception);
13697 images=DestroyImageList(images);
13698 montage_info=DestroyMontageInfo(montage_info);
13699 read_info=DestroyImageInfo(read_info);
13700 XSetCursorState(display,windows,MagickFalse);
13701 if (montage_image == (Image *) NULL)
13702 return(montage_image);
13703 XClientMessage(display,windows->image.id,windows->im_protocols,
13704 windows->im_next_image,CurrentTime);
13705 return(montage_image);
13709 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13713 % X D i s p l a y B a c k g r o u n d I m a g e %
13717 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13719 % XDisplayBackgroundImage() displays an image in the background of a window.
13721 % The format of the XDisplayBackgroundImage method is:
13723 % MagickBooleanType XDisplayBackgroundImage(Display *display,
13724 % XResourceInfo *resource_info,Image *image,ExceptionInfo *exception)
13726 % A description of each parameter follows:
13728 % o display: Specifies a connection to an X server; returned from
13731 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
13733 % o image: the image.
13735 % o exception: return any errors or warnings in this structure.
13738 MagickExport MagickBooleanType XDisplayBackgroundImage(Display *display,
13739 XResourceInfo *resource_info,Image *image,ExceptionInfo *exception)
13742 geometry[MaxTextExtent],
13743 visual_type[MaxTextExtent];
13756 static XStandardColormap
13760 *visual_info = (XVisualInfo *) NULL;
13781 Determine target window.
13783 assert(image != (Image *) NULL);
13784 assert(image->signature == MagickSignature);
13785 if (image->debug != MagickFalse)
13786 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
13787 resources=(*resource_info);
13788 window_info.id=(Window) NULL;
13789 root_window=XRootWindow(display,XDefaultScreen(display));
13790 if (LocaleCompare(resources.window_id,"root") == 0)
13791 window_info.id=root_window;
13794 if (isdigit((unsigned char) *resources.window_id) != 0)
13795 window_info.id=XWindowByID(display,root_window,
13796 (Window) strtol((char *) resources.window_id,(char **) NULL,0));
13797 if (window_info.id == (Window) NULL)
13798 window_info.id=XWindowByName(display,root_window,resources.window_id);
13800 if (window_info.id == (Window) NULL)
13802 ThrowXWindowFatalException(XServerError,"NoWindowWithSpecifiedIDExists",
13803 resources.window_id);
13804 return(MagickFalse);
13807 Determine window visual id.
13809 window_attributes.width=XDisplayWidth(display,XDefaultScreen(display));
13810 window_attributes.height=XDisplayHeight(display,XDefaultScreen(display));
13811 (void) CopyMagickString(visual_type,"default",MaxTextExtent);
13812 status=XGetWindowAttributes(display,window_info.id,&window_attributes);
13814 (void) FormatLocaleString(visual_type,MaxTextExtent,"0x%lx",
13815 XVisualIDFromVisual(window_attributes.visual));
13816 if (visual_info == (XVisualInfo *) NULL)
13819 Allocate standard colormap.
13821 map_info=XAllocStandardColormap();
13822 if (map_info == (XStandardColormap *) NULL)
13823 ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
13825 map_info->colormap=(Colormap) NULL;
13826 pixel.pixels=(unsigned long *) NULL;
13828 Initialize visual info.
13830 resources.map_type=(char *) NULL;
13831 resources.visual_type=visual_type;
13832 visual_info=XBestVisualInfo(display,map_info,&resources);
13833 if (visual_info == (XVisualInfo *) NULL)
13834 ThrowXWindowFatalException(XServerFatalError,"UnableToGetVisual",
13835 resources.visual_type);
13837 Initialize window info.
13839 window_info.ximage=(XImage *) NULL;
13840 window_info.matte_image=(XImage *) NULL;
13841 window_info.pixmap=(Pixmap) NULL;
13842 window_info.matte_pixmap=(Pixmap) NULL;
13845 Free previous root colors.
13847 if (window_info.id == root_window)
13848 (void) XDestroyWindowColors(display,root_window);
13850 Initialize Standard Colormap.
13852 resources.colormap=SharedColormap;
13853 XMakeStandardColormap(display,visual_info,&resources,image,map_info,&pixel);
13855 Graphic context superclass.
13857 context_values.background=pixel.background_color.pixel;
13858 context_values.foreground=pixel.foreground_color.pixel;
13859 pixel.annotate_context=XCreateGC(display,window_info.id,
13860 (size_t) (GCBackground | GCForeground),&context_values);
13861 if (pixel.annotate_context == (GC) NULL)
13862 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
13865 Initialize Image window attributes.
13867 window_info.name=AcquireString("\0");
13868 window_info.icon_name=AcquireString("\0");
13869 XGetWindowInfo(display,visual_info,map_info,&pixel,(XFontStruct *) NULL,
13870 &resources,&window_info);
13872 Create the X image.
13874 window_info.width=(unsigned int) image->columns;
13875 window_info.height=(unsigned int) image->rows;
13876 if ((image->columns != window_info.width) ||
13877 (image->rows != window_info.height))
13878 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
13880 (void) FormatLocaleString(geometry,MaxTextExtent,"%ux%u+0+0>",
13881 window_attributes.width,window_attributes.height);
13882 geometry_info.width=window_info.width;
13883 geometry_info.height=window_info.height;
13884 geometry_info.x=(ssize_t) window_info.x;
13885 geometry_info.y=(ssize_t) window_info.y;
13886 (void) ParseMetaGeometry(geometry,&geometry_info.x,&geometry_info.y,
13887 &geometry_info.width,&geometry_info.height);
13888 window_info.width=(unsigned int) geometry_info.width;
13889 window_info.height=(unsigned int) geometry_info.height;
13890 window_info.x=(int) geometry_info.x;
13891 window_info.y=(int) geometry_info.y;
13892 status=XMakeImage(display,&resources,&window_info,image,window_info.width,
13893 window_info.height,exception);
13894 if (status == MagickFalse)
13895 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
13899 if (image->debug != MagickFalse)
13901 (void) LogMagickEvent(X11Event,GetMagickModule(),
13902 "Image: %s[%.20g] %.20gx%.20g ",image->filename,(double) image->scene,
13903 (double) image->columns,(double) image->rows);
13904 if (image->colors != 0)
13905 (void) LogMagickEvent(X11Event,GetMagickModule(),"%.20gc ",(double)
13907 (void) LogMagickEvent(X11Event,GetMagickModule(),"%s",image->magick);
13910 Adjust image dimensions as specified by backdrop or geometry options.
13912 width=(int) window_info.width;
13913 height=(int) window_info.height;
13914 if (resources.backdrop != MagickFalse)
13917 Center image on window.
13919 window_info.x=(window_attributes.width/2)-
13920 (window_info.ximage->width/2);
13921 window_info.y=(window_attributes.height/2)-
13922 (window_info.ximage->height/2);
13923 width=window_attributes.width;
13924 height=window_attributes.height;
13926 if ((resources.image_geometry != (char *) NULL) &&
13927 (*resources.image_geometry != '\0'))
13930 default_geometry[MaxTextExtent];
13940 User specified geometry.
13942 size_hints=XAllocSizeHints();
13943 if (size_hints == (XSizeHints *) NULL)
13944 ThrowXWindowFatalException(ResourceLimitFatalError,
13945 "MemoryAllocationFailed",image->filename);
13946 size_hints->flags=0L;
13947 (void) FormatLocaleString(default_geometry,MaxTextExtent,"%dx%d",
13949 flags=XWMGeometry(display,visual_info->screen,resources.image_geometry,
13950 default_geometry,window_info.border_width,size_hints,&window_info.x,
13951 &window_info.y,&width,&height,&gravity);
13952 if (flags & (XValue | YValue))
13954 width=window_attributes.width;
13955 height=window_attributes.height;
13957 (void) XFree((void *) size_hints);
13960 Create the X pixmap.
13962 window_info.pixmap=XCreatePixmap(display,window_info.id,(unsigned int) width,
13963 (unsigned int) height,window_info.depth);
13964 if (window_info.pixmap == (Pixmap) NULL)
13965 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXPixmap",
13968 Display pixmap on the window.
13970 if (((unsigned int) width > window_info.width) ||
13971 ((unsigned int) height > window_info.height))
13972 (void) XFillRectangle(display,window_info.pixmap,
13973 window_info.annotate_context,0,0,(unsigned int) width,
13974 (unsigned int) height);
13975 (void) XPutImage(display,window_info.pixmap,window_info.annotate_context,
13976 window_info.ximage,0,0,window_info.x,window_info.y,(unsigned int)
13977 window_info.width,(unsigned int) window_info.height);
13978 (void) XSetWindowBackgroundPixmap(display,window_info.id,window_info.pixmap);
13979 (void) XClearWindow(display,window_info.id);
13980 delay=1000*image->delay/MagickMax(image->ticks_per_second,1L);
13981 XDelay(display,delay == 0UL ? 10UL : delay);
13982 (void) XSync(display,MagickFalse);
13983 return(window_info.id == root_window ? MagickTrue : MagickFalse);
13987 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13991 + X D i s p l a y I m a g e %
13995 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13997 % XDisplayImage() displays an image via X11. A new image is created and
13998 % returned if the user interactively transforms the displayed image.
14000 % The format of the XDisplayImage method is:
14002 % Image *XDisplayImage(Display *display,XResourceInfo *resource_info,
14003 % char **argv,int argc,Image **image,size_t *state,
14004 % ExceptionInfo *exception)
14006 % A description of each parameter follows:
14008 % o nexus: Method XDisplayImage returns an image when the
14009 % user chooses 'Open Image' from the command menu or picks a tile
14010 % from the image directory. Otherwise a null image is returned.
14012 % o display: Specifies a connection to an X server; returned from
14015 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
14017 % o argv: Specifies the application's argument list.
14019 % o argc: Specifies the number of arguments.
14021 % o image: Specifies an address to an address of an Image structure;
14023 % o exception: return any errors or warnings in this structure.
14026 MagickExport Image *XDisplayImage(Display *display,XResourceInfo *resource_info,
14027 char **argv,int argc,Image **image,size_t *state,ExceptionInfo *exception)
14029 #define MagnifySize 256 /* must be a power of 2 */
14030 #define MagickMenus 10
14031 #define MagickTitle "Commands"
14058 "Visual Directory...",
14104 "Contrast Stretch...",
14105 "Sigmoidal Contrast...",
14139 "Charcoal Draw...",
14153 "Region of Interest...",
14156 *MiscellanyMenu[] =
14171 "Browse Documentation",
14198 **Menus[MagickMenus] =
14236 VisualDirectoryCommand,
14250 OriginalSizeCommand,
14257 TransformCommands[] =
14263 RotateRightCommand,
14270 EnhanceCommands[] =
14278 ContrastStretchCommand,
14279 SigmoidalContrastCommand,
14287 EffectsCommands[] =
14291 ReduceNoiseCommand,
14311 CharcoalDrawCommand
14313 ImageEditCommands[] =
14324 RegionofInterestCommand
14326 MiscellanyCommands[] =
14330 ShowPreviewCommand,
14331 ShowHistogramCommand,
14340 BrowseDocumentationCommand,
14343 ShortCutsCommands[] =
14355 VirtualCommands[] =
14364 *Commands[MagickMenus] =
14374 MiscellanyCommands,
14379 command[MaxTextExtent],
14381 geometry[MaxTextExtent],
14382 resource_name[MaxTextExtent];
14409 working_directory[MaxTextExtent];
14415 *magick_windows[MaxXWindows];
14417 static unsigned int
14477 assert(image != (Image **) NULL);
14478 assert((*image)->signature == MagickSignature);
14479 if ((*image)->debug != MagickFalse)
14480 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",(*image)->filename);
14481 display_image=(*image);
14482 warning_handler=(WarningHandler) NULL;
14483 windows=XSetWindows((XWindows *) ~0);
14484 if (windows != (XWindows *) NULL)
14489 status=chdir(working_directory);
14491 (void) ThrowMagickException(exception,GetMagickModule(),FileOpenError,
14492 "UnableToOpenFile","%s",working_directory);
14493 warning_handler=resource_info->display_warnings ?
14494 SetErrorHandler(XWarning) : SetErrorHandler((ErrorHandler) NULL);
14495 warning_handler=resource_info->display_warnings ?
14496 SetWarningHandler(XWarning) : SetWarningHandler((WarningHandler) NULL);
14501 Allocate windows structure.
14503 resource_info->colors=display_image->colors;
14504 windows=XSetWindows(XInitializeWindows(display,resource_info));
14505 if (windows == (XWindows *) NULL)
14506 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateWindow",
14507 (*image)->filename);
14509 Initialize window id's.
14512 magick_windows[number_windows++]=(&windows->icon);
14513 magick_windows[number_windows++]=(&windows->backdrop);
14514 magick_windows[number_windows++]=(&windows->image);
14515 magick_windows[number_windows++]=(&windows->info);
14516 magick_windows[number_windows++]=(&windows->command);
14517 magick_windows[number_windows++]=(&windows->widget);
14518 magick_windows[number_windows++]=(&windows->popup);
14519 magick_windows[number_windows++]=(&windows->magnify);
14520 magick_windows[number_windows++]=(&windows->pan);
14521 for (i=0; i < (int) number_windows; i++)
14522 magick_windows[i]->id=(Window) NULL;
14527 Initialize font info.
14529 if (windows->font_info != (XFontStruct *) NULL)
14530 (void) XFreeFont(display,windows->font_info);
14531 windows->font_info=XBestFont(display,resource_info,MagickFalse);
14532 if (windows->font_info == (XFontStruct *) NULL)
14533 ThrowXWindowFatalException(XServerFatalError,"UnableToLoadFont",
14534 resource_info->font);
14536 Initialize Standard Colormap.
14538 map_info=windows->map_info;
14539 icon_map=windows->icon_map;
14540 visual_info=windows->visual_info;
14541 icon_visual=windows->icon_visual;
14542 pixel=windows->pixel_info;
14543 icon_pixel=windows->icon_pixel;
14544 font_info=windows->font_info;
14545 icon_resources=windows->icon_resources;
14546 class_hints=windows->class_hints;
14547 manager_hints=windows->manager_hints;
14548 root_window=XRootWindow(display,visual_info->screen);
14549 nexus=NewImageList();
14550 if (display_image->debug != MagickFalse)
14552 (void) LogMagickEvent(X11Event,GetMagickModule(),
14553 "Image: %s[%.20g] %.20gx%.20g ",display_image->filename,
14554 (double) display_image->scene,(double) display_image->columns,
14555 (double) display_image->rows);
14556 if (display_image->colors != 0)
14557 (void) LogMagickEvent(X11Event,GetMagickModule(),"%.20gc ",(double)
14558 display_image->colors);
14559 (void) LogMagickEvent(X11Event,GetMagickModule(),"%s",
14560 display_image->magick);
14562 XMakeStandardColormap(display,visual_info,resource_info,display_image,
14564 display_image->taint=MagickFalse;
14566 Initialize graphic context.
14568 windows->context.id=(Window) NULL;
14569 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
14570 resource_info,&windows->context);
14571 (void) CloneString(&class_hints->res_name,resource_info->client_name);
14572 (void) CloneString(&class_hints->res_class,resource_info->client_name);
14573 class_hints->res_class[0]=(char) toupper((int) class_hints->res_class[0]);
14574 manager_hints->flags=InputHint | StateHint;
14575 manager_hints->input=MagickFalse;
14576 manager_hints->initial_state=WithdrawnState;
14577 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14578 &windows->context);
14579 if (display_image->debug != MagickFalse)
14580 (void) LogMagickEvent(X11Event,GetMagickModule(),
14581 "Window id: 0x%lx (context)",windows->context.id);
14582 context_values.background=pixel->background_color.pixel;
14583 context_values.font=font_info->fid;
14584 context_values.foreground=pixel->foreground_color.pixel;
14585 context_values.graphics_exposures=MagickFalse;
14586 context_mask=(MagickStatusType)
14587 (GCBackground | GCFont | GCForeground | GCGraphicsExposures);
14588 if (pixel->annotate_context != (GC) NULL)
14589 (void) XFreeGC(display,pixel->annotate_context);
14590 pixel->annotate_context=XCreateGC(display,windows->context.id,
14591 context_mask,&context_values);
14592 if (pixel->annotate_context == (GC) NULL)
14593 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
14594 display_image->filename);
14595 context_values.background=pixel->depth_color.pixel;
14596 if (pixel->widget_context != (GC) NULL)
14597 (void) XFreeGC(display,pixel->widget_context);
14598 pixel->widget_context=XCreateGC(display,windows->context.id,context_mask,
14600 if (pixel->widget_context == (GC) NULL)
14601 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
14602 display_image->filename);
14603 context_values.background=pixel->foreground_color.pixel;
14604 context_values.foreground=pixel->background_color.pixel;
14605 context_values.plane_mask=context_values.background ^
14606 context_values.foreground;
14607 if (pixel->highlight_context != (GC) NULL)
14608 (void) XFreeGC(display,pixel->highlight_context);
14609 pixel->highlight_context=XCreateGC(display,windows->context.id,
14610 (size_t) (context_mask | GCPlaneMask),&context_values);
14611 if (pixel->highlight_context == (GC) NULL)
14612 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
14613 display_image->filename);
14614 (void) XDestroyWindow(display,windows->context.id);
14616 Initialize icon window.
14618 XGetWindowInfo(display,icon_visual,icon_map,icon_pixel,(XFontStruct *) NULL,
14619 icon_resources,&windows->icon);
14620 windows->icon.geometry=resource_info->icon_geometry;
14621 XBestIconSize(display,&windows->icon,display_image);
14622 windows->icon.attributes.colormap=XDefaultColormap(display,
14623 icon_visual->screen);
14624 windows->icon.attributes.event_mask=ExposureMask | StructureNotifyMask;
14625 manager_hints->flags=InputHint | StateHint;
14626 manager_hints->input=MagickFalse;
14627 manager_hints->initial_state=IconicState;
14628 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14630 if (display_image->debug != MagickFalse)
14631 (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (icon)",
14634 Initialize graphic context for icon window.
14636 if (icon_pixel->annotate_context != (GC) NULL)
14637 (void) XFreeGC(display,icon_pixel->annotate_context);
14638 context_values.background=icon_pixel->background_color.pixel;
14639 context_values.foreground=icon_pixel->foreground_color.pixel;
14640 icon_pixel->annotate_context=XCreateGC(display,windows->icon.id,
14641 (size_t) (GCBackground | GCForeground),&context_values);
14642 if (icon_pixel->annotate_context == (GC) NULL)
14643 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
14644 display_image->filename);
14645 windows->icon.annotate_context=icon_pixel->annotate_context;
14647 Initialize Image window.
14649 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,resource_info,
14651 windows->image.shape=MagickTrue; /* non-rectangular shape hint */
14652 if (resource_info->use_shared_memory == MagickFalse)
14653 windows->image.shared_memory=MagickFalse;
14654 if ((resource_info->title != (char *) NULL) && !(*state & MontageImageState))
14659 title=InterpretImageProperties(resource_info->image_info,display_image,
14660 resource_info->title,exception);
14661 (void) CopyMagickString(windows->image.name,title,MaxTextExtent);
14662 (void) CopyMagickString(windows->image.icon_name,title,MaxTextExtent);
14663 title=DestroyString(title);
14668 filename[MaxTextExtent];
14671 Window name is the base of the filename.
14673 GetPathComponent(display_image->magick_filename,TailPath,filename);
14674 if (GetImageListLength(display_image) == 1)
14675 (void) FormatLocaleString(windows->image.name,MaxTextExtent,
14676 "%s: %s",MagickPackageName,filename);
14678 (void) FormatLocaleString(windows->image.name,MaxTextExtent,
14679 "%s: %s[scene: %.20g frames: %.20g]",MagickPackageName,filename,
14680 (double) display_image->scene,(double) GetImageListLength(
14682 (void) CopyMagickString(windows->image.icon_name,filename,MaxTextExtent);
14684 if (resource_info->immutable)
14685 windows->image.immutable=MagickTrue;
14686 windows->image.use_pixmap=resource_info->use_pixmap;
14687 windows->image.geometry=resource_info->image_geometry;
14688 (void) FormatLocaleString(geometry,MaxTextExtent,"%ux%u+0+0>!",
14689 XDisplayWidth(display,visual_info->screen),
14690 XDisplayHeight(display,visual_info->screen));
14691 geometry_info.width=display_image->columns;
14692 geometry_info.height=display_image->rows;
14695 (void) ParseMetaGeometry(geometry,&geometry_info.x,&geometry_info.y,
14696 &geometry_info.width,&geometry_info.height);
14697 windows->image.width=(unsigned int) geometry_info.width;
14698 windows->image.height=(unsigned int) geometry_info.height;
14699 windows->image.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
14700 ButtonReleaseMask | EnterWindowMask | ExposureMask | KeyPressMask |
14701 KeyReleaseMask | LeaveWindowMask | OwnerGrabButtonMask |
14702 PropertyChangeMask | StructureNotifyMask | SubstructureNotifyMask;
14703 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
14704 resource_info,&windows->backdrop);
14705 if ((resource_info->backdrop) || (windows->backdrop.id != (Window) NULL))
14708 Initialize backdrop window.
14710 windows->backdrop.x=0;
14711 windows->backdrop.y=0;
14712 (void) CloneString(&windows->backdrop.name,"Backdrop");
14713 windows->backdrop.flags=(size_t) (USSize | USPosition);
14714 windows->backdrop.width=(unsigned int)
14715 XDisplayWidth(display,visual_info->screen);
14716 windows->backdrop.height=(unsigned int)
14717 XDisplayHeight(display,visual_info->screen);
14718 windows->backdrop.border_width=0;
14719 windows->backdrop.immutable=MagickTrue;
14720 windows->backdrop.attributes.do_not_propagate_mask=ButtonPressMask |
14722 windows->backdrop.attributes.event_mask=ButtonPressMask | KeyPressMask |
14723 StructureNotifyMask;
14724 manager_hints->flags=IconWindowHint | InputHint | StateHint;
14725 manager_hints->icon_window=windows->icon.id;
14726 manager_hints->input=MagickTrue;
14727 manager_hints->initial_state=resource_info->iconic ? IconicState :
14729 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14730 &windows->backdrop);
14731 if (display_image->debug != MagickFalse)
14732 (void) LogMagickEvent(X11Event,GetMagickModule(),
14733 "Window id: 0x%lx (backdrop)",windows->backdrop.id);
14734 (void) XMapWindow(display,windows->backdrop.id);
14735 (void) XClearWindow(display,windows->backdrop.id);
14736 if (windows->image.id != (Window) NULL)
14738 (void) XDestroyWindow(display,windows->image.id);
14739 windows->image.id=(Window) NULL;
14742 Position image in the center the backdrop.
14744 windows->image.flags|=USPosition;
14745 windows->image.x=(XDisplayWidth(display,visual_info->screen)/2)-
14746 (windows->image.width/2);
14747 windows->image.y=(XDisplayHeight(display,visual_info->screen)/2)-
14748 (windows->image.height/2);
14750 manager_hints->flags=IconWindowHint | InputHint | StateHint;
14751 manager_hints->icon_window=windows->icon.id;
14752 manager_hints->input=MagickTrue;
14753 manager_hints->initial_state=resource_info->iconic ? IconicState :
14755 if (windows->group_leader.id != (Window) NULL)
14760 manager_hints->flags|=WindowGroupHint;
14761 manager_hints->window_group=windows->group_leader.id;
14762 (void) XSelectInput(display,windows->group_leader.id,StructureNotifyMask);
14763 if (display_image->debug != MagickFalse)
14764 (void) LogMagickEvent(X11Event,GetMagickModule(),
14765 "Window id: 0x%lx (group leader)",windows->group_leader.id);
14767 XMakeWindow(display,
14768 (Window) (resource_info->backdrop ? windows->backdrop.id : root_window),
14769 argv,argc,class_hints,manager_hints,&windows->image);
14770 (void) XChangeProperty(display,windows->image.id,windows->im_protocols,
14771 XA_STRING,8,PropModeReplace,(unsigned char *) NULL,0);
14772 if (windows->group_leader.id != (Window) NULL)
14773 (void) XSetTransientForHint(display,windows->image.id,
14774 windows->group_leader.id);
14775 if (display_image->debug != MagickFalse)
14776 (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (image)",
14777 windows->image.id);
14779 Initialize Info widget.
14781 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,resource_info,
14783 (void) CloneString(&windows->info.name,"Info");
14784 (void) CloneString(&windows->info.icon_name,"Info");
14785 windows->info.border_width=1;
14788 windows->info.flags|=PPosition;
14789 windows->info.attributes.win_gravity=UnmapGravity;
14790 windows->info.attributes.event_mask=ButtonPressMask | ExposureMask |
14791 StructureNotifyMask;
14792 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
14793 manager_hints->input=MagickFalse;
14794 manager_hints->initial_state=NormalState;
14795 manager_hints->window_group=windows->image.id;
14796 XMakeWindow(display,windows->image.id,argv,argc,class_hints,manager_hints,
14798 windows->info.highlight_stipple=XCreateBitmapFromData(display,
14799 windows->info.id,(char *) HighlightBitmap,HighlightWidth,HighlightHeight);
14800 windows->info.shadow_stipple=XCreateBitmapFromData(display,
14801 windows->info.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
14802 (void) XSetTransientForHint(display,windows->info.id,windows->image.id);
14803 if (windows->image.mapped != MagickFalse)
14804 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
14805 if (display_image->debug != MagickFalse)
14806 (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (info)",
14809 Initialize Command widget.
14811 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
14812 resource_info,&windows->command);
14813 windows->command.data=MagickMenus;
14814 (void) XCommandWidget(display,windows,CommandMenu,(XEvent *) NULL);
14815 (void) FormatLocaleString(resource_name,MaxTextExtent,"%s.command",
14816 resource_info->client_name);
14817 windows->command.geometry=XGetResourceClass(resource_info->resource_database,
14818 resource_name,"geometry",(char *) NULL);
14819 (void) CloneString(&windows->command.name,MagickTitle);
14820 windows->command.border_width=0;
14821 windows->command.flags|=PPosition;
14822 windows->command.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
14823 ButtonReleaseMask | EnterWindowMask | ExposureMask | LeaveWindowMask |
14824 OwnerGrabButtonMask | StructureNotifyMask;
14825 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
14826 manager_hints->input=MagickTrue;
14827 manager_hints->initial_state=NormalState;
14828 manager_hints->window_group=windows->image.id;
14829 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14830 &windows->command);
14831 windows->command.highlight_stipple=XCreateBitmapFromData(display,
14832 windows->command.id,(char *) HighlightBitmap,HighlightWidth,
14834 windows->command.shadow_stipple=XCreateBitmapFromData(display,
14835 windows->command.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
14836 (void) XSetTransientForHint(display,windows->command.id,windows->image.id);
14837 if (windows->command.mapped != MagickFalse)
14838 (void) XMapRaised(display,windows->command.id);
14839 if (display_image->debug != MagickFalse)
14840 (void) LogMagickEvent(X11Event,GetMagickModule(),
14841 "Window id: 0x%lx (command)",windows->command.id);
14843 Initialize Widget window.
14845 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
14846 resource_info,&windows->widget);
14847 (void) FormatLocaleString(resource_name,MaxTextExtent,"%s.widget",
14848 resource_info->client_name);
14849 windows->widget.geometry=XGetResourceClass(resource_info->resource_database,
14850 resource_name,"geometry",(char *) NULL);
14851 windows->widget.border_width=0;
14852 windows->widget.flags|=PPosition;
14853 windows->widget.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
14854 ButtonReleaseMask | EnterWindowMask | ExposureMask | KeyPressMask |
14855 KeyReleaseMask | LeaveWindowMask | OwnerGrabButtonMask |
14856 StructureNotifyMask;
14857 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
14858 manager_hints->input=MagickTrue;
14859 manager_hints->initial_state=NormalState;
14860 manager_hints->window_group=windows->image.id;
14861 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14863 windows->widget.highlight_stipple=XCreateBitmapFromData(display,
14864 windows->widget.id,(char *) HighlightBitmap,HighlightWidth,HighlightHeight);
14865 windows->widget.shadow_stipple=XCreateBitmapFromData(display,
14866 windows->widget.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
14867 (void) XSetTransientForHint(display,windows->widget.id,windows->image.id);
14868 if (display_image->debug != MagickFalse)
14869 (void) LogMagickEvent(X11Event,GetMagickModule(),
14870 "Window id: 0x%lx (widget)",windows->widget.id);
14872 Initialize popup window.
14874 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
14875 resource_info,&windows->popup);
14876 windows->popup.border_width=0;
14877 windows->popup.flags|=PPosition;
14878 windows->popup.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
14879 ButtonReleaseMask | EnterWindowMask | ExposureMask | KeyPressMask |
14880 KeyReleaseMask | LeaveWindowMask | StructureNotifyMask;
14881 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
14882 manager_hints->input=MagickTrue;
14883 manager_hints->initial_state=NormalState;
14884 manager_hints->window_group=windows->image.id;
14885 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14887 windows->popup.highlight_stipple=XCreateBitmapFromData(display,
14888 windows->popup.id,(char *) HighlightBitmap,HighlightWidth,HighlightHeight);
14889 windows->popup.shadow_stipple=XCreateBitmapFromData(display,
14890 windows->popup.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
14891 (void) XSetTransientForHint(display,windows->popup.id,windows->image.id);
14892 if (display_image->debug != MagickFalse)
14893 (void) LogMagickEvent(X11Event,GetMagickModule(),
14894 "Window id: 0x%lx (pop up)",windows->popup.id);
14896 Initialize Magnify window and cursor.
14898 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
14899 resource_info,&windows->magnify);
14900 if (resource_info->use_shared_memory == MagickFalse)
14901 windows->magnify.shared_memory=MagickFalse;
14902 (void) FormatLocaleString(resource_name,MaxTextExtent,"%s.magnify",
14903 resource_info->client_name);
14904 windows->magnify.geometry=XGetResourceClass(resource_info->resource_database,
14905 resource_name,"geometry",(char *) NULL);
14906 (void) FormatLocaleString(windows->magnify.name,MaxTextExtent,"Magnify %uX",
14907 resource_info->magnify);
14908 if (windows->magnify.cursor != (Cursor) NULL)
14909 (void) XFreeCursor(display,windows->magnify.cursor);
14910 windows->magnify.cursor=XMakeCursor(display,windows->image.id,
14911 map_info->colormap,resource_info->background_color,
14912 resource_info->foreground_color);
14913 if (windows->magnify.cursor == (Cursor) NULL)
14914 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateCursor",
14915 display_image->filename);
14916 windows->magnify.width=MagnifySize;
14917 windows->magnify.height=MagnifySize;
14918 windows->magnify.flags|=PPosition;
14919 windows->magnify.min_width=MagnifySize;
14920 windows->magnify.min_height=MagnifySize;
14921 windows->magnify.width_inc=MagnifySize;
14922 windows->magnify.height_inc=MagnifySize;
14923 windows->magnify.data=resource_info->magnify;
14924 windows->magnify.attributes.cursor=windows->magnify.cursor;
14925 windows->magnify.attributes.event_mask=ButtonPressMask | ButtonReleaseMask |
14926 ExposureMask | KeyPressMask | KeyReleaseMask | OwnerGrabButtonMask |
14927 StructureNotifyMask;
14928 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
14929 manager_hints->input=MagickTrue;
14930 manager_hints->initial_state=NormalState;
14931 manager_hints->window_group=windows->image.id;
14932 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14933 &windows->magnify);
14934 if (display_image->debug != MagickFalse)
14935 (void) LogMagickEvent(X11Event,GetMagickModule(),
14936 "Window id: 0x%lx (magnify)",windows->magnify.id);
14937 (void) XSetTransientForHint(display,windows->magnify.id,windows->image.id);
14939 Initialize panning window.
14941 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
14942 resource_info,&windows->pan);
14943 (void) CloneString(&windows->pan.name,"Pan Icon");
14944 windows->pan.width=windows->icon.width;
14945 windows->pan.height=windows->icon.height;
14946 (void) FormatLocaleString(resource_name,MaxTextExtent,"%s.pan",
14947 resource_info->client_name);
14948 windows->pan.geometry=XGetResourceClass(resource_info->resource_database,
14949 resource_name,"geometry",(char *) NULL);
14950 (void) XParseGeometry(windows->pan.geometry,&windows->pan.x,&windows->pan.y,
14951 &windows->pan.width,&windows->pan.height);
14952 windows->pan.flags|=PPosition;
14953 windows->pan.immutable=MagickTrue;
14954 windows->pan.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
14955 ButtonReleaseMask | ExposureMask | KeyPressMask | KeyReleaseMask |
14956 StructureNotifyMask;
14957 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
14958 manager_hints->input=MagickFalse;
14959 manager_hints->initial_state=NormalState;
14960 manager_hints->window_group=windows->image.id;
14961 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14963 if (display_image->debug != MagickFalse)
14964 (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (pan)",
14966 (void) XSetTransientForHint(display,windows->pan.id,windows->image.id);
14967 if (windows->info.mapped != MagickFalse)
14968 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
14969 if ((windows->image.mapped == MagickFalse) ||
14970 (windows->backdrop.id != (Window) NULL))
14971 (void) XMapWindow(display,windows->image.id);
14973 Set our progress monitor and warning handlers.
14975 if (warning_handler == (WarningHandler) NULL)
14977 warning_handler=resource_info->display_warnings ?
14978 SetErrorHandler(XWarning) : SetErrorHandler((ErrorHandler) NULL);
14979 warning_handler=resource_info->display_warnings ?
14980 SetWarningHandler(XWarning) : SetWarningHandler((WarningHandler) NULL);
14983 Initialize Image and Magnify X images.
14985 windows->image.x=0;
14986 windows->image.y=0;
14987 windows->magnify.shape=MagickFalse;
14988 width=(unsigned int) display_image->columns;
14989 height=(unsigned int) display_image->rows;
14990 if ((display_image->columns != width) || (display_image->rows != height))
14991 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
14992 display_image->filename);
14993 status=XMakeImage(display,resource_info,&windows->image,display_image,
14994 width,height,exception);
14995 if (status == MagickFalse)
14996 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
14997 display_image->filename);
14998 status=XMakeImage(display,resource_info,&windows->magnify,(Image *) NULL,
14999 windows->magnify.width,windows->magnify.height,exception);
15000 if (status == MagickFalse)
15001 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
15002 display_image->filename);
15003 if (windows->magnify.mapped != MagickFalse)
15004 (void) XMapRaised(display,windows->magnify.id);
15005 if (windows->pan.mapped != MagickFalse)
15006 (void) XMapRaised(display,windows->pan.id);
15007 windows->image.window_changes.width=(int) display_image->columns;
15008 windows->image.window_changes.height=(int) display_image->rows;
15009 (void) XConfigureImage(display,resource_info,windows,display_image,exception);
15010 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
15011 (void) XSync(display,MagickFalse);
15015 delay=display_image->delay/MagickMax(display_image->ticks_per_second,1L);
15016 timer=time((time_t *) NULL)+(delay == 0 ? 1 : delay)+1;
15018 if (resource_info->update != MagickFalse)
15024 Determine when file data was last modified.
15026 status=GetPathAttributes(display_image->filename,&attributes);
15027 if (status != MagickFalse)
15028 update_time=attributes.st_mtime;
15030 *state&=(~FormerImageState);
15031 *state&=(~MontageImageState);
15032 *state&=(~NextImageState);
15036 Handle a window event.
15038 if (windows->image.mapped != MagickFalse)
15039 if ((display_image->delay != 0) || (resource_info->update != 0))
15041 if (timer < time((time_t *) NULL))
15043 if (resource_info->update == MagickFalse)
15044 *state|=NextImageState | ExitState;
15051 Determine if image file was modified.
15053 status=GetPathAttributes(display_image->filename,&attributes);
15054 if (status != MagickFalse)
15055 if (update_time != attributes.st_mtime)
15060 (void) FormatLocaleString(
15061 resource_info->image_info->filename,MaxTextExtent,
15062 "%s:%s",display_image->magick,
15063 display_image->filename);
15064 nexus=ReadImage(resource_info->image_info,
15065 &display_image->exception);
15066 if (nexus != (Image *) NULL)
15068 nexus=DestroyImage(nexus);
15069 *state|=NextImageState | ExitState;
15072 delay=display_image->delay/MagickMax(
15073 display_image->ticks_per_second,1L);
15074 timer=time((time_t *) NULL)+(delay == 0 ? 1 : delay)+1;
15077 if (XEventsQueued(display,QueuedAfterFlush) == 0)
15080 Do not block if delay > 0.
15082 XDelay(display,SuspendTime << 2);
15086 timestamp=time((time_t *) NULL);
15087 (void) XNextEvent(display,&event);
15088 if (windows->image.stasis == MagickFalse)
15089 windows->image.stasis=(time((time_t *) NULL)-timestamp) > 0 ?
15090 MagickTrue : MagickFalse;
15091 if (windows->magnify.stasis == MagickFalse)
15092 windows->magnify.stasis=(time((time_t *) NULL)-timestamp) > 0 ?
15093 MagickTrue : MagickFalse;
15094 if (event.xany.window == windows->command.id)
15097 Select a command from the Command widget.
15099 id=XCommandWidget(display,windows,CommandMenu,&event);
15102 (void) CopyMagickString(command,CommandMenu[id],MaxTextExtent);
15103 command_type=CommandMenus[id];
15104 if (id < MagickMenus)
15107 Select a command from a pop-up menu.
15109 entry=XMenuWidget(display,windows,CommandMenu[id],Menus[id],
15113 (void) CopyMagickString(command,Menus[id][entry],MaxTextExtent);
15114 command_type=Commands[id][entry];
15116 if (command_type != NullCommand)
15117 nexus=XMagickCommand(display,resource_info,windows,command_type,
15118 &display_image,exception);
15121 switch (event.type)
15125 if (display_image->debug != MagickFalse)
15126 (void) LogMagickEvent(X11Event,GetMagickModule(),
15127 "Button Press: 0x%lx %u +%d+%d",event.xbutton.window,
15128 event.xbutton.button,event.xbutton.x,event.xbutton.y);
15129 if ((event.xbutton.button == Button3) &&
15130 (event.xbutton.state & Mod1Mask))
15133 Convert Alt-Button3 to Button2.
15135 event.xbutton.button=Button2;
15136 event.xbutton.state&=(~Mod1Mask);
15138 if (event.xbutton.window == windows->backdrop.id)
15140 (void) XSetInputFocus(display,event.xbutton.window,RevertToParent,
15141 event.xbutton.time);
15144 if (event.xbutton.window == windows->image.id)
15146 switch (event.xbutton.button)
15150 if (resource_info->immutable)
15153 Select a command from the Virtual menu.
15155 entry=XMenuWidget(display,windows,"Commands",VirtualMenu,
15158 nexus=XMagickCommand(display,resource_info,windows,
15159 VirtualCommands[entry],&display_image,exception);
15163 Map/unmap Command widget.
15165 if (windows->command.mapped != MagickFalse)
15166 (void) XWithdrawWindow(display,windows->command.id,
15167 windows->command.screen);
15170 (void) XCommandWidget(display,windows,CommandMenu,
15172 (void) XMapRaised(display,windows->command.id);
15179 User pressed the image magnify button.
15181 (void) XMagickCommand(display,resource_info,windows,ZoomCommand,
15182 &display_image,exception);
15183 XMagnifyImage(display,windows,&event);
15188 if (resource_info->immutable)
15191 Select a command from the Virtual menu.
15193 entry=XMenuWidget(display,windows,"Commands",VirtualMenu,
15196 nexus=XMagickCommand(display,resource_info,windows,
15197 VirtualCommands[entry],&display_image,exception);
15200 if (display_image->montage != (char *) NULL)
15203 Open or delete a tile from a visual image directory.
15205 nexus=XTileImage(display,resource_info,windows,
15206 display_image,&event,exception);
15207 if (nexus != (Image *) NULL)
15208 *state|=MontageImageState | NextImageState | ExitState;
15209 vid_info.x=(short int) windows->image.x;
15210 vid_info.y=(short int) windows->image.y;
15214 Select a command from the Short Cuts menu.
15216 entry=XMenuWidget(display,windows,"Short Cuts",ShortCutsMenu,
15219 nexus=XMagickCommand(display,resource_info,windows,
15220 ShortCutsCommands[entry],&display_image,exception);
15228 XTranslateImage(display,windows,*image,XK_Up);
15236 XTranslateImage(display,windows,*image,XK_Down);
15244 if (event.xbutton.window == windows->magnify.id)
15264 MagnifyCommands[] =
15277 Select a magnify factor from the pop-up menu.
15279 factor=XMenuWidget(display,windows,"Magnify",MagnifyMenu,command);
15281 XMagnifyWindowCommand(display,windows,0,MagnifyCommands[factor]);
15284 if (event.xbutton.window == windows->pan.id)
15286 switch (event.xbutton.button)
15293 XTranslateImage(display,windows,*image,XK_Up);
15301 XTranslateImage(display,windows,*image,XK_Down);
15306 XPanImage(display,windows,&event);
15312 delay=display_image->delay/MagickMax(display_image->ticks_per_second,
15314 timer=time((time_t *) NULL)+(delay == 0 ? 1 : delay)+1;
15317 case ButtonRelease:
15319 if (display_image->debug != MagickFalse)
15320 (void) LogMagickEvent(X11Event,GetMagickModule(),
15321 "Button Release: 0x%lx %u +%d+%d",event.xbutton.window,
15322 event.xbutton.button,event.xbutton.x,event.xbutton.y);
15325 case ClientMessage:
15327 if (display_image->debug != MagickFalse)
15328 (void) LogMagickEvent(X11Event,GetMagickModule(),
15329 "Client Message: 0x%lx 0x%lx %d 0x%lx",event.xclient.window,
15330 event.xclient.message_type,event.xclient.format,(unsigned long)
15331 event.xclient.data.l[0]);
15332 if (event.xclient.message_type == windows->im_protocols)
15334 if (*event.xclient.data.l == (long) windows->im_update_widget)
15336 (void) CloneString(&windows->command.name,MagickTitle);
15337 windows->command.data=MagickMenus;
15338 (void) XCommandWidget(display,windows,CommandMenu,
15342 if (*event.xclient.data.l == (long) windows->im_update_colormap)
15345 Update graphic context and window colormap.
15347 for (i=0; i < (int) number_windows; i++)
15349 if (magick_windows[i]->id == windows->icon.id)
15351 context_values.background=pixel->background_color.pixel;
15352 context_values.foreground=pixel->foreground_color.pixel;
15353 (void) XChangeGC(display,magick_windows[i]->annotate_context,
15354 context_mask,&context_values);
15355 (void) XChangeGC(display,magick_windows[i]->widget_context,
15356 context_mask,&context_values);
15357 context_values.background=pixel->foreground_color.pixel;
15358 context_values.foreground=pixel->background_color.pixel;
15359 context_values.plane_mask=context_values.background ^
15360 context_values.foreground;
15361 (void) XChangeGC(display,magick_windows[i]->highlight_context,
15362 (size_t) (context_mask | GCPlaneMask),
15364 magick_windows[i]->attributes.background_pixel=
15365 pixel->background_color.pixel;
15366 magick_windows[i]->attributes.border_pixel=
15367 pixel->border_color.pixel;
15368 magick_windows[i]->attributes.colormap=map_info->colormap;
15369 (void) XChangeWindowAttributes(display,magick_windows[i]->id,
15370 (unsigned long) magick_windows[i]->mask,
15371 &magick_windows[i]->attributes);
15373 if (windows->pan.mapped != MagickFalse)
15375 (void) XSetWindowBackgroundPixmap(display,windows->pan.id,
15376 windows->pan.pixmap);
15377 (void) XClearWindow(display,windows->pan.id);
15378 XDrawPanRectangle(display,windows);
15380 if (windows->backdrop.id != (Window) NULL)
15381 (void) XInstallColormap(display,map_info->colormap);
15384 if (*event.xclient.data.l == (long) windows->im_former_image)
15386 *state|=FormerImageState | ExitState;
15389 if (*event.xclient.data.l == (long) windows->im_next_image)
15391 *state|=NextImageState | ExitState;
15394 if (*event.xclient.data.l == (long) windows->im_retain_colors)
15396 *state|=RetainColorsState;
15399 if (*event.xclient.data.l == (long) windows->im_exit)
15406 if (event.xclient.message_type == windows->dnd_protocols)
15424 Display image named by the Drag-and-Drop selection.
15426 if ((*event.xclient.data.l != 2) && (*event.xclient.data.l != 128))
15428 selection=XInternAtom(display,"DndSelection",MagickFalse);
15429 status=XGetWindowProperty(display,root_window,selection,0L,(long)
15430 MaxTextExtent,MagickFalse,(Atom) AnyPropertyType,&type,&format,
15431 &length,&after,&data);
15432 if ((status != Success) || (length == 0))
15434 if (*event.xclient.data.l == 2)
15439 (void) CopyMagickString(resource_info->image_info->filename,
15440 (char *) data,MaxTextExtent);
15447 if (strncmp((char *) data, "file:", 5) != 0)
15449 (void) XFree((void *) data);
15452 (void) CopyMagickString(resource_info->image_info->filename,
15453 ((char *) data)+5,MaxTextExtent);
15455 nexus=ReadImage(resource_info->image_info,
15456 &display_image->exception);
15457 CatchException(&display_image->exception);
15458 if (nexus != (Image *) NULL)
15459 *state|=NextImageState | ExitState;
15460 (void) XFree((void *) data);
15464 If client window delete message, exit.
15466 if (event.xclient.message_type != windows->wm_protocols)
15468 if (*event.xclient.data.l != (long) windows->wm_delete_window)
15470 (void) XWithdrawWindow(display,event.xclient.window,
15471 visual_info->screen);
15472 if (event.xclient.window == windows->image.id)
15477 if (event.xclient.window == windows->pan.id)
15480 Restore original image size when pan window is deleted.
15482 windows->image.window_changes.width=windows->image.ximage->width;
15483 windows->image.window_changes.height=windows->image.ximage->height;
15484 (void) XConfigureImage(display,resource_info,windows,
15485 display_image,exception);
15489 case ConfigureNotify:
15491 if (display_image->debug != MagickFalse)
15492 (void) LogMagickEvent(X11Event,GetMagickModule(),
15493 "Configure Notify: 0x%lx %dx%d+%d+%d %d",event.xconfigure.window,
15494 event.xconfigure.width,event.xconfigure.height,event.xconfigure.x,
15495 event.xconfigure.y,event.xconfigure.send_event);
15496 if (event.xconfigure.window == windows->image.id)
15499 Image window has a new configuration.
15501 if (event.xconfigure.send_event != 0)
15507 Position the transient windows relative of the Image window.
15509 if (windows->command.geometry == (char *) NULL)
15510 if (windows->command.mapped == MagickFalse)
15512 windows->command.x=event.xconfigure.x-
15513 windows->command.width-25;
15514 windows->command.y=event.xconfigure.y;
15515 XConstrainWindowPosition(display,&windows->command);
15516 window_changes.x=windows->command.x;
15517 window_changes.y=windows->command.y;
15518 (void) XReconfigureWMWindow(display,windows->command.id,
15519 windows->command.screen,(unsigned int) (CWX | CWY),
15522 if (windows->widget.geometry == (char *) NULL)
15523 if (windows->widget.mapped == MagickFalse)
15525 windows->widget.x=event.xconfigure.x+
15526 event.xconfigure.width/10;
15527 windows->widget.y=event.xconfigure.y+
15528 event.xconfigure.height/10;
15529 XConstrainWindowPosition(display,&windows->widget);
15530 window_changes.x=windows->widget.x;
15531 window_changes.y=windows->widget.y;
15532 (void) XReconfigureWMWindow(display,windows->widget.id,
15533 windows->widget.screen,(unsigned int) (CWX | CWY),
15536 if (windows->magnify.geometry == (char *) NULL)
15537 if (windows->magnify.mapped == MagickFalse)
15539 windows->magnify.x=event.xconfigure.x+
15540 event.xconfigure.width+25;
15541 windows->magnify.y=event.xconfigure.y;
15542 XConstrainWindowPosition(display,&windows->magnify);
15543 window_changes.x=windows->magnify.x;
15544 window_changes.y=windows->magnify.y;
15545 (void) XReconfigureWMWindow(display,windows->magnify.id,
15546 windows->magnify.screen,(unsigned int) (CWX | CWY),
15549 if (windows->pan.geometry == (char *) NULL)
15550 if (windows->pan.mapped == MagickFalse)
15552 windows->pan.x=event.xconfigure.x+
15553 event.xconfigure.width+25;
15554 windows->pan.y=event.xconfigure.y+
15555 windows->magnify.height+50;
15556 XConstrainWindowPosition(display,&windows->pan);
15557 window_changes.x=windows->pan.x;
15558 window_changes.y=windows->pan.y;
15559 (void) XReconfigureWMWindow(display,windows->pan.id,
15560 windows->pan.screen,(unsigned int) (CWX | CWY),
15564 if ((event.xconfigure.width == (int) windows->image.width) &&
15565 (event.xconfigure.height == (int) windows->image.height))
15567 windows->image.width=(unsigned int) event.xconfigure.width;
15568 windows->image.height=(unsigned int) event.xconfigure.height;
15569 windows->image.x=0;
15570 windows->image.y=0;
15571 if (display_image->montage != (char *) NULL)
15573 windows->image.x=vid_info.x;
15574 windows->image.y=vid_info.y;
15576 if ((windows->image.mapped != MagickFalse) &&
15577 (windows->image.stasis != MagickFalse))
15580 Update image window configuration.
15582 windows->image.window_changes.width=event.xconfigure.width;
15583 windows->image.window_changes.height=event.xconfigure.height;
15584 (void) XConfigureImage(display,resource_info,windows,
15585 display_image,exception);
15588 Update pan window configuration.
15590 if ((event.xconfigure.width < windows->image.ximage->width) ||
15591 (event.xconfigure.height < windows->image.ximage->height))
15593 (void) XMapRaised(display,windows->pan.id);
15594 XDrawPanRectangle(display,windows);
15597 if (windows->pan.mapped != MagickFalse)
15598 (void) XWithdrawWindow(display,windows->pan.id,
15599 windows->pan.screen);
15602 if (event.xconfigure.window == windows->magnify.id)
15608 Magnify window has a new configuration.
15610 windows->magnify.width=(unsigned int) event.xconfigure.width;
15611 windows->magnify.height=(unsigned int) event.xconfigure.height;
15612 if (windows->magnify.mapped == MagickFalse)
15615 while ((int) magnify <= event.xconfigure.width)
15617 while ((int) magnify <= event.xconfigure.height)
15620 if (((int) magnify != event.xconfigure.width) ||
15621 ((int) magnify != event.xconfigure.height))
15623 window_changes.width=(int) magnify;
15624 window_changes.height=(int) magnify;
15625 (void) XReconfigureWMWindow(display,windows->magnify.id,
15626 windows->magnify.screen,(unsigned int) (CWWidth | CWHeight),
15630 if ((windows->magnify.mapped != MagickFalse) &&
15631 (windows->magnify.stasis != MagickFalse))
15633 status=XMakeImage(display,resource_info,&windows->magnify,
15634 display_image,windows->magnify.width,windows->magnify.height,
15636 XMakeMagnifyImage(display,windows);
15640 if ((windows->magnify.mapped != MagickFalse) &&
15641 (event.xconfigure.window == windows->pan.id))
15644 Pan icon window has a new configuration.
15646 if (event.xconfigure.send_event != 0)
15648 windows->pan.x=event.xconfigure.x;
15649 windows->pan.y=event.xconfigure.y;
15651 windows->pan.width=(unsigned int) event.xconfigure.width;
15652 windows->pan.height=(unsigned int) event.xconfigure.height;
15655 if (event.xconfigure.window == windows->icon.id)
15658 Icon window has a new configuration.
15660 windows->icon.width=(unsigned int) event.xconfigure.width;
15661 windows->icon.height=(unsigned int) event.xconfigure.height;
15666 case DestroyNotify:
15669 Group leader has exited.
15671 if (display_image->debug != MagickFalse)
15672 (void) LogMagickEvent(X11Event,GetMagickModule(),
15673 "Destroy Notify: 0x%lx",event.xdestroywindow.window);
15674 if (event.xdestroywindow.window == windows->group_leader.id)
15684 Selectively install colormap.
15686 if (map_info->colormap != XDefaultColormap(display,visual_info->screen))
15687 if (event.xcrossing.mode != NotifyUngrab)
15688 XInstallColormap(display,map_info->colormap);
15693 if (display_image->debug != MagickFalse)
15694 (void) LogMagickEvent(X11Event,GetMagickModule(),
15695 "Expose: 0x%lx %dx%d+%d+%d",event.xexpose.window,
15696 event.xexpose.width,event.xexpose.height,event.xexpose.x,
15699 Refresh windows that are now exposed.
15701 if ((event.xexpose.window == windows->image.id) &&
15702 (windows->image.mapped != MagickFalse))
15704 XRefreshWindow(display,&windows->image,&event);
15705 delay=display_image->delay/MagickMax(
15706 display_image->ticks_per_second,1L);
15707 timer=time((time_t *) NULL)+(delay == 0 ? 1 : delay)+1;
15710 if ((event.xexpose.window == windows->magnify.id) &&
15711 (windows->magnify.mapped != MagickFalse))
15713 XMakeMagnifyImage(display,windows);
15716 if (event.xexpose.window == windows->pan.id)
15718 XDrawPanRectangle(display,windows);
15721 if (event.xexpose.window == windows->icon.id)
15723 XRefreshWindow(display,&windows->icon,&event);
15734 Respond to a user key press.
15736 length=XLookupString((XKeyEvent *) &event.xkey,command,(int)
15737 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
15738 *(command+length)='\0';
15739 if (display_image->debug != MagickFalse)
15740 (void) LogMagickEvent(X11Event,GetMagickModule(),
15741 "Key press: %d 0x%lx (%s)",event.xkey.state,(unsigned long)
15742 key_symbol,command);
15743 if (event.xkey.window == windows->image.id)
15745 command_type=XImageWindowCommand(display,resource_info,windows,
15746 event.xkey.state,key_symbol,&display_image,exception);
15747 if (command_type != NullCommand)
15748 nexus=XMagickCommand(display,resource_info,windows,command_type,
15749 &display_image,exception);
15751 if (event.xkey.window == windows->magnify.id)
15752 XMagnifyWindowCommand(display,windows,event.xkey.state,key_symbol);
15753 if (event.xkey.window == windows->pan.id)
15755 if ((key_symbol == XK_q) || (key_symbol == XK_Escape))
15756 (void) XWithdrawWindow(display,windows->pan.id,
15757 windows->pan.screen);
15759 if ((key_symbol == XK_F1) || (key_symbol == XK_Help))
15760 XTextViewWidget(display,resource_info,windows,MagickFalse,
15761 "Help Viewer - Image Pan",ImagePanHelp);
15763 XTranslateImage(display,windows,*image,key_symbol);
15765 delay=display_image->delay/MagickMax(
15766 display_image->ticks_per_second,1L);
15767 timer=time((time_t *) NULL)+(delay == 0 ? 1 : delay)+1;
15773 Respond to a user key release.
15775 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
15776 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
15777 if (display_image->debug != MagickFalse)
15778 (void) LogMagickEvent(X11Event,GetMagickModule(),
15779 "Key release: 0x%lx (%c)",(unsigned long) key_symbol,*command);
15785 Selectively uninstall colormap.
15787 if (map_info->colormap != XDefaultColormap(display,visual_info->screen))
15788 if (event.xcrossing.mode != NotifyUngrab)
15789 XUninstallColormap(display,map_info->colormap);
15794 if (display_image->debug != MagickFalse)
15795 (void) LogMagickEvent(X11Event,GetMagickModule(),"Map Notify: 0x%lx",
15796 event.xmap.window);
15797 if (event.xmap.window == windows->backdrop.id)
15799 (void) XSetInputFocus(display,event.xmap.window,RevertToParent,
15801 windows->backdrop.mapped=MagickTrue;
15804 if (event.xmap.window == windows->image.id)
15806 if (windows->backdrop.id != (Window) NULL)
15807 (void) XInstallColormap(display,map_info->colormap);
15808 if (LocaleCompare(display_image->magick,"LOGO") == 0)
15810 if (LocaleCompare(display_image->filename,"LOGO") == 0)
15811 nexus=XOpenImage(display,resource_info,windows,MagickFalse);
15813 if (((int) windows->image.width < windows->image.ximage->width) ||
15814 ((int) windows->image.height < windows->image.ximage->height))
15815 (void) XMapRaised(display,windows->pan.id);
15816 windows->image.mapped=MagickTrue;
15819 if (event.xmap.window == windows->magnify.id)
15821 XMakeMagnifyImage(display,windows);
15822 windows->magnify.mapped=MagickTrue;
15823 (void) XWithdrawWindow(display,windows->info.id,
15824 windows->info.screen);
15827 if (event.xmap.window == windows->pan.id)
15829 XMakePanImage(display,resource_info,windows,display_image,
15831 windows->pan.mapped=MagickTrue;
15834 if (event.xmap.window == windows->info.id)
15836 windows->info.mapped=MagickTrue;
15839 if (event.xmap.window == windows->icon.id)
15845 Create an icon image.
15847 taint=display_image->taint;
15848 XMakeStandardColormap(display,icon_visual,icon_resources,
15849 display_image,icon_map,icon_pixel);
15850 (void) XMakeImage(display,icon_resources,&windows->icon,
15851 display_image,windows->icon.width,windows->icon.height,
15853 display_image->taint=taint;
15854 (void) XSetWindowBackgroundPixmap(display,windows->icon.id,
15855 windows->icon.pixmap);
15856 (void) XClearWindow(display,windows->icon.id);
15857 (void) XWithdrawWindow(display,windows->info.id,
15858 windows->info.screen);
15859 windows->icon.mapped=MagickTrue;
15862 if (event.xmap.window == windows->command.id)
15864 windows->command.mapped=MagickTrue;
15867 if (event.xmap.window == windows->popup.id)
15869 windows->popup.mapped=MagickTrue;
15872 if (event.xmap.window == windows->widget.id)
15874 windows->widget.mapped=MagickTrue;
15879 case MappingNotify:
15881 (void) XRefreshKeyboardMapping(&event.xmapping);
15886 case PropertyNotify:
15902 if (display_image->debug != MagickFalse)
15903 (void) LogMagickEvent(X11Event,GetMagickModule(),
15904 "Property Notify: 0x%lx 0x%lx %d",event.xproperty.window,
15905 event.xproperty.atom,event.xproperty.state);
15906 if (event.xproperty.atom != windows->im_remote_command)
15909 Display image named by the remote command protocol.
15911 status=XGetWindowProperty(display,event.xproperty.window,
15912 event.xproperty.atom,0L,(long) MaxTextExtent,MagickFalse,(Atom)
15913 AnyPropertyType,&type,&format,&length,&after,&data);
15914 if ((status != Success) || (length == 0))
15916 if (LocaleCompare((char *) data,"-quit") == 0)
15918 XClientMessage(display,windows->image.id,windows->im_protocols,
15919 windows->im_exit,CurrentTime);
15920 (void) XFree((void *) data);
15923 (void) CopyMagickString(resource_info->image_info->filename,
15924 (char *) data,MaxTextExtent);
15925 (void) XFree((void *) data);
15926 nexus=ReadImage(resource_info->image_info,&display_image->exception);
15927 CatchException(&display_image->exception);
15928 if (nexus != (Image *) NULL)
15929 *state|=NextImageState | ExitState;
15932 case ReparentNotify:
15934 if (display_image->debug != MagickFalse)
15935 (void) LogMagickEvent(X11Event,GetMagickModule(),
15936 "Reparent Notify: 0x%lx=>0x%lx",event.xreparent.parent,
15937 event.xreparent.window);
15942 if (display_image->debug != MagickFalse)
15943 (void) LogMagickEvent(X11Event,GetMagickModule(),
15944 "Unmap Notify: 0x%lx",event.xunmap.window);
15945 if (event.xunmap.window == windows->backdrop.id)
15947 windows->backdrop.mapped=MagickFalse;
15950 if (event.xunmap.window == windows->image.id)
15952 windows->image.mapped=MagickFalse;
15955 if (event.xunmap.window == windows->magnify.id)
15957 windows->magnify.mapped=MagickFalse;
15960 if (event.xunmap.window == windows->pan.id)
15962 windows->pan.mapped=MagickFalse;
15965 if (event.xunmap.window == windows->info.id)
15967 windows->info.mapped=MagickFalse;
15970 if (event.xunmap.window == windows->icon.id)
15972 if (map_info->colormap == icon_map->colormap)
15973 XConfigureImageColormap(display,resource_info,windows,
15975 (void) XFreeStandardColormap(display,icon_visual,icon_map,
15977 windows->icon.mapped=MagickFalse;
15980 if (event.xunmap.window == windows->command.id)
15982 windows->command.mapped=MagickFalse;
15985 if (event.xunmap.window == windows->popup.id)
15987 if (windows->backdrop.id != (Window) NULL)
15988 (void) XSetInputFocus(display,windows->image.id,RevertToParent,
15990 windows->popup.mapped=MagickFalse;
15993 if (event.xunmap.window == windows->widget.id)
15995 if (windows->backdrop.id != (Window) NULL)
15996 (void) XSetInputFocus(display,windows->image.id,RevertToParent,
15998 windows->widget.mapped=MagickFalse;
16005 if (display_image->debug != MagickFalse)
16006 (void) LogMagickEvent(X11Event,GetMagickModule(),"Event type: %d",
16011 } while (!(*state & ExitState));
16012 if ((*state & ExitState) == 0)
16013 (void) XMagickCommand(display,resource_info,windows,FreeBuffersCommand,
16014 &display_image,exception);
16016 if (resource_info->confirm_edit != MagickFalse)
16019 Query user if image has changed.
16021 if ((resource_info->immutable == MagickFalse) &&
16022 (display_image->taint != MagickFalse))
16027 status=XConfirmWidget(display,windows,"Your image changed.",
16028 "Do you want to save it");
16030 *state&=(~ExitState);
16033 (void) XMagickCommand(display,resource_info,windows,SaveCommand,
16034 &display_image,exception);
16037 if ((windows->visual_info->klass == GrayScale) ||
16038 (windows->visual_info->klass == PseudoColor) ||
16039 (windows->visual_info->klass == DirectColor))
16042 Withdraw pan and Magnify window.
16044 if (windows->info.mapped != MagickFalse)
16045 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
16046 if (windows->magnify.mapped != MagickFalse)
16047 (void) XWithdrawWindow(display,windows->magnify.id,
16048 windows->magnify.screen);
16049 if (windows->command.mapped != MagickFalse)
16050 (void) XWithdrawWindow(display,windows->command.id,
16051 windows->command.screen);
16053 if (windows->pan.mapped != MagickFalse)
16054 (void) XWithdrawWindow(display,windows->pan.id,windows->pan.screen);
16055 if (resource_info->backdrop == MagickFalse)
16056 if (windows->backdrop.mapped)
16058 (void) XWithdrawWindow(display,windows->backdrop.id,
16059 windows->backdrop.screen);
16060 (void) XDestroyWindow(display,windows->backdrop.id);
16061 windows->backdrop.id=(Window) NULL;
16062 (void) XWithdrawWindow(display,windows->image.id,
16063 windows->image.screen);
16064 (void) XDestroyWindow(display,windows->image.id);
16065 windows->image.id=(Window) NULL;
16067 XSetCursorState(display,windows,MagickTrue);
16068 XCheckRefreshWindows(display,windows);
16069 if (((*state & FormerImageState) != 0) || ((*state & NextImageState) != 0))
16070 *state&=(~ExitState);
16071 if (*state & ExitState)
16074 Free Standard Colormap.
16076 (void) XFreeStandardColormap(display,icon_visual,icon_map,icon_pixel);
16077 if (resource_info->map_type == (char *) NULL)
16078 (void) XFreeStandardColormap(display,visual_info,map_info,pixel);
16082 if (resource_info->copy_image != (Image *) NULL)
16084 resource_info->copy_image=DestroyImage(resource_info->copy_image);
16085 resource_info->copy_image=NewImageList();
16087 DestroyXResources();
16089 (void) XSync(display,MagickFalse);
16091 Restore our progress monitor and warning handlers.
16093 (void) SetErrorHandler(warning_handler);
16094 (void) SetWarningHandler(warning_handler);
16096 Change to home directory.
16098 directory=getcwd(working_directory,MaxTextExtent);
16104 status=chdir(resource_info->home_directory);
16106 (void) ThrowMagickException(&display_image->exception,GetMagickModule(),
16107 FileOpenError,"UnableToOpenFile","%s",resource_info->home_directory);
16109 *image=display_image;
16115 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
16119 + D i s p l a y I m a g e s %
16123 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
16125 % DisplayImages() displays an image sequence to any X window screen. It
16126 % returns a value other than 0 if successful. Check the exception member
16127 % of image to determine the reason for any failure.
16129 % The format of the DisplayImages method is:
16131 % MagickBooleanType DisplayImages(const ImageInfo *image_info,
16132 % Image *images,ExceptionInfo *exception)
16134 % A description of each parameter follows:
16136 % o image_info: the image info.
16138 % o image: the image.
16140 % o exception: return any errors or warnings in this structure.
16143 MagickExport MagickBooleanType DisplayImages(const ImageInfo *image_info,
16144 Image *image,ExceptionInfo *exception)
16146 assert(image_info != (const ImageInfo *) NULL);
16147 assert(image_info->signature == MagickSignature);
16148 assert(image != (Image *) NULL);
16149 assert(image->signature == MagickSignature);
16150 if (image->debug != MagickFalse)
16151 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
16152 (void) ThrowMagickException(exception,GetMagickModule(),MissingDelegateError,
16153 "DelegateLibrarySupportNotBuiltIn","`%s' (X11)",image->filename);
16154 return(MagickFalse);
16158 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
16162 + R e m o t e D i s p l a y C o m m a n d %
16166 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
16168 % RemoteDisplayCommand() encourages a remote display program to display the
16169 % specified image filename.
16171 % The format of the RemoteDisplayCommand method is:
16173 % MagickBooleanType RemoteDisplayCommand(const ImageInfo *image,
16174 % const char *window,const char *filename,ExceptionInfo *exception)
16176 % A description of each parameter follows:
16178 % o image_info: the image info.
16180 % o window: Specifies the name or id of an X window.
16182 % o filename: the name of the image filename to display.
16184 % o exception: return any errors or warnings in this structure.
16187 MagickExport MagickBooleanType RemoteDisplayCommand(const ImageInfo *image_info,
16188 const char *window,const char *filename,ExceptionInfo *exception)
16190 assert(image_info != (const ImageInfo *) NULL);
16191 assert(image_info->signature == MagickSignature);
16192 assert(filename != (char *) NULL);
16194 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
16195 (void) ThrowMagickException(exception,GetMagickModule(),MissingDelegateError,
16196 "DelegateLibrarySupportNotBuiltIn","`%s' (X11)",image_info->filename);
16197 return(MagickFalse);