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-2013 ImageMagick Studio LLC, a non-profit organization %
21 % dedicated to making software imaging solutions freely available. %
23 % You may not use this file except in compliance with the License. You may %
24 % obtain a copy of the License at %
26 % http://www.imagemagick.org/script/license.php %
28 % Unless required by applicable law or agreed to in writing, software %
29 % distributed under the License is distributed on an "AS IS" BASIS, %
30 % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
31 % See the License for the specific language governing permissions and %
32 % limitations under the License. %
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
42 #include "MagickCore/studio.h"
43 #include "MagickCore/artifact.h"
44 #include "MagickCore/attribute.h"
45 #include "MagickCore/blob.h"
46 #include "MagickCore/cache.h"
47 #include "MagickCore/cache-private.h"
48 #include "MagickCore/channel.h"
49 #include "MagickCore/client.h"
50 #include "MagickCore/color.h"
51 #include "MagickCore/colorspace.h"
52 #include "MagickCore/composite.h"
53 #include "MagickCore/constitute.h"
54 #include "MagickCore/decorate.h"
55 #include "MagickCore/delegate.h"
56 #include "MagickCore/display.h"
57 #include "MagickCore/display-private.h"
58 #include "MagickCore/distort.h"
59 #include "MagickCore/draw.h"
60 #include "MagickCore/effect.h"
61 #include "MagickCore/enhance.h"
62 #include "MagickCore/exception.h"
63 #include "MagickCore/exception-private.h"
64 #include "MagickCore/fx.h"
65 #include "MagickCore/geometry.h"
66 #include "MagickCore/image.h"
67 #include "MagickCore/image-private.h"
68 #include "MagickCore/list.h"
69 #include "MagickCore/log.h"
70 #include "MagickCore/magick.h"
71 #include "MagickCore/memory_.h"
72 #include "MagickCore/monitor.h"
73 #include "MagickCore/monitor-private.h"
74 #include "MagickCore/montage.h"
75 #include "MagickCore/option.h"
76 #include "MagickCore/paint.h"
77 #include "MagickCore/pixel.h"
78 #include "MagickCore/pixel-accessor.h"
79 #include "MagickCore/PreRvIcccm.h"
80 #include "MagickCore/property.h"
81 #include "MagickCore/quantum.h"
82 #include "MagickCore/quantum-private.h"
83 #include "MagickCore/resize.h"
84 #include "MagickCore/resource_.h"
85 #include "MagickCore/shear.h"
86 #include "MagickCore/segment.h"
87 #include "MagickCore/statistic.h"
88 #include "MagickCore/string_.h"
89 #include "MagickCore/string-private.h"
90 #include "MagickCore/transform.h"
91 #include "MagickCore/threshold.h"
92 #include "MagickCore/utility.h"
93 #include "MagickCore/utility-private.h"
94 #include "MagickCore/version.h"
95 #include "MagickCore/widget.h"
96 #include "MagickCore/widget-private.h"
97 #include "MagickCore/xwindow.h"
98 #include "MagickCore/xwindow-private.h"
100 #if defined(MAGICKCORE_X11_DELEGATE)
104 #define MaxColors MagickMin((ssize_t) windows->visual_info->colormap_size,256L)
107 Constant declarations.
109 static const unsigned char
112 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55
116 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
120 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
144 Help widget declarations.
147 *ImageAnnotateHelp[] =
149 "In annotate mode, the Command widget has these options:",
199 "Choose a font name from the Font Name sub-menu. Additional",
200 "font names can be specified with the font browser. You can",
201 "change the menu names by setting the X resources font1",
204 "Choose a font color from the Font Color sub-menu.",
205 "Additional font colors can be specified with the color",
206 "browser. You can change the menu colors by setting the X",
207 "resources pen1 through pen9.",
209 "If you select the color browser and press Grab, you can",
210 "choose the font color by moving the pointer to the desired",
211 "color on the screen and press any button.",
213 "If you choose to rotate the text, choose Rotate Text from the",
214 "menu and select an angle. Typically you will only want to",
215 "rotate one line of text at a time. Depending on the angle you",
216 "choose, subsequent lines may end up overwriting each other.",
218 "Choosing a font and its color is optional. The default font",
219 "is fixed and the default color is black. However, you must",
220 "choose a location to begin entering text and press button 1.",
221 "An underscore character will appear at the location of the",
222 "pointer. The cursor changes to a pencil to indicate you are",
223 "in text mode. To exit immediately, press Dismiss.",
225 "In text mode, any key presses will display the character at",
226 "the location of the underscore and advance the underscore",
227 "cursor. Enter your text and once completed press Apply to",
228 "finish your image annotation. To correct errors press BACK",
229 "SPACE. To delete an entire line of text, press DELETE. Any",
230 "text that exceeds the boundaries of the image window is",
231 "automagically continued onto the next line.",
233 "The actual color you request for the font is saved in the",
234 "image. However, the color that appears in your image window",
235 "may be different. For example, on a monochrome screen the",
236 "text will appear black or white even if you choose the color",
237 "red as the font color. However, the image saved to a file",
238 "with -write is written with red lettering. To assure the",
239 "correct color text in the final image, any PseudoClass image",
240 "is promoted to DirectClass (see miff(5)). To force a",
241 "PseudoClass image to remain PseudoClass, use -colors.",
246 "In chop mode, the Command widget has these options:",
254 "If the you choose the horizontal direction (this the",
255 "default), the area of the image between the two horizontal",
256 "endpoints of the chop line is removed. Otherwise, the area",
257 "of the image between the two vertical endpoints of the chop",
260 "Select a location within the image window to begin your chop,",
261 "press and hold any button. Next, move the pointer to",
262 "another location in the image. As you move a line will",
263 "connect the initial location and the pointer. When you",
264 "release the button, the area within the image to chop is",
265 "determined by which direction you choose from the Command",
268 "To cancel the image chopping, move the pointer back to the",
269 "starting point of the line and release the button.",
272 *ImageColorEditHelp[] =
274 "In color edit mode, the Command widget has these options:",
315 "Choose a color editing method from the Method sub-menu",
316 "of the Command widget. The point method recolors any pixel",
317 "selected with the pointer until the button is released. The",
318 "replace method recolors any pixel that matches the color of",
319 "the pixel you select with a button press. Floodfill recolors",
320 "any pixel that matches the color of the pixel you select with",
321 "a button press and is a neighbor. Whereas filltoborder recolors",
322 "any neighbor pixel that is not the border color. Finally reset",
323 "changes the entire image to the designated color.",
325 "Next, choose a pixel color from the Pixel Color sub-menu.",
326 "Additional pixel colors can be specified with the color",
327 "browser. You can change the menu colors by setting the X",
328 "resources pen1 through pen9.",
330 "Now press button 1 to select a pixel within the image window",
331 "to change its color. Additional pixels may be recolored as",
332 "prescribed by the method you choose.",
334 "If the Magnify widget is mapped, it can be helpful in positioning",
335 "your pointer within the image (refer to button 2).",
337 "The actual color you request for the pixels is saved in the",
338 "image. However, the color that appears in your image window",
339 "may be different. For example, on a monochrome screen the",
340 "pixel will appear black or white even if you choose the",
341 "color red as the pixel color. However, the image saved to a",
342 "file with -write is written with red pixels. To assure the",
343 "correct color text in the final image, any PseudoClass image",
344 "is promoted to DirectClass (see miff(5)). To force a",
345 "PseudoClass image to remain PseudoClass, use -colors.",
348 *ImageCompositeHelp[] =
350 "First a widget window is displayed requesting you to enter an",
351 "image name. Press Composite, Grab or type a file name.",
352 "Press Cancel if you choose not to create a composite image.",
353 "When you choose Grab, move the pointer to the desired window",
354 "and press any button.",
356 "If the Composite image does not have any matte information,",
357 "you are informed and the file browser is displayed again.",
358 "Enter the name of a mask image. The image is typically",
359 "grayscale and the same size as the composite image. If the",
360 "image is not grayscale, it is converted to grayscale and the",
361 "resulting intensities are used as matte information.",
363 "A small window appears showing the location of the cursor in",
364 "the image window. You are now in composite mode. To exit",
365 "immediately, press Dismiss. In composite mode, the Command",
366 "widget has these options:",
392 "Choose a composite operation from the Operators sub-menu of",
393 "the Command widget. How each operator behaves is described",
394 "below. Image window is the image currently displayed on",
395 "your X server and image is the image obtained with the File",
398 "Over The result is the union of the two image shapes,",
399 " with image obscuring image window in the region of",
402 "In The result is simply image cut by the shape of",
403 " image window. None of the image data of image",
404 " window is in the result.",
406 "Out The resulting image is image with the shape of",
407 " image window cut out.",
409 "Atop The result is the same shape as image image window,",
410 " with image obscuring image window where the image",
411 " shapes overlap. Note this differs from over",
412 " because the portion of image outside image window's",
413 " shape does not appear in the result.",
415 "Xor The result is the image data from both image and",
416 " image window that is outside the overlap region.",
417 " The overlap region is blank.",
419 "Plus The result is just the sum of the image data.",
420 " Output values are cropped to QuantumRange (no overflow).",
422 "Minus The result of image - image window, with underflow",
425 "Add The result of image + image window, with overflow",
426 " wrapping around (mod 256).",
428 "Subtract The result of image - image window, with underflow",
429 " wrapping around (mod 256). The add and subtract",
430 " operators can be used to perform reversible",
434 " The result of abs(image - image window). This",
435 " useful for comparing two very similar images.",
438 " The result of image * image window. This",
439 " useful for the creation of drop-shadows.",
441 "Bumpmap The result of surface normals from image * image",
444 "Copy The resulting image is image window replaced with",
445 " image. Here the matte information is ignored.",
447 "CopyRed The red layer of the image window is replace with",
448 " the red layer of the image. The other layers are",
452 " The green layer of the image window is replace with",
453 " the green layer of the image. The other layers are",
456 "CopyBlue The blue layer of the image window is replace with",
457 " the blue layer of the image. The other layers are",
461 " The matte layer of the image window is replace with",
462 " the matte layer of the image. The other layers are",
465 "The image compositor requires a matte, or alpha channel in",
466 "the image for some operations. This extra channel usually",
467 "defines a mask which represents a sort of a cookie-cutter",
468 "for the image. This the case when matte is opaque (full",
469 "coverage) for pixels inside the shape, zero outside, and",
470 "between 0 and QuantumRange on the boundary. If image does not",
471 "have a matte channel, it is initialized with 0 for any pixel",
472 "matching in color to pixel location (0,0), otherwise QuantumRange.",
474 "If you choose Dissolve, the composite operator becomes Over. The",
475 "image matte channel percent transparency is initialized to factor.",
476 "The image window is initialized to (100-factor). Where factor is the",
477 "value you specify in the Dialog widget.",
479 "Displace shifts the image pixels as defined by a displacement",
480 "map. With this option, image is used as a displacement map.",
481 "Black, within the displacement map, is a maximum positive",
482 "displacement. White is a maximum negative displacement and",
483 "middle gray is neutral. The displacement is scaled to determine",
484 "the pixel shift. By default, the displacement applies in both the",
485 "horizontal and vertical directions. However, if you specify a mask,",
486 "image is the horizontal X displacement and mask the vertical Y",
489 "Note that matte information for image window is not retained",
490 "for colormapped X server visuals (e.g. StaticColor,",
491 "StaticColor, GrayScale, PseudoColor). Correct compositing",
492 "behavior may require a TrueColor or DirectColor visual or a",
493 "Standard Colormap.",
495 "Choosing a composite operator is optional. The default",
496 "operator is replace. However, you must choose a location to",
497 "composite your image and press button 1. Press and hold the",
498 "button before releasing and an outline of the image will",
499 "appear to help you identify your location.",
501 "The actual colors of the composite image is saved. However,",
502 "the color that appears in image window may be different.",
503 "For example, on a monochrome screen image window will appear",
504 "black or white even though your composited image may have",
505 "many colors. If the image is saved to a file it is written",
506 "with the correct colors. To assure the correct colors are",
507 "saved in the final image, any PseudoClass image is promoted",
508 "to DirectClass (see miff(5)). To force a PseudoClass image",
509 "to remain PseudoClass, use -colors.",
514 "In cut mode, the Command widget has these options:",
519 "To define a cut region, press button 1 and drag. The",
520 "cut region is defined by a highlighted rectangle that",
521 "expands or contracts as it follows the pointer. Once you",
522 "are satisfied with the cut region, release the button.",
523 "You are now in rectify mode. In rectify mode, the Command",
524 "widget has these options:",
530 "You can make adjustments by moving the pointer to one of the",
531 "cut rectangle corners, pressing a button, and dragging.",
532 "Finally, press Cut to commit your copy region. To",
533 "exit without cutting the image, press Dismiss.",
538 "In copy mode, the Command widget has these options:",
543 "To define a copy region, press button 1 and drag. The",
544 "copy region is defined by a highlighted rectangle that",
545 "expands or contracts as it follows the pointer. Once you",
546 "are satisfied with the copy region, release the button.",
547 "You are now in rectify mode. In rectify mode, the Command",
548 "widget has these options:",
554 "You can make adjustments by moving the pointer to one of the",
555 "copy rectangle corners, pressing a button, and dragging.",
556 "Finally, press Copy to commit your copy region. To",
557 "exit without copying the image, press Dismiss.",
562 "In crop mode, the Command widget has these options:",
567 "To define a cropping region, press button 1 and drag. The",
568 "cropping region is defined by a highlighted rectangle that",
569 "expands or contracts as it follows the pointer. Once you",
570 "are satisfied with the cropping region, release the button.",
571 "You are now in rectify mode. In rectify mode, the Command",
572 "widget has these options:",
578 "You can make adjustments by moving the pointer to one of the",
579 "cropping rectangle corners, pressing a button, and dragging.",
580 "Finally, press Crop to commit your cropping region. To",
581 "exit without cropping the image, press Dismiss.",
586 "The cursor changes to a crosshair to indicate you are in",
587 "draw mode. To exit immediately, press Dismiss. In draw mode,",
588 "the Command widget has these options:",
633 "Choose a drawing primitive from the Element sub-menu.",
635 "Choose a color from the Color sub-menu. Additional",
636 "colors can be specified with the color browser.",
638 "If you choose the color browser and press Grab, you can",
639 "select the color by moving the pointer to the desired",
640 "color on the screen and press any button. The transparent",
641 "color updates the image matte channel and is useful for",
642 "image compositing.",
644 "Choose a stipple, if appropriate, from the Stipple sub-menu.",
645 "Additional stipples can be specified with the file browser.",
646 "Stipples obtained from the file browser must be on disk in the",
647 "X11 bitmap format.",
649 "Choose a width, if appropriate, from the Width sub-menu. To",
650 "choose a specific width select the Dialog widget.",
652 "Choose a point in the Image window and press button 1 and",
653 "hold. Next, move the pointer to another location in the",
654 "image. As you move, a line connects the initial location and",
655 "the pointer. When you release the button, the image is",
656 "updated with the primitive you just drew. For polygons, the",
657 "image is updated when you press and release the button without",
658 "moving the pointer.",
660 "To cancel image drawing, move the pointer back to the",
661 "starting point of the line and release the button.",
667 " The effects of each button press is described below. Three",
668 " buttons are required. If you have a two button mouse,",
669 " button 1 and 3 are returned. Press ALT and button 3 to",
670 " simulate button 2.",
672 " 1 Press this button to map or unmap the Command widget.",
674 " 2 Press and drag to define a region of the image to",
677 " 3 Press and drag to choose from a select set of commands.",
678 " This button behaves differently if the image being",
679 " displayed is a visual image directory. Here, choose a",
680 " particular tile of the directory and press this button and",
681 " drag to select a command from a pop-up menu. Choose from",
682 " these menu items:",
690 " If you choose Open, the image represented by the tile is",
691 " displayed. To return to the visual image directory, choose",
692 " Next from the Command widget. Next and Former moves to the",
693 " next or former image respectively. Choose Delete to delete",
694 " a particular image tile. Finally, choose Update to",
695 " synchronize all the image tiles with their respective",
699 " The Command widget lists a number of sub-menus and commands.",
711 " Visual Directory...",
745 " Contrast Stretch...",
746 " Sigmoidal Contrast...",
774 " Charcoal Drawing...",
785 " Region of Interest...",
797 " Browse Documentation",
800 " Menu items with a indented triangle have a sub-menu. They",
801 " are represented above as the indented items. To access a",
802 " sub-menu item, move the pointer to the appropriate menu and",
803 " press a button and drag. When you find the desired sub-menu",
804 " item, release the button and the command is executed. Move",
805 " the pointer away from the sub-menu if you decide not to",
806 " execute a particular command.",
808 "KEYBOARD ACCELERATORS",
809 " Accelerators are one or two key presses that effect a",
810 " particular command. The keyboard accelerators that",
811 " display(1) understands is:",
813 " Ctl+O Press to open an image from a file.",
815 " space Press to display the next image.",
817 " If the image is a multi-paged document such as a Postscript",
818 " document, you can skip ahead several pages by preceding",
819 " this command with a number. For example to display the",
820 " third page beyond the current page, press 3<space>.",
822 " backspace Press to display the former image.",
824 " If the image is a multi-paged document such as a Postscript",
825 " document, you can skip behind several pages by preceding",
826 " this command with a number. For example to display the",
827 " third page preceding the current page, press 3<backspace>.",
829 " Ctl+S Press to write the image to a file.",
831 " Ctl+P Press to print the image to a Postscript printer.",
833 " Ctl+D Press to delete an image file.",
835 " Ctl+N Press to create a blank canvas.",
837 " Ctl+Q Press to discard all images and exit program.",
839 " Ctl+Z Press to undo last image transformation.",
841 " Ctl+R Press to redo last image transformation.",
843 " Ctl+X Press to cut a region of the image.",
845 " Ctl+C Press to copy a region of the image.",
847 " Ctl+V Press to paste a region to the image.",
849 " < Press to half the image size.",
851 " - Press to return to the original image size.",
853 " > Press to double the image size.",
855 " % Press to resize the image to a width and height you",
858 "Cmd-A Press to make any image transformations permanent."
860 " By default, any image size transformations are applied",
861 " to the original image to create the image displayed on",
862 " the X server. However, the transformations are not",
863 " permanent (i.e. the original image does not change",
864 " size only the X image does). For example, if you",
865 " press > the X image will appear to double in size,",
866 " but the original image will in fact remain the same size.",
867 " To force the original image to double in size, press >",
868 " followed by Cmd-A.",
870 " @ Press to refresh the image window.",
872 " C Press to cut out a rectangular region of the image.",
874 " [ Press to chop the image.",
876 " H Press to flop image in the horizontal direction.",
878 " V Press to flip image in the vertical direction.",
880 " / Press to rotate the image 90 degrees clockwise.",
882 " \\ Press to rotate the image 90 degrees counter-clockwise.",
884 " * Press to rotate the image the number of degrees you",
887 " S Press to shear the image the number of degrees you",
890 " R Press to roll the image.",
892 " T Press to trim the image edges.",
894 " Shft-H Press to vary the image hue.",
896 " Shft-S Press to vary the color saturation.",
898 " Shft-L Press to vary the color brightness.",
900 " Shft-G Press to gamma correct the image.",
902 " Shft-C Press to sharpen the image contrast.",
904 " Shft-Z Press to dull the image contrast.",
906 " = Press to perform histogram equalization on the image.",
908 " Shft-N Press to perform histogram normalization on the image.",
910 " Shft-~ Press to negate the colors of the image.",
912 " . Press to convert the image colors to gray.",
914 " Shft-# Press to set the maximum number of unique colors in the",
917 " F2 Press to reduce the speckles in an image.",
919 " F3 Press to eliminate peak noise from an image.",
921 " F4 Press to add noise to an image.",
923 " F5 Press to sharpen an image.",
925 " F6 Press to delete an image file.",
927 " F7 Press to threshold the image.",
929 " F8 Press to detect edges within an image.",
931 " F9 Press to emboss an image.",
933 " F10 Press to displace pixels by a random amount.",
935 " F11 Press to negate all pixels above the threshold level.",
937 " F12 Press to shade the image using a distant light source.",
939 " F13 Press to lighten or darken image edges to create a 3-D effect.",
941 " F14 Press to segment the image by color.",
943 " Meta-S Press to swirl image pixels about the center.",
945 " Meta-I Press to implode image pixels about the center.",
947 " Meta-W Press to alter an image along a sine wave.",
949 " Meta-P Press to simulate an oil painting.",
951 " Meta-C Press to simulate a charcoal drawing.",
953 " Alt-A Press to annotate the image with text.",
955 " Alt-D Press to draw on an image.",
957 " Alt-P Press to edit an image pixel color.",
959 " Alt-M Press to edit the image matte information.",
961 " Alt-V Press to composite the image with another.",
963 " Alt-B Press to add a border to the image.",
965 " Alt-F Press to add an ornamental border to the image.",
968 " Press to add an image comment.",
970 " Ctl-A Press to apply image processing techniques to a region",
973 " Shft-? Press to display information about the image.",
975 " Shft-+ Press to map the zoom image window.",
977 " Shft-P Press to preview an image enhancement, effect, or f/x.",
979 " F1 Press to display helpful information about display(1).",
981 " Find Press to browse documentation about ImageMagick.",
983 " 1-9 Press to change the level of magnification.",
985 " Use the arrow keys to move the image one pixel up, down,",
986 " left, or right within the magnify window. Be sure to first",
987 " map the magnify window by pressing button 2.",
989 " Press ALT and one of the arrow keys to trim off one pixel",
990 " from any side of the image.",
993 *ImageMatteEditHelp[] =
995 "Matte information within an image is useful for some",
996 "operations such as image compositing (See IMAGE",
997 "COMPOSITING). This extra channel usually defines a mask",
998 "which represents a sort of a cookie-cutter for the image.",
999 "This the case when matte is opaque (full coverage) for",
1000 "pixels inside the shape, zero outside, and between 0 and",
1001 "QuantumRange on the boundary.",
1003 "A small window appears showing the location of the cursor in",
1004 "the image window. You are now in matte edit mode. To exit",
1005 "immediately, press Dismiss. In matte edit mode, the Command",
1006 "widget has these options:",
1040 "Choose a matte editing method from the Method sub-menu of",
1041 "the Command widget. The point method changes the matte value",
1042 "of any pixel selected with the pointer until the button is",
1043 "is released. The replace method changes the matte value of",
1044 "any pixel that matches the color of the pixel you select with",
1045 "a button press. Floodfill changes the matte value of any pixel",
1046 "that matches the color of the pixel you select with a button",
1047 "press and is a neighbor. Whereas filltoborder changes the matte",
1048 "value any neighbor pixel that is not the border color. Finally",
1049 "reset changes the entire image to the designated matte value.",
1051 "Choose Matte Value and pick Opaque or Transarent. For other values",
1052 "select the Dialog entry. Here a dialog appears requesting a matte",
1053 "value. The value you select is assigned as the opacity value of the",
1054 "selected pixel or pixels.",
1056 "Now, press any button to select a pixel within the image",
1057 "window to change its matte value.",
1059 "If the Magnify widget is mapped, it can be helpful in positioning",
1060 "your pointer within the image (refer to button 2).",
1062 "Matte information is only valid in a DirectClass image.",
1063 "Therefore, any PseudoClass image is promoted to DirectClass",
1064 "(see miff(5)). Note that matte information for PseudoClass",
1065 "is not retained for colormapped X server visuals (e.g.",
1066 "StaticColor, StaticColor, GrayScale, PseudoColor) unless you",
1067 "immediately save your image to a file (refer to Write).",
1068 "Correct matte editing behavior may require a TrueColor or",
1069 "DirectColor visual or a Standard Colormap.",
1074 "When an image exceeds the width or height of the X server",
1075 "screen, display maps a small panning icon. The rectangle",
1076 "within the panning icon shows the area that is currently",
1077 "displayed in the image window. To pan about the image,",
1078 "press any button and drag the pointer within the panning",
1079 "icon. The pan rectangle moves with the pointer and the",
1080 "image window is updated to reflect the location of the",
1081 "rectangle within the panning icon. When you have selected",
1082 "the area of the image you wish to view, release the button.",
1084 "Use the arrow keys to pan the image one pixel up, down,",
1085 "left, or right within the image window.",
1087 "The panning icon is withdrawn if the image becomes smaller",
1088 "than the dimensions of the X server screen.",
1093 "A small window appears showing the location of the cursor in",
1094 "the image window. You are now in paste mode. To exit",
1095 "immediately, press Dismiss. In paste mode, the Command",
1096 "widget has these options:",
1113 "Choose a composite operation from the Operators sub-menu of",
1114 "the Command widget. How each operator behaves is described",
1115 "below. Image window is the image currently displayed on",
1116 "your X server and image is the image obtained with the File",
1119 "Over The result is the union of the two image shapes,",
1120 " with image obscuring image window in the region of",
1123 "In The result is simply image cut by the shape of",
1124 " image window. None of the image data of image",
1125 " window is in the result.",
1127 "Out The resulting image is image with the shape of",
1128 " image window cut out.",
1130 "Atop The result is the same shape as image image window,",
1131 " with image obscuring image window where the image",
1132 " shapes overlap. Note this differs from over",
1133 " because the portion of image outside image window's",
1134 " shape does not appear in the result.",
1136 "Xor The result is the image data from both image and",
1137 " image window that is outside the overlap region.",
1138 " The overlap region is blank.",
1140 "Plus The result is just the sum of the image data.",
1141 " Output values are cropped to QuantumRange (no overflow).",
1142 " This operation is independent of the matte",
1145 "Minus The result of image - image window, with underflow",
1146 " cropped to zero.",
1148 "Add The result of image + image window, with overflow",
1149 " wrapping around (mod 256).",
1151 "Subtract The result of image - image window, with underflow",
1152 " wrapping around (mod 256). The add and subtract",
1153 " operators can be used to perform reversible",
1154 " transformations.",
1157 " The result of abs(image - image window). This",
1158 " useful for comparing two very similar images.",
1160 "Copy The resulting image is image window replaced with",
1161 " image. Here the matte information is ignored.",
1163 "CopyRed The red layer of the image window is replace with",
1164 " the red layer of the image. The other layers are",
1168 " The green layer of the image window is replace with",
1169 " the green layer of the image. The other layers are",
1172 "CopyBlue The blue layer of the image window is replace with",
1173 " the blue layer of the image. The other layers are",
1177 " The matte layer of the image window is replace with",
1178 " the matte layer of the image. The other layers are",
1181 "The image compositor requires a matte, or alpha channel in",
1182 "the image for some operations. This extra channel usually",
1183 "defines a mask which represents a sort of a cookie-cutter",
1184 "for the image. This the case when matte is opaque (full",
1185 "coverage) for pixels inside the shape, zero outside, and",
1186 "between 0 and QuantumRange on the boundary. If image does not",
1187 "have a matte channel, it is initialized with 0 for any pixel",
1188 "matching in color to pixel location (0,0), otherwise QuantumRange.",
1190 "Note that matte information for image window is not retained",
1191 "for colormapped X server visuals (e.g. StaticColor,",
1192 "StaticColor, GrayScale, PseudoColor). Correct compositing",
1193 "behavior may require a TrueColor or DirectColor visual or a",
1194 "Standard Colormap.",
1196 "Choosing a composite operator is optional. The default",
1197 "operator is replace. However, you must choose a location to",
1198 "paste your image and press button 1. Press and hold the",
1199 "button before releasing and an outline of the image will",
1200 "appear to help you identify your location.",
1202 "The actual colors of the pasted image is saved. However,",
1203 "the color that appears in image window may be different.",
1204 "For example, on a monochrome screen image window will appear",
1205 "black or white even though your pasted image may have",
1206 "many colors. If the image is saved to a file it is written",
1207 "with the correct colors. To assure the correct colors are",
1208 "saved in the final image, any PseudoClass image is promoted",
1209 "to DirectClass (see miff(5)). To force a PseudoClass image",
1210 "to remain PseudoClass, use -colors.",
1215 "In region of interest mode, the Command widget has these",
1221 "To define a region of interest, press button 1 and drag.",
1222 "The region of interest is defined by a highlighted rectangle",
1223 "that expands or contracts as it follows the pointer. Once",
1224 "you are satisfied with the region of interest, release the",
1225 "button. You are now in apply mode. In apply mode the",
1226 "Command widget has these options:",
1246 " Contrast Stretch",
1247 " Sigmoidal Contrast...",
1274 " Charcoal Drawing...",
1284 "You can make adjustments to the region of interest by moving",
1285 "the pointer to one of the rectangle corners, pressing a",
1286 "button, and dragging. Finally, choose an image processing",
1287 "technique from the Command widget. You can choose more than",
1288 "one image processing technique to apply to an area.",
1289 "Alternatively, you can move the region of interest before",
1290 "applying another image processing technique. To exit, press",
1294 *ImageRotateHelp[] =
1296 "In rotate mode, the Command widget has these options:",
1315 "Choose a background color from the Pixel Color sub-menu.",
1316 "Additional background colors can be specified with the color",
1317 "browser. You can change the menu colors by setting the X",
1318 "resources pen1 through pen9.",
1320 "If you choose the color browser and press Grab, you can",
1321 "select the background color by moving the pointer to the",
1322 "desired color on the screen and press any button.",
1324 "Choose a point in the image window and press this button and",
1325 "hold. Next, move the pointer to another location in the",
1326 "image. As you move a line connects the initial location and",
1327 "the pointer. When you release the button, the degree of",
1328 "image rotation is determined by the slope of the line you",
1329 "just drew. The slope is relative to the direction you",
1330 "choose from the Direction sub-menu of the Command widget.",
1332 "To cancel the image rotation, move the pointer back to the",
1333 "starting point of the line and release the button.",
1338 Enumeration declarations.
1357 VisualDirectoryCommand,
1365 OriginalSizeCommand,
1387 ContrastStretchCommand,
1388 SigmoidalContrastCommand,
1414 CharcoalDrawCommand,
1424 RegionofInterestCommand,
1430 ShowHistogramCommand,
1436 BrowseDocumentationCommand,
1438 SaveToUndoBufferCommand,
1445 AnnotateNameCommand,
1446 AnnotateFontColorCommand,
1447 AnnotateBackgroundColorCommand,
1448 AnnotateRotateCommand,
1449 AnnotateHelpCommand,
1450 AnnotateDismissCommand,
1453 ChopDirectionCommand,
1456 HorizontalChopCommand,
1457 VerticalChopCommand,
1458 ColorEditMethodCommand,
1459 ColorEditColorCommand,
1460 ColorEditBorderCommand,
1461 ColorEditFuzzCommand,
1462 ColorEditUndoCommand,
1463 ColorEditHelpCommand,
1464 ColorEditDismissCommand,
1465 CompositeOperatorsCommand,
1466 CompositeDissolveCommand,
1467 CompositeDisplaceCommand,
1468 CompositeHelpCommand,
1469 CompositeDismissCommand,
1474 RectifyDismissCommand,
1483 MatteEditBorderCommand,
1484 MatteEditFuzzCommand,
1485 MatteEditValueCommand,
1486 MatteEditUndoCommand,
1487 MatteEditHelpCommand,
1488 MatteEditDismissCommand,
1489 PasteOperatorsCommand,
1491 PasteDismissCommand,
1493 RotateDirectionCommand,
1495 RotateSharpenCommand,
1497 RotateDismissCommand,
1498 HorizontalRotateCommand,
1499 VerticalRotateCommand,
1510 #define BricksWidth 20
1511 #define BricksHeight 20
1512 #define DiagonalWidth 16
1513 #define DiagonalHeight 16
1514 #define HighlightWidth 8
1515 #define HighlightHeight 8
1516 #define OpaqueWidth 8
1517 #define OpaqueHeight 8
1518 #define ScalesWidth 16
1519 #define ScalesHeight 16
1520 #define ShadowWidth 8
1521 #define ShadowHeight 8
1522 #define VerticalWidth 16
1523 #define VerticalHeight 16
1524 #define WavyWidth 16
1525 #define WavyHeight 16
1528 Constant declaration.
1533 static const unsigned char
1536 0xff, 0xff, 0x0f, 0x03, 0x0c, 0x00, 0x03, 0x0c, 0x00, 0x03, 0x0c, 0x00,
1537 0x03, 0x0c, 0x00, 0xff, 0xff, 0x0f, 0x60, 0x80, 0x01, 0x60, 0x80, 0x01,
1538 0x60, 0x80, 0x01, 0x60, 0x80, 0x01, 0xff, 0xff, 0x0f, 0x03, 0x0c, 0x00,
1539 0x03, 0x0c, 0x00, 0x03, 0x0c, 0x00, 0x03, 0x0c, 0x00, 0xff, 0xff, 0x0f,
1540 0x60, 0x80, 0x01, 0x60, 0x80, 0x01, 0x60, 0x80, 0x01, 0x60, 0x80, 0x01
1544 0x44, 0x44, 0x88, 0x88, 0x11, 0x11, 0x22, 0x22, 0x44, 0x44, 0x88, 0x88,
1545 0x11, 0x11, 0x22, 0x22, 0x44, 0x44, 0x88, 0x88, 0x11, 0x11, 0x22, 0x22,
1546 0x44, 0x44, 0x88, 0x88, 0x11, 0x11, 0x22, 0x22
1550 0x08, 0x08, 0x08, 0x08, 0x14, 0x14, 0xe3, 0xe3, 0x80, 0x80, 0x80, 0x80,
1551 0x41, 0x41, 0x3e, 0x3e, 0x08, 0x08, 0x08, 0x08, 0x14, 0x14, 0xe3, 0xe3,
1552 0x80, 0x80, 0x80, 0x80, 0x41, 0x41, 0x3e, 0x3e
1556 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
1557 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
1558 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
1562 0xfe, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfd, 0xff, 0xfd, 0xff, 0xfb, 0xff,
1563 0xe7, 0xff, 0x1f, 0xff, 0xff, 0xf8, 0xff, 0xe7, 0xff, 0xdf, 0xff, 0xbf,
1564 0xff, 0xbf, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f
1568 Function prototypes.
1571 XImageWindowCommand(Display *,XResourceInfo *,XWindows *,
1572 const MagickStatusType,KeySym,Image **,ExceptionInfo *);
1575 *XMagickCommand(Display *,XResourceInfo *,XWindows *,const CommandType,
1576 Image **,ExceptionInfo *),
1577 *XOpenImage(Display *,XResourceInfo *,XWindows *,const MagickBooleanType),
1578 *XTileImage(Display *,XResourceInfo *,XWindows *,Image *,XEvent *,
1580 *XVisualDirectoryImage(Display *,XResourceInfo *,XWindows *,
1583 static MagickBooleanType
1584 XAnnotateEditImage(Display *,XResourceInfo *,XWindows *,Image *,
1586 XBackgroundImage(Display *,XResourceInfo *,XWindows *,Image **,
1588 XChopImage(Display *,XResourceInfo *,XWindows *,Image **,
1590 XCropImage(Display *,XResourceInfo *,XWindows *,Image *,const ClipboardMode,
1592 XColorEditImage(Display *,XResourceInfo *,XWindows *,Image **,
1594 XCompositeImage(Display *,XResourceInfo *,XWindows *,Image *,
1596 XConfigureImage(Display *,XResourceInfo *,XWindows *,Image *,ExceptionInfo *),
1597 XDrawEditImage(Display *,XResourceInfo *,XWindows *,Image **,
1599 XMatteEditImage(Display *,XResourceInfo *,XWindows *,Image **,
1601 XPasteImage(Display *,XResourceInfo *,XWindows *,Image *,ExceptionInfo *),
1602 XPrintImage(Display *,XResourceInfo *,XWindows *,Image *,ExceptionInfo *),
1603 XRotateImage(Display *,XResourceInfo *,XWindows *,double,Image **,
1605 XROIImage(Display *,XResourceInfo *,XWindows *,Image **,ExceptionInfo *),
1606 XSaveImage(Display *,XResourceInfo *,XWindows *,Image *,ExceptionInfo *),
1607 XTrimImage(Display *,XResourceInfo *,XWindows *,Image *,ExceptionInfo *);
1610 XDrawPanRectangle(Display *,XWindows *),
1611 XImageCache(Display *,XResourceInfo *,XWindows *,const CommandType,Image **,
1613 XMagnifyImage(Display *,XWindows *,XEvent *,ExceptionInfo *),
1614 XMakePanImage(Display *,XResourceInfo *,XWindows *,Image *,ExceptionInfo *),
1615 XPanImage(Display *,XWindows *,XEvent *,ExceptionInfo *),
1616 XMagnifyWindowCommand(Display *,XWindows *,const MagickStatusType,
1617 const KeySym,ExceptionInfo *),
1618 XSetCropGeometry(Display *,XWindows *,RectangleInfo *,Image *),
1619 XScreenEvent(Display *,XWindows *,XEvent *,ExceptionInfo *),
1620 XTranslateImage(Display *,XWindows *,Image *,const KeySym);
1623 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1627 % D i s p l a y I m a g e s %
1631 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1633 % DisplayImages() displays an image sequence to any X window screen. It
1634 % returns a value other than 0 if successful. Check the exception member
1635 % of image to determine the reason for any failure.
1637 % The format of the DisplayImages method is:
1639 % MagickBooleanType DisplayImages(const ImageInfo *image_info,
1640 % Image *images,ExceptionInfo *exception)
1642 % A description of each parameter follows:
1644 % o image_info: the image info.
1646 % o image: the image.
1648 % o exception: return any errors or warnings in this structure.
1651 MagickExport MagickBooleanType DisplayImages(const ImageInfo *image_info,
1652 Image *images,ExceptionInfo *exception)
1675 assert(image_info != (const ImageInfo *) NULL);
1676 assert(image_info->signature == MagickSignature);
1677 assert(images != (Image *) NULL);
1678 assert(images->signature == MagickSignature);
1679 if (IfMagickTrue(images->debug) )
1680 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",images->filename);
1681 display=XOpenDisplay(image_info->server_name);
1682 if (display == (Display *) NULL)
1684 (void) ThrowMagickException(exception,GetMagickModule(),XServerError,
1685 "UnableToOpenXServer","`%s'",XDisplayName(image_info->server_name));
1686 return(MagickFalse);
1688 if (exception->severity != UndefinedException)
1689 CatchException(exception);
1690 (void) XSetErrorHandler(XError);
1691 resource_database=XGetResourceDatabase(display,GetClientName());
1692 (void) ResetMagickMemory(&resource_info,0,sizeof(resource_info));
1693 XGetResourceInfo(image_info,resource_database,GetClientName(),&resource_info);
1694 if (image_info->page != (char *) NULL)
1695 resource_info.image_geometry=AcquireString(image_info->page);
1696 resource_info.immutable=MagickTrue;
1697 argv[0]=AcquireString(GetClientName());
1699 for (i=0; (state & ExitState) == 0; i++)
1701 if ((images->iterations != 0) && (i >= (ssize_t) images->iterations))
1703 image=GetImageFromList(images,i % GetImageListLength(images));
1704 (void) XDisplayImage(display,&resource_info,argv,1,&image,&state,exception);
1706 (void) SetErrorHandler((ErrorHandler) NULL);
1707 (void) SetWarningHandler((WarningHandler) NULL);
1708 argv[0]=DestroyString(argv[0]);
1709 (void) XCloseDisplay(display);
1710 XDestroyResourceInfo(&resource_info);
1711 if (exception->severity != UndefinedException)
1712 return(MagickFalse);
1717 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1721 % R e m o t e D i s p l a y C o m m a n d %
1725 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1727 % RemoteDisplayCommand() encourages a remote display program to display the
1728 % specified image filename.
1730 % The format of the RemoteDisplayCommand method is:
1732 % MagickBooleanType RemoteDisplayCommand(const ImageInfo *image_info,
1733 % const char *window,const char *filename,ExceptionInfo *exception)
1735 % A description of each parameter follows:
1737 % o image_info: the image info.
1739 % o window: Specifies the name or id of an X window.
1741 % o filename: the name of the image filename to display.
1743 % o exception: return any errors or warnings in this structure.
1746 MagickExport MagickBooleanType RemoteDisplayCommand(const ImageInfo *image_info,
1747 const char *window,const char *filename,ExceptionInfo *exception)
1755 assert(image_info != (const ImageInfo *) NULL);
1756 assert(image_info->signature == MagickSignature);
1757 assert(filename != (char *) NULL);
1758 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
1759 display=XOpenDisplay(image_info->server_name);
1760 if (display == (Display *) NULL)
1762 (void) ThrowMagickException(exception,GetMagickModule(),XServerError,
1763 "UnableToOpenXServer","`%s'",XDisplayName(image_info->server_name));
1764 return(MagickFalse);
1766 (void) XSetErrorHandler(XError);
1767 status=XRemoteCommand(display,window,filename);
1768 (void) XCloseDisplay(display);
1769 return(IsMagickTrue(status));
1773 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1777 + X A n n o t a t e E d i t I m a g e %
1781 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1783 % XAnnotateEditImage() annotates the image with text.
1785 % The format of the XAnnotateEditImage method is:
1787 % MagickBooleanType XAnnotateEditImage(Display *display,
1788 % XResourceInfo *resource_info,XWindows *windows,Image *image,
1789 % ExceptionInfo *exception)
1791 % A description of each parameter follows:
1793 % o display: Specifies a connection to an X server; returned from
1796 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1798 % o windows: Specifies a pointer to a XWindows structure.
1800 % o image: the image; returned from ReadImage.
1804 static inline ssize_t MagickMax(const ssize_t x,const ssize_t y)
1811 static inline ssize_t MagickMin(const ssize_t x,const ssize_t y)
1818 static MagickBooleanType XAnnotateEditImage(Display *display,
1819 XResourceInfo *resource_info,XWindows *windows,Image *image,
1820 ExceptionInfo *exception)
1840 static const ModeType
1841 AnnotateCommands[] =
1843 AnnotateNameCommand,
1844 AnnotateFontColorCommand,
1845 AnnotateBackgroundColorCommand,
1846 AnnotateRotateCommand,
1847 AnnotateHelpCommand,
1848 AnnotateDismissCommand
1856 static MagickBooleanType
1857 transparent_box = MagickTrue,
1858 transparent_pen = MagickFalse;
1864 box_id = MaxNumberPens-2,
1869 command[MaxTextExtent],
1870 text[MaxTextExtent];
1873 *ColorMenu[MaxNumberPens+1];
1921 (void) CloneString(&windows->command.name,"Annotate");
1922 windows->command.data=4;
1923 (void) XCommandWidget(display,windows,AnnotateMenu,(XEvent *) NULL);
1924 (void) XMapRaised(display,windows->command.id);
1925 XClientMessage(display,windows->image.id,windows->im_protocols,
1926 windows->im_update_widget,CurrentTime);
1928 Track pointer until button 1 is pressed.
1930 XQueryPosition(display,windows->image.id,&x,&y);
1931 (void) XSelectInput(display,windows->image.id,
1932 windows->image.attributes.event_mask | PointerMotionMask);
1933 cursor=XCreateFontCursor(display,XC_left_side);
1934 (void) XCheckDefineCursor(display,windows->image.id,cursor);
1938 if (IfMagickTrue(windows->info.mapped) )
1941 Display pointer position.
1943 (void) FormatLocaleString(text,MaxTextExtent," %+d%+d ",
1944 x+windows->image.x,y+windows->image.y);
1945 XInfoWidget(display,windows,text);
1948 Wait for next event.
1950 XScreenEvent(display,windows,&event,exception);
1951 if (event.xany.window == windows->command.id)
1954 Select a command from the Command widget.
1956 id=XCommandWidget(display,windows,AnnotateMenu,&event);
1957 (void) XCheckDefineCursor(display,windows->image.id,cursor);
1960 switch (AnnotateCommands[id])
1962 case AnnotateNameCommand:
1965 *FontMenu[MaxNumberFonts];
1971 Initialize menu selections.
1973 for (i=0; i < MaxNumberFonts; i++)
1974 FontMenu[i]=resource_info->font_name[i];
1975 FontMenu[MaxNumberFonts-2]="Browser...";
1976 FontMenu[MaxNumberFonts-1]=(const char *) NULL;
1978 Select a font name from the pop-up menu.
1980 font_number=XMenuWidget(display,windows,AnnotateMenu[id],
1981 (const char **) FontMenu,command);
1982 if (font_number < 0)
1984 if (font_number == (MaxNumberFonts-2))
1987 font_name[MaxTextExtent] = "fixed";
1990 Select a font name from a browser.
1992 resource_info->font_name[font_number]=font_name;
1993 XFontBrowserWidget(display,windows,"Select",font_name);
1994 if (*font_name == '\0')
1998 Initialize font info.
2000 font_info=XLoadQueryFont(display,resource_info->font_name[
2002 if (font_info == (XFontStruct *) NULL)
2004 XNoticeWidget(display,windows,"Unable to load font:",
2005 resource_info->font_name[font_number]);
2008 font_id=(unsigned int) font_number;
2009 (void) XFreeFont(display,font_info);
2012 case AnnotateFontColorCommand:
2015 Initialize menu selections.
2017 for (i=0; i < (int) (MaxNumberPens-2); i++)
2018 ColorMenu[i]=resource_info->pen_colors[i];
2019 ColorMenu[MaxNumberPens-2]="transparent";
2020 ColorMenu[MaxNumberPens-1]="Browser...";
2021 ColorMenu[MaxNumberPens]=(const char *) NULL;
2023 Select a pen color from the pop-up menu.
2025 pen_number=XMenuWidget(display,windows,AnnotateMenu[id],
2026 (const char **) ColorMenu,command);
2029 transparent_pen=pen_number == (MaxNumberPens-2) ? MagickTrue :
2031 if (IfMagickTrue(transparent_pen) )
2033 if (pen_number == (MaxNumberPens-1))
2036 color_name[MaxTextExtent] = "gray";
2039 Select a pen color from a dialog.
2041 resource_info->pen_colors[pen_number]=color_name;
2042 XColorBrowserWidget(display,windows,"Select",color_name);
2043 if (*color_name == '\0')
2049 (void) XParseColor(display,windows->map_info->colormap,
2050 resource_info->pen_colors[pen_number],&color);
2051 XBestPixel(display,windows->map_info->colormap,(XColor *) NULL,
2052 (unsigned int) MaxColors,&color);
2053 windows->pixel_info->pen_colors[pen_number]=color;
2054 pen_id=(unsigned int) pen_number;
2057 case AnnotateBackgroundColorCommand:
2060 Initialize menu selections.
2062 for (i=0; i < (int) (MaxNumberPens-2); i++)
2063 ColorMenu[i]=resource_info->pen_colors[i];
2064 ColorMenu[MaxNumberPens-2]="transparent";
2065 ColorMenu[MaxNumberPens-1]="Browser...";
2066 ColorMenu[MaxNumberPens]=(const char *) NULL;
2068 Select a pen color from the pop-up menu.
2070 pen_number=XMenuWidget(display,windows,AnnotateMenu[id],
2071 (const char **) ColorMenu,command);
2074 transparent_box=pen_number == (MaxNumberPens-2) ? MagickTrue :
2076 if (IfMagickTrue(transparent_box) )
2078 if (pen_number == (MaxNumberPens-1))
2081 color_name[MaxTextExtent] = "gray";
2084 Select a pen color from a dialog.
2086 resource_info->pen_colors[pen_number]=color_name;
2087 XColorBrowserWidget(display,windows,"Select",color_name);
2088 if (*color_name == '\0')
2094 (void) XParseColor(display,windows->map_info->colormap,
2095 resource_info->pen_colors[pen_number],&color);
2096 XBestPixel(display,windows->map_info->colormap,(XColor *) NULL,
2097 (unsigned int) MaxColors,&color);
2098 windows->pixel_info->pen_colors[pen_number]=color;
2099 box_id=(unsigned int) pen_number;
2102 case AnnotateRotateCommand:
2108 angle[MaxTextExtent] = "30.0";
2126 Select a command from the pop-up menu.
2128 entry=XMenuWidget(display,windows,AnnotateMenu[id],RotateMenu,
2134 degrees=StringToDouble(RotateMenu[entry],(char **) NULL);
2137 (void) XDialogWidget(display,windows,"OK","Enter rotation angle:",
2141 degrees=StringToDouble(angle,(char **) NULL);
2144 case AnnotateHelpCommand:
2146 XTextViewWidget(display,resource_info,windows,MagickFalse,
2147 "Help Viewer - Image Annotation",ImageAnnotateHelp);
2150 case AnnotateDismissCommand:
2168 if (event.xbutton.button != Button1)
2170 if (event.xbutton.window != windows->image.id)
2173 Change to text entering mode.
2186 if (event.xkey.window != windows->image.id)
2189 Respond to a user key press.
2191 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
2192 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
2193 switch ((int) key_symbol)
2208 XTextViewWidget(display,resource_info,windows,MagickFalse,
2209 "Help Viewer - Image Annotation",ImageAnnotateHelp);
2214 (void) XBell(display,0);
2223 Map and unmap Info widget as cursor crosses its boundaries.
2227 if (IfMagickTrue(windows->info.mapped) )
2229 if ((x < (int) (windows->info.x+windows->info.width)) &&
2230 (y < (int) (windows->info.y+windows->info.height)))
2231 (void) XWithdrawWindow(display,windows->info.id,
2232 windows->info.screen);
2235 if ((x > (int) (windows->info.x+windows->info.width)) ||
2236 (y > (int) (windows->info.y+windows->info.height)))
2237 (void) XMapWindow(display,windows->info.id);
2243 } while ((state & ExitState) == 0);
2244 (void) XSelectInput(display,windows->image.id,
2245 windows->image.attributes.event_mask);
2246 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
2247 if ((state & EscapeState) != 0)
2250 Set font info and check boundary conditions.
2252 font_info=XLoadQueryFont(display,resource_info->font_name[font_id]);
2253 if (font_info == (XFontStruct *) NULL)
2255 XNoticeWidget(display,windows,"Unable to load font:",
2256 resource_info->font_name[font_id]);
2257 font_info=windows->font_info;
2259 if ((x+font_info->max_bounds.width) >= (int) windows->image.width)
2260 x=(int) windows->image.width-font_info->max_bounds.width;
2261 if (y < (int) (font_info->ascent+font_info->descent))
2262 y=(int) font_info->ascent+font_info->descent;
2263 if (((int) font_info->max_bounds.width > (int) windows->image.width) ||
2264 ((font_info->ascent+font_info->descent) >= (int) windows->image.height))
2265 return(MagickFalse);
2267 Initialize annotate structure.
2269 annotate_info=(XAnnotateInfo *) AcquireMagickMemory(sizeof(*annotate_info));
2270 if (annotate_info == (XAnnotateInfo *) NULL)
2271 return(MagickFalse);
2272 XGetAnnotateInfo(annotate_info);
2275 if (IfMagickFalse(transparent_box) && IfMagickFalse(transparent_pen))
2276 annotate_info->stencil=OpaqueStencil;
2278 if (IfMagickFalse(transparent_box) )
2279 annotate_info->stencil=BackgroundStencil;
2281 annotate_info->stencil=ForegroundStencil;
2282 annotate_info->height=(unsigned int) font_info->ascent+font_info->descent;
2283 annotate_info->degrees=degrees;
2284 annotate_info->font_info=font_info;
2285 annotate_info->text=(char *) AcquireQuantumMemory((size_t)
2286 windows->image.width/MagickMax((ssize_t) font_info->min_bounds.width,1)+2UL,
2287 sizeof(*annotate_info->text));
2288 if (annotate_info->text == (char *) NULL)
2289 return(MagickFalse);
2291 Create cursor and set graphic context.
2293 cursor=XCreateFontCursor(display,XC_pencil);
2294 (void) XCheckDefineCursor(display,windows->image.id,cursor);
2295 annotate_context=windows->image.annotate_context;
2296 (void) XSetFont(display,annotate_context,font_info->fid);
2297 (void) XSetBackground(display,annotate_context,
2298 windows->pixel_info->pen_colors[box_id].pixel);
2299 (void) XSetForeground(display,annotate_context,
2300 windows->pixel_info->pen_colors[pen_id].pixel);
2302 Begin annotating the image with text.
2304 (void) CloneString(&windows->command.name,"Text");
2305 windows->command.data=0;
2306 (void) XCommandWidget(display,windows,TextMenu,(XEvent *) NULL);
2308 (void) XDrawString(display,windows->image.id,annotate_context,x,y,"_",1);
2309 text_event.xexpose.width=(int) font_info->max_bounds.width;
2310 text_event.xexpose.height=font_info->max_bounds.ascent+
2311 font_info->max_bounds.descent;
2312 p=annotate_info->text;
2316 Display text cursor.
2319 (void) XDrawString(display,windows->image.id,annotate_context,x,y,"_",1);
2321 Wait for next event.
2323 XScreenEvent(display,windows,&event,exception);
2324 if (event.xany.window == windows->command.id)
2327 Select a command from the Command widget.
2329 (void) XSetBackground(display,annotate_context,
2330 windows->pixel_info->background_color.pixel);
2331 (void) XSetForeground(display,annotate_context,
2332 windows->pixel_info->foreground_color.pixel);
2333 id=XCommandWidget(display,windows,AnnotateMenu,&event);
2334 (void) XSetBackground(display,annotate_context,
2335 windows->pixel_info->pen_colors[box_id].pixel);
2336 (void) XSetForeground(display,annotate_context,
2337 windows->pixel_info->pen_colors[pen_id].pixel);
2340 switch (TextCommands[id])
2342 case TextHelpCommand:
2344 XTextViewWidget(display,resource_info,windows,MagickFalse,
2345 "Help Viewer - Image Annotation",ImageAnnotateHelp);
2346 (void) XCheckDefineCursor(display,windows->image.id,cursor);
2349 case TextApplyCommand:
2352 Finished annotating.
2354 annotate_info->width=(unsigned int) XTextWidth(font_info,
2355 annotate_info->text,(int) strlen(annotate_info->text));
2356 XRefreshWindow(display,&windows->image,&text_event);
2368 text_event.xexpose.x=x;
2369 text_event.xexpose.y=y-font_info->max_bounds.ascent;
2370 (void) XClearArea(display,windows->image.id,x,text_event.xexpose.y,
2371 (unsigned int) text_event.xexpose.width,(unsigned int)
2372 text_event.xexpose.height,MagickFalse);
2373 XRefreshWindow(display,&windows->image,&text_event);
2378 if (event.xbutton.window != windows->image.id)
2380 if (event.xbutton.button == Button2)
2383 Request primary selection.
2385 (void) XConvertSelection(display,XA_PRIMARY,XA_STRING,XA_STRING,
2386 windows->image.id,CurrentTime);
2393 if (event.xexpose.count == 0)
2399 Refresh Image window.
2401 XRefreshWindow(display,&windows->image,(XEvent *) NULL);
2402 text_info=annotate_info;
2403 while (text_info != (XAnnotateInfo *) NULL)
2405 if (annotate_info->stencil == ForegroundStencil)
2406 (void) XDrawString(display,windows->image.id,annotate_context,
2407 text_info->x,text_info->y,text_info->text,
2408 (int) strlen(text_info->text));
2410 (void) XDrawImageString(display,windows->image.id,
2411 annotate_context,text_info->x,text_info->y,text_info->text,
2412 (int) strlen(text_info->text));
2413 text_info=text_info->previous;
2415 (void) XDrawString(display,windows->image.id,annotate_context,
2425 if (event.xkey.window != windows->image.id)
2428 Respond to a user key press.
2430 length=XLookupString((XKeyEvent *) &event.xkey,command,(int)
2431 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
2432 *(command+length)='\0';
2433 if (((event.xkey.state & ControlMask) != 0) ||
2434 ((event.xkey.state & Mod1Mask) != 0))
2435 state|=ModifierState;
2436 if ((state & ModifierState) != 0)
2437 switch ((int) key_symbol)
2442 key_symbol=DeleteCommand;
2448 switch ((int) key_symbol)
2453 Erase one character.
2455 if (p == annotate_info->text)
2457 if (annotate_info->previous == (XAnnotateInfo *) NULL)
2462 Go to end of the previous line of text.
2464 annotate_info=annotate_info->previous;
2465 p=annotate_info->text;
2466 x=annotate_info->x+annotate_info->width;
2468 if (annotate_info->width != 0)
2469 p+=strlen(annotate_info->text);
2474 x-=XTextWidth(font_info,p,1);
2475 text_event.xexpose.x=x;
2476 text_event.xexpose.y=y-font_info->max_bounds.ascent;
2477 XRefreshWindow(display,&windows->image,&text_event);
2480 case XK_bracketleft:
2482 key_symbol=XK_Escape;
2488 Erase the entire line of text.
2490 while (p != annotate_info->text)
2493 x-=XTextWidth(font_info,p,1);
2494 text_event.xexpose.x=x;
2495 XRefreshWindow(display,&windows->image,&text_event);
2503 Finished annotating.
2505 annotate_info->width=(unsigned int) XTextWidth(font_info,
2506 annotate_info->text,(int) strlen(annotate_info->text));
2507 XRefreshWindow(display,&windows->image,&text_event);
2514 Draw a single character on the Image window.
2516 if ((state & ModifierState) != 0)
2518 if (*command == '\0')
2521 if (annotate_info->stencil == ForegroundStencil)
2522 (void) XDrawString(display,windows->image.id,annotate_context,
2525 (void) XDrawImageString(display,windows->image.id,
2526 annotate_context,x,y,p,1);
2527 x+=XTextWidth(font_info,p,1);
2529 if ((x+font_info->max_bounds.width) < (int) windows->image.width)
2536 Advance to the next line of text.
2539 annotate_info->width=(unsigned int) XTextWidth(font_info,
2540 annotate_info->text,(int) strlen(annotate_info->text));
2541 if (annotate_info->next != (XAnnotateInfo *) NULL)
2544 Line of text already exists.
2546 annotate_info=annotate_info->next;
2549 p=annotate_info->text;
2552 annotate_info->next=(XAnnotateInfo *) AcquireMagickMemory(
2553 sizeof(*annotate_info->next));
2554 if (annotate_info->next == (XAnnotateInfo *) NULL)
2555 return(MagickFalse);
2556 *annotate_info->next=(*annotate_info);
2557 annotate_info->next->previous=annotate_info;
2558 annotate_info=annotate_info->next;
2559 annotate_info->text=(char *) AcquireQuantumMemory((size_t)
2560 windows->image.width/MagickMax((ssize_t)
2561 font_info->min_bounds.width,1)+2UL,sizeof(*annotate_info->text));
2562 if (annotate_info->text == (char *) NULL)
2563 return(MagickFalse);
2564 annotate_info->y+=annotate_info->height;
2565 if (annotate_info->y > (int) windows->image.height)
2566 annotate_info->y=(int) annotate_info->height;
2567 annotate_info->next=(XAnnotateInfo *) NULL;
2570 p=annotate_info->text;
2579 Respond to a user key release.
2581 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
2582 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
2583 state&=(~ModifierState);
2586 case SelectionNotify:
2602 Obtain response from primary selection.
2604 if (event.xselection.property == (Atom) None)
2606 status=XGetWindowProperty(display,event.xselection.requestor,
2607 event.xselection.property,0L,(long) MaxTextExtent,True,XA_STRING,
2608 &type,&format,&length,&after,&data);
2609 if ((status != Success) || (type != XA_STRING) || (format == 32) ||
2613 Annotate Image window with primary selection.
2615 for (i=0; i < (ssize_t) length; i++)
2617 if ((char) data[i] != '\n')
2620 Draw a single character on the Image window.
2623 (void) XDrawString(display,windows->image.id,annotate_context,
2625 x+=XTextWidth(font_info,p,1);
2627 if ((x+font_info->max_bounds.width) < (int) windows->image.width)
2631 Advance to the next line of text.
2634 annotate_info->width=(unsigned int) XTextWidth(font_info,
2635 annotate_info->text,(int) strlen(annotate_info->text));
2636 if (annotate_info->next != (XAnnotateInfo *) NULL)
2639 Line of text already exists.
2641 annotate_info=annotate_info->next;
2644 p=annotate_info->text;
2647 annotate_info->next=(XAnnotateInfo *) AcquireMagickMemory(
2648 sizeof(*annotate_info->next));
2649 if (annotate_info->next == (XAnnotateInfo *) NULL)
2650 return(MagickFalse);
2651 *annotate_info->next=(*annotate_info);
2652 annotate_info->next->previous=annotate_info;
2653 annotate_info=annotate_info->next;
2654 annotate_info->text=(char *) AcquireQuantumMemory((size_t)
2655 windows->image.width/MagickMax((ssize_t)
2656 font_info->min_bounds.width,1)+2UL,sizeof(*annotate_info->text));
2657 if (annotate_info->text == (char *) NULL)
2658 return(MagickFalse);
2659 annotate_info->y+=annotate_info->height;
2660 if (annotate_info->y > (int) windows->image.height)
2661 annotate_info->y=(int) annotate_info->height;
2662 annotate_info->next=(XAnnotateInfo *) NULL;
2665 p=annotate_info->text;
2667 (void) XFree((void *) data);
2673 } while ((state & ExitState) == 0);
2674 (void) XFreeCursor(display,cursor);
2676 Annotation is relative to image configuration.
2678 width=(unsigned int) image->columns;
2679 height=(unsigned int) image->rows;
2682 if (windows->image.crop_geometry != (char *) NULL)
2683 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
2685 Initialize annotated image.
2687 XSetCursorState(display,windows,MagickTrue);
2688 XCheckRefreshWindows(display,windows);
2689 while (annotate_info != (XAnnotateInfo *) NULL)
2691 if (annotate_info->width == 0)
2694 No text on this line-- go to the next line of text.
2696 previous_info=annotate_info->previous;
2697 annotate_info->text=(char *)
2698 RelinquishMagickMemory(annotate_info->text);
2699 annotate_info=(XAnnotateInfo *) RelinquishMagickMemory(annotate_info);
2700 annotate_info=previous_info;
2704 Determine pixel index for box and pen color.
2706 windows->pixel_info->box_color=windows->pixel_info->pen_colors[box_id];
2707 if (windows->pixel_info->colors != 0)
2708 for (i=0; i < (ssize_t) windows->pixel_info->colors; i++)
2709 if (windows->pixel_info->pixels[i] ==
2710 windows->pixel_info->pen_colors[box_id].pixel)
2712 windows->pixel_info->box_index=(unsigned short) i;
2715 windows->pixel_info->pen_color=windows->pixel_info->pen_colors[pen_id];
2716 if (windows->pixel_info->colors != 0)
2717 for (i=0; i < (ssize_t) windows->pixel_info->colors; i++)
2718 if (windows->pixel_info->pixels[i] ==
2719 windows->pixel_info->pen_colors[pen_id].pixel)
2721 windows->pixel_info->pen_index=(unsigned short) i;
2725 Define the annotate geometry string.
2727 annotate_info->x=(int)
2728 width*(annotate_info->x+windows->image.x)/windows->image.ximage->width;
2729 annotate_info->y=(int) height*(annotate_info->y-font_info->ascent+
2730 windows->image.y)/windows->image.ximage->height;
2731 (void) FormatLocaleString(annotate_info->geometry,MaxTextExtent,
2732 "%ux%u%+d%+d",width*annotate_info->width/windows->image.ximage->width,
2733 height*annotate_info->height/windows->image.ximage->height,
2734 annotate_info->x+x,annotate_info->y+y);
2736 Annotate image with text.
2738 status=XAnnotateImage(display,windows->pixel_info,annotate_info,image,
2741 return(MagickFalse);
2745 previous_info=annotate_info->previous;
2746 annotate_info->text=DestroyString(annotate_info->text);
2747 annotate_info=(XAnnotateInfo *) RelinquishMagickMemory(annotate_info);
2748 annotate_info=previous_info;
2750 (void) XSetForeground(display,annotate_context,
2751 windows->pixel_info->foreground_color.pixel);
2752 (void) XSetBackground(display,annotate_context,
2753 windows->pixel_info->background_color.pixel);
2754 (void) XSetFont(display,annotate_context,windows->font_info->fid);
2755 XSetCursorState(display,windows,MagickFalse);
2756 (void) XFreeFont(display,font_info);
2758 Update image configuration.
2760 XConfigureImageColormap(display,resource_info,windows,image,exception);
2761 (void) XConfigureImage(display,resource_info,windows,image,exception);
2766 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2770 + X B a c k g r o u n d I m a g e %
2774 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2776 % XBackgroundImage() displays the image in the background of a window.
2778 % The format of the XBackgroundImage method is:
2780 % MagickBooleanType XBackgroundImage(Display *display,
2781 % XResourceInfo *resource_info,XWindows *windows,Image **image,
2782 % ExceptionInfo *exception)
2784 % A description of each parameter follows:
2786 % o display: Specifies a connection to an X server; returned from
2789 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
2791 % o windows: Specifies a pointer to a XWindows structure.
2793 % o image: the image.
2795 % o exception: return any errors or warnings in this structure.
2798 static MagickBooleanType XBackgroundImage(Display *display,
2799 XResourceInfo *resource_info,XWindows *windows,Image **image,
2800 ExceptionInfo *exception)
2802 #define BackgroundImageTag "Background/Image"
2808 window_id[MaxTextExtent] = "root";
2811 background_resources;
2814 Put image in background.
2816 status=XDialogWidget(display,windows,"Background",
2817 "Enter window id (id 0x00 selects window with pointer):",window_id);
2818 if (*window_id == '\0')
2819 return(MagickFalse);
2820 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image,
2822 XInfoWidget(display,windows,BackgroundImageTag);
2823 XSetCursorState(display,windows,MagickTrue);
2824 XCheckRefreshWindows(display,windows);
2825 background_resources=(*resource_info);
2826 background_resources.window_id=window_id;
2827 background_resources.backdrop=IsMagickTrue(status);
2828 status=XDisplayBackgroundImage(display,&background_resources,*image,
2830 if (IfMagickTrue(status))
2831 XClientMessage(display,windows->image.id,windows->im_protocols,
2832 windows->im_retain_colors,CurrentTime);
2833 XSetCursorState(display,windows,MagickFalse);
2834 (void) XMagickCommand(display,resource_info,windows,UndoCommand,image,
2840 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2844 + X C h o p I m a g e %
2848 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2850 % XChopImage() chops the X image.
2852 % The format of the XChopImage method is:
2854 % MagickBooleanType XChopImage(Display *display,XResourceInfo *resource_info,
2855 % XWindows *windows,Image **image,ExceptionInfo *exception)
2857 % A description of each parameter follows:
2859 % o display: Specifies a connection to an X server; returned from
2862 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
2864 % o windows: Specifies a pointer to a XWindows structure.
2866 % o image: the image.
2868 % o exception: return any errors or warnings in this structure.
2871 static MagickBooleanType XChopImage(Display *display,
2872 XResourceInfo *resource_info,XWindows *windows,Image **image,
2873 ExceptionInfo *exception)
2885 direction = HorizontalChopCommand;
2887 static const ModeType
2890 ChopDirectionCommand,
2894 DirectionCommands[] =
2896 HorizontalChopCommand,
2901 text[MaxTextExtent];
2934 (void) CloneString(&windows->command.name,"Chop");
2935 windows->command.data=1;
2936 (void) XCommandWidget(display,windows,ChopMenu,(XEvent *) NULL);
2937 (void) XMapRaised(display,windows->command.id);
2938 XClientMessage(display,windows->image.id,windows->im_protocols,
2939 windows->im_update_widget,CurrentTime);
2941 Track pointer until button 1 is pressed.
2943 XQueryPosition(display,windows->image.id,&x,&y);
2944 (void) XSelectInput(display,windows->image.id,
2945 windows->image.attributes.event_mask | PointerMotionMask);
2949 if (IfMagickTrue(windows->info.mapped) )
2952 Display pointer position.
2954 (void) FormatLocaleString(text,MaxTextExtent," %+d%+d ",
2955 x+windows->image.x,y+windows->image.y);
2956 XInfoWidget(display,windows,text);
2959 Wait for next event.
2961 XScreenEvent(display,windows,&event,exception);
2962 if (event.xany.window == windows->command.id)
2965 Select a command from the Command widget.
2967 id=XCommandWidget(display,windows,ChopMenu,&event);
2970 switch (ChopCommands[id])
2972 case ChopDirectionCommand:
2975 command[MaxTextExtent];
2986 Select a command from the pop-up menu.
2988 id=XMenuWidget(display,windows,ChopMenu[id],Directions,command);
2990 direction=DirectionCommands[id];
2993 case ChopHelpCommand:
2995 XTextViewWidget(display,resource_info,windows,MagickFalse,
2996 "Help Viewer - Image Chop",ImageChopHelp);
2999 case ChopDismissCommand:
3017 if (event.xbutton.button != Button1)
3019 if (event.xbutton.window != windows->image.id)
3022 User has committed to start point of chopping line.
3024 segment_info.x1=(short int) event.xbutton.x;
3025 segment_info.x2=(short int) event.xbutton.x;
3026 segment_info.y1=(short int) event.xbutton.y;
3027 segment_info.y2=(short int) event.xbutton.y;
3038 command[MaxTextExtent];
3043 if (event.xkey.window != windows->image.id)
3046 Respond to a user key press.
3048 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
3049 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
3050 switch ((int) key_symbol)
3065 (void) XSetFunction(display,windows->image.highlight_context,
3067 XTextViewWidget(display,resource_info,windows,MagickFalse,
3068 "Help Viewer - Image Chop",ImageChopHelp);
3069 (void) XSetFunction(display,windows->image.highlight_context,
3075 (void) XBell(display,0);
3084 Map and unmap Info widget as text cursor crosses its boundaries.
3088 if (IfMagickTrue(windows->info.mapped) )
3090 if ((x < (int) (windows->info.x+windows->info.width)) &&
3091 (y < (int) (windows->info.y+windows->info.height)))
3092 (void) XWithdrawWindow(display,windows->info.id,
3093 windows->info.screen);
3096 if ((x > (int) (windows->info.x+windows->info.width)) ||
3097 (y > (int) (windows->info.y+windows->info.height)))
3098 (void) XMapWindow(display,windows->info.id);
3101 } while ((state & ExitState) == 0);
3102 (void) XSelectInput(display,windows->image.id,
3103 windows->image.attributes.event_mask);
3104 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
3105 if ((state & EscapeState) != 0)
3108 Draw line as pointer moves until the mouse button is released.
3115 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
3122 Display info and draw chopping line.
3124 if (IfMagickFalse(windows->info.mapped) )
3125 (void) XMapWindow(display,windows->info.id);
3126 (void) FormatLocaleString(text,MaxTextExtent,
3127 " %.20gx%.20g%+.20g%+.20g",(double) chop_info.width,(double)
3128 chop_info.height,(double) chop_info.x,(double) chop_info.y);
3129 XInfoWidget(display,windows,text);
3130 XHighlightLine(display,windows->image.id,
3131 windows->image.highlight_context,&segment_info);
3134 if (IfMagickTrue(windows->info.mapped) )
3135 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
3137 Wait for next event.
3139 XScreenEvent(display,windows,&event,exception);
3141 XHighlightLine(display,windows->image.id,
3142 windows->image.highlight_context,&segment_info);
3147 segment_info.x2=(short int) event.xmotion.x;
3148 segment_info.y2=(short int) event.xmotion.y;
3154 User has committed to chopping line.
3156 segment_info.x2=(short int) event.xbutton.x;
3157 segment_info.y2=(short int) event.xbutton.y;
3165 segment_info.x2=(short int) event.xmotion.x;
3166 segment_info.y2=(short int) event.xmotion.y;
3172 Check boundary conditions.
3174 if (segment_info.x2 < 0)
3177 if (segment_info.x2 > windows->image.ximage->width)
3178 segment_info.x2=windows->image.ximage->width;
3179 if (segment_info.y2 < 0)
3182 if (segment_info.y2 > windows->image.ximage->height)
3183 segment_info.y2=windows->image.ximage->height;
3184 distance=(unsigned int)
3185 (((segment_info.x2-segment_info.x1)*(segment_info.x2-segment_info.x1))+
3186 ((segment_info.y2-segment_info.y1)*(segment_info.y2-segment_info.y1)));
3188 Compute chopping geometry.
3190 if (direction == HorizontalChopCommand)
3192 chop_info.width=(size_t) (segment_info.x2-segment_info.x1+1);
3193 chop_info.x=(ssize_t) windows->image.x+segment_info.x1;
3196 if (segment_info.x1 > (int) segment_info.x2)
3198 chop_info.width=(size_t) (segment_info.x1-segment_info.x2+1);
3199 chop_info.x=(ssize_t) windows->image.x+segment_info.x2;
3205 chop_info.height=(size_t) (segment_info.y2-segment_info.y1+1);
3207 chop_info.y=(ssize_t) windows->image.y+segment_info.y1;
3208 if (segment_info.y1 > segment_info.y2)
3210 chop_info.height=(size_t) (segment_info.y1-segment_info.y2+1);
3211 chop_info.y=(ssize_t) windows->image.y+segment_info.y2;
3214 } while ((state & ExitState) == 0);
3215 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
3216 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
3220 Image chopping is relative to image configuration.
3222 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image,
3224 XSetCursorState(display,windows,MagickTrue);
3225 XCheckRefreshWindows(display,windows);
3226 windows->image.window_changes.width=windows->image.ximage->width-
3227 (unsigned int) chop_info.width;
3228 windows->image.window_changes.height=windows->image.ximage->height-
3229 (unsigned int) chop_info.height;
3230 width=(unsigned int) (*image)->columns;
3231 height=(unsigned int) (*image)->rows;
3234 if (windows->image.crop_geometry != (char *) NULL)
3235 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
3236 scale_factor=(double) width/windows->image.ximage->width;
3238 chop_info.x=(ssize_t) (scale_factor*chop_info.x+0.5);
3239 chop_info.width=(unsigned int) (scale_factor*chop_info.width+0.5);
3240 scale_factor=(double) height/windows->image.ximage->height;
3242 chop_info.y=(ssize_t) (scale_factor*chop_info.y+0.5);
3243 chop_info.height=(unsigned int) (scale_factor*chop_info.height+0.5);
3247 chop_image=ChopImage(*image,&chop_info,exception);
3248 XSetCursorState(display,windows,MagickFalse);
3249 if (chop_image == (Image *) NULL)
3250 return(MagickFalse);
3251 *image=DestroyImage(*image);
3254 Update image configuration.
3256 XConfigureImageColormap(display,resource_info,windows,*image,exception);
3257 (void) XConfigureImage(display,resource_info,windows,*image,exception);
3262 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3266 + X C o l o r E d i t I m a g e %
3270 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3272 % XColorEditImage() allows the user to interactively change the color of one
3273 % pixel for a DirectColor image or one colormap entry for a PseudoClass image.
3275 % The format of the XColorEditImage method is:
3277 % MagickBooleanType XColorEditImage(Display *display,
3278 % XResourceInfo *resource_info,XWindows *windows,Image **image,
3279 % ExceptionInfo *exception)
3281 % A description of each parameter follows:
3283 % o display: Specifies a connection to an X server; returned from
3286 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
3288 % o windows: Specifies a pointer to a XWindows structure.
3290 % o image: the image; returned from ReadImage.
3292 % o exception: return any errors or warnings in this structure.
3295 static MagickBooleanType XColorEditImage(Display *display,
3296 XResourceInfo *resource_info,XWindows *windows,Image **image,
3297 ExceptionInfo *exception)
3312 static const ModeType
3313 ColorEditCommands[] =
3315 ColorEditMethodCommand,
3316 ColorEditColorCommand,
3317 ColorEditBorderCommand,
3318 ColorEditFuzzCommand,
3319 ColorEditUndoCommand,
3320 ColorEditHelpCommand,
3321 ColorEditDismissCommand
3325 method = PointMethod;
3331 border_color = { 0, 0, 0, 0, 0, 0 };
3334 command[MaxTextExtent],
3335 text[MaxTextExtent];
3370 (void) CloneString(&windows->command.name,"Color Edit");
3371 windows->command.data=4;
3372 (void) XCommandWidget(display,windows,ColorEditMenu,(XEvent *) NULL);
3373 (void) XMapRaised(display,windows->command.id);
3374 XClientMessage(display,windows->image.id,windows->im_protocols,
3375 windows->im_update_widget,CurrentTime);
3379 cursor=XMakeCursor(display,windows->image.id,windows->map_info->colormap,
3380 resource_info->background_color,resource_info->foreground_color);
3381 (void) XCheckDefineCursor(display,windows->image.id,cursor);
3383 Track pointer until button 1 is pressed.
3385 XQueryPosition(display,windows->image.id,&x,&y);
3386 (void) XSelectInput(display,windows->image.id,
3387 windows->image.attributes.event_mask | PointerMotionMask);
3391 if (IfMagickTrue(windows->info.mapped) )
3394 Display pointer position.
3396 (void) FormatLocaleString(text,MaxTextExtent," %+d%+d ",
3397 x+windows->image.x,y+windows->image.y);
3398 XInfoWidget(display,windows,text);
3401 Wait for next event.
3403 XScreenEvent(display,windows,&event,exception);
3404 if (event.xany.window == windows->command.id)
3407 Select a command from the Command widget.
3409 id=XCommandWidget(display,windows,ColorEditMenu,&event);
3412 (void) XCheckDefineCursor(display,windows->image.id,cursor);
3415 switch (ColorEditCommands[id])
3417 case ColorEditMethodCommand:
3423 Select a method from the pop-up menu.
3425 methods=(char **) GetCommandOptions(MagickMethodOptions);
3426 if (methods == (char **) NULL)
3428 entry=XMenuWidget(display,windows,ColorEditMenu[id],
3429 (const char **) methods,command);
3431 method=(PaintMethod) ParseCommandOption(MagickMethodOptions,
3432 MagickFalse,methods[entry]);
3433 methods=DestroyStringList(methods);
3436 case ColorEditColorCommand:
3439 *ColorMenu[MaxNumberPens];
3445 Initialize menu selections.
3447 for (i=0; i < (int) (MaxNumberPens-2); i++)
3448 ColorMenu[i]=resource_info->pen_colors[i];
3449 ColorMenu[MaxNumberPens-2]="Browser...";
3450 ColorMenu[MaxNumberPens-1]=(const char *) NULL;
3452 Select a pen color from the pop-up menu.
3454 pen_number=XMenuWidget(display,windows,ColorEditMenu[id],
3455 (const char **) ColorMenu,command);
3458 if (pen_number == (MaxNumberPens-2))
3461 color_name[MaxTextExtent] = "gray";
3464 Select a pen color from a dialog.
3466 resource_info->pen_colors[pen_number]=color_name;
3467 XColorBrowserWidget(display,windows,"Select",color_name);
3468 if (*color_name == '\0')
3474 (void) XParseColor(display,windows->map_info->colormap,
3475 resource_info->pen_colors[pen_number],&color);
3476 XBestPixel(display,windows->map_info->colormap,(XColor *) NULL,
3477 (unsigned int) MaxColors,&color);
3478 windows->pixel_info->pen_colors[pen_number]=color;
3479 pen_id=(unsigned int) pen_number;
3482 case ColorEditBorderCommand:
3485 *ColorMenu[MaxNumberPens];
3491 Initialize menu selections.
3493 for (i=0; i < (int) (MaxNumberPens-2); i++)
3494 ColorMenu[i]=resource_info->pen_colors[i];
3495 ColorMenu[MaxNumberPens-2]="Browser...";
3496 ColorMenu[MaxNumberPens-1]=(const char *) NULL;
3498 Select a pen color from the pop-up menu.
3500 pen_number=XMenuWidget(display,windows,ColorEditMenu[id],
3501 (const char **) ColorMenu,command);
3504 if (pen_number == (MaxNumberPens-2))
3507 color_name[MaxTextExtent] = "gray";
3510 Select a pen color from a dialog.
3512 resource_info->pen_colors[pen_number]=color_name;
3513 XColorBrowserWidget(display,windows,"Select",color_name);
3514 if (*color_name == '\0')
3520 (void) XParseColor(display,windows->map_info->colormap,
3521 resource_info->pen_colors[pen_number],&border_color);
3524 case ColorEditFuzzCommand:
3527 fuzz[MaxTextExtent];
3542 Select a command from the pop-up menu.
3544 entry=XMenuWidget(display,windows,ColorEditMenu[id],FuzzMenu,
3550 (*image)->fuzz=StringToDoubleInterval(FuzzMenu[entry],(double)
3554 (void) (void) CopyMagickString(fuzz,"20%",MaxTextExtent);
3555 (void) XDialogWidget(display,windows,"Ok",
3556 "Enter fuzz factor (0.0 - 99.9%):",fuzz);
3559 (void) ConcatenateMagickString(fuzz,"%",MaxTextExtent);
3560 (*image)->fuzz=StringToDoubleInterval(fuzz,(double) QuantumRange+
3564 case ColorEditUndoCommand:
3566 (void) XMagickCommand(display,resource_info,windows,UndoCommand,
3570 case ColorEditHelpCommand:
3573 XTextViewWidget(display,resource_info,windows,MagickFalse,
3574 "Help Viewer - Image Annotation",ImageColorEditHelp);
3577 case ColorEditDismissCommand:
3587 (void) XCheckDefineCursor(display,windows->image.id,cursor);
3594 if (event.xbutton.button != Button1)
3596 if ((event.xbutton.window != windows->image.id) &&
3597 (event.xbutton.window != windows->magnify.id))
3604 (void) XMagickCommand(display,resource_info,windows,
3605 SaveToUndoBufferCommand,image,exception);
3606 state|=UpdateConfigurationState;
3611 if (event.xbutton.button != Button1)
3613 if ((event.xbutton.window != windows->image.id) &&
3614 (event.xbutton.window != windows->magnify.id))
3617 Update colormap information.
3621 XConfigureImageColormap(display,resource_info,windows,*image,exception);
3622 (void) XConfigureImage(display,resource_info,windows,*image,exception);
3623 XInfoWidget(display,windows,text);
3624 (void) XCheckDefineCursor(display,windows->image.id,cursor);
3625 state&=(~UpdateConfigurationState);
3635 if (event.xkey.window == windows->magnify.id)
3640 window=windows->magnify.id;
3641 while (XCheckWindowEvent(display,window,KeyPressMask,&event)) ;
3643 if (event.xkey.window != windows->image.id)
3646 Respond to a user key press.
3648 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
3649 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
3650 switch ((int) key_symbol)
3664 XTextViewWidget(display,resource_info,windows,MagickFalse,
3665 "Help Viewer - Image Annotation",ImageColorEditHelp);
3670 (void) XBell(display,0);
3679 Map and unmap Info widget as cursor crosses its boundaries.
3683 if (IfMagickTrue(windows->info.mapped) )
3685 if ((x < (int) (windows->info.x+windows->info.width)) &&
3686 (y < (int) (windows->info.y+windows->info.height)))
3687 (void) XWithdrawWindow(display,windows->info.id,
3688 windows->info.screen);
3691 if ((x > (int) (windows->info.x+windows->info.width)) ||
3692 (y > (int) (windows->info.y+windows->info.height)))
3693 (void) XMapWindow(display,windows->info.id);
3699 if (event.xany.window == windows->magnify.id)
3701 x=windows->magnify.x-windows->image.x;
3702 y=windows->magnify.y-windows->image.y;
3706 if ((state & UpdateConfigurationState) != 0)
3716 Pixel edit is relative to image configuration.
3718 (void) XClearArea(display,windows->image.id,x_offset,y_offset,1,1,
3720 color=windows->pixel_info->pen_colors[pen_id];
3721 XPutPixel(windows->image.ximage,x_offset,y_offset,color.pixel);
3722 width=(unsigned int) (*image)->columns;
3723 height=(unsigned int) (*image)->rows;
3726 if (windows->image.crop_geometry != (char *) NULL)
3727 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,
3730 (width*(windows->image.x+x_offset)/windows->image.ximage->width+x);
3732 (height*(windows->image.y+y_offset)/windows->image.ximage->height+y);
3733 if ((x_offset < 0) || (y_offset < 0))
3735 if ((x_offset >= (int) (*image)->columns) ||
3736 (y_offset >= (int) (*image)->rows))
3738 image_view=AcquireAuthenticCacheView(*image,exception);
3745 Update color information using point algorithm.
3747 if (IfMagickFalse(SetImageStorageClass(*image,DirectClass,exception)) )
3748 return(MagickFalse);
3749 q=GetCacheViewAuthenticPixels(image_view,(ssize_t)x_offset,
3750 (ssize_t) y_offset,1,1,exception);
3751 if (q == (Quantum *) NULL)
3753 SetPixelRed(*image,ScaleShortToQuantum(color.red),q);
3754 SetPixelGreen(*image,ScaleShortToQuantum(color.green),q);
3755 SetPixelBlue(*image,ScaleShortToQuantum(color.blue),q);
3756 (void) SyncCacheViewAuthenticPixels(image_view,exception);
3766 Update color information using replace algorithm.
3768 (void) GetOneCacheViewVirtualPixelInfo(image_view,(ssize_t)
3769 x_offset,(ssize_t) y_offset,&target,exception);
3770 if ((*image)->storage_class == DirectClass)
3772 for (y=0; y < (int) (*image)->rows; y++)
3774 q=GetCacheViewAuthenticPixels(image_view,0,(ssize_t) y,
3775 (*image)->columns,1,exception);
3776 if (q == (Quantum *) NULL)
3778 for (x=0; x < (int) (*image)->columns; x++)
3780 GetPixelInfoPixel(*image,q,&pixel);
3781 if (IsFuzzyEquivalencePixelInfo(&pixel,&target))
3783 SetPixelRed(*image,ScaleShortToQuantum(
3785 SetPixelGreen(*image,ScaleShortToQuantum(
3787 SetPixelBlue(*image,ScaleShortToQuantum(
3790 q+=GetPixelChannels(*image);
3792 if (IfMagickFalse(SyncCacheViewAuthenticPixels(image_view,exception)) )
3798 for (i=0; i < (ssize_t) (*image)->colors; i++)
3799 if (IsFuzzyEquivalencePixelInfo((*image)->colormap+i,&target))
3801 (*image)->colormap[i].red=(double) ScaleShortToQuantum(
3803 (*image)->colormap[i].green=(double) ScaleShortToQuantum(
3805 (*image)->colormap[i].blue=(double) ScaleShortToQuantum(
3808 (void) SyncImage(*image,exception);
3812 case FloodfillMethod:
3813 case FillToBorderMethod:
3822 Update color information using floodfill algorithm.
3824 (void) GetOneVirtualPixelInfo(*image,
3825 GetPixelCacheVirtualMethod(*image),(ssize_t) x_offset,(ssize_t)
3826 y_offset,&target,exception);
3827 if (method == FillToBorderMethod)
3830 ScaleShortToQuantum(border_color.red);
3831 target.green=(double)
3832 ScaleShortToQuantum(border_color.green);
3833 target.blue=(double)
3834 ScaleShortToQuantum(border_color.blue);
3836 draw_info=CloneDrawInfo(resource_info->image_info,
3838 (void) QueryColorCompliance(resource_info->pen_colors[pen_id],
3839 AllCompliance,&draw_info->fill,exception);
3840 (void) FloodfillPaintImage(*image,draw_info,&target,
3841 (ssize_t)x_offset,(ssize_t)y_offset,
3842 IsMagickFalse(method == FloodfillMethod),exception);
3843 draw_info=DestroyDrawInfo(draw_info);
3849 Update color information using reset algorithm.
3851 if (IfMagickFalse(SetImageStorageClass(*image,DirectClass,exception)) )
3852 return(MagickFalse);
3853 for (y=0; y < (int) (*image)->rows; y++)
3855 q=QueueCacheViewAuthenticPixels(image_view,0,(ssize_t) y,
3856 (*image)->columns,1,exception);
3857 if (q == (Quantum *) NULL)
3859 for (x=0; x < (int) (*image)->columns; x++)
3861 SetPixelRed(*image,ScaleShortToQuantum(color.red),q);
3862 SetPixelGreen(*image,ScaleShortToQuantum(color.green),q);
3863 SetPixelBlue(*image,ScaleShortToQuantum(color.blue),q);
3864 q+=GetPixelChannels(*image);
3866 if (IfMagickFalse(SyncCacheViewAuthenticPixels(image_view,exception)) )
3872 image_view=DestroyCacheView(image_view);
3873 state&=(~UpdateConfigurationState);
3875 } while ((state & ExitState) == 0);
3876 (void) XSelectInput(display,windows->image.id,
3877 windows->image.attributes.event_mask);
3878 XSetCursorState(display,windows,MagickFalse);
3879 (void) XFreeCursor(display,cursor);
3884 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3888 + X C o m p o s i t e I m a g e %
3892 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3894 % XCompositeImage() requests an image name from the user, reads the image and
3895 % composites it with the X window image at a location the user chooses with
3898 % The format of the XCompositeImage method is:
3900 % MagickBooleanType XCompositeImage(Display *display,
3901 % XResourceInfo *resource_info,XWindows *windows,Image *image,
3902 % ExceptionInfo *exception)
3904 % A description of each parameter follows:
3906 % o display: Specifies a connection to an X server; returned from
3909 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
3911 % o windows: Specifies a pointer to a XWindows structure.
3913 % o image: the image; returned from ReadImage.
3915 % o exception: return any errors or warnings in this structure.
3918 static MagickBooleanType XCompositeImage(Display *display,
3919 XResourceInfo *resource_info,XWindows *windows,Image *image,
3920 ExceptionInfo *exception)
3923 displacement_geometry[MaxTextExtent] = "30x30",
3924 filename[MaxTextExtent] = "\0";
3937 static CompositeOperator
3938 compose = CopyCompositeOp;
3940 static const ModeType
3941 CompositeCommands[] =
3943 CompositeOperatorsCommand,
3944 CompositeDissolveCommand,
3945 CompositeDisplaceCommand,
3946 CompositeHelpCommand,
3947 CompositeDismissCommand
3951 text[MaxTextExtent];
3984 Request image file name from user.
3986 XFileBrowserWidget(display,windows,"Composite",filename);
3987 if (*filename == '\0')
3992 XSetCursorState(display,windows,MagickTrue);
3993 XCheckRefreshWindows(display,windows);
3994 (void) CopyMagickString(resource_info->image_info->filename,filename,
3996 composite_image=ReadImage(resource_info->image_info,exception);
3997 CatchException(exception);
3998 XSetCursorState(display,windows,MagickFalse);
3999 if (composite_image == (Image *) NULL)
4000 return(MagickFalse);
4004 (void) CloneString(&windows->command.name,"Composite");
4005 windows->command.data=1;
4006 (void) XCommandWidget(display,windows,CompositeMenu,(XEvent *) NULL);
4007 (void) XMapRaised(display,windows->command.id);
4008 XClientMessage(display,windows->image.id,windows->im_protocols,
4009 windows->im_update_widget,CurrentTime);
4011 Track pointer until button 1 is pressed.
4013 XQueryPosition(display,windows->image.id,&x,&y);
4014 (void) XSelectInput(display,windows->image.id,
4015 windows->image.attributes.event_mask | PointerMotionMask);
4016 composite_info.x=(ssize_t) windows->image.x+x;
4017 composite_info.y=(ssize_t) windows->image.y+y;
4018 composite_info.width=0;
4019 composite_info.height=0;
4020 cursor=XCreateFontCursor(display,XC_ul_angle);
4021 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
4026 if (IfMagickTrue(windows->info.mapped) )
4029 Display pointer position.
4031 (void) FormatLocaleString(text,MaxTextExtent," %+ld%+ld ",
4032 (long) composite_info.x,(long) composite_info.y);
4033 XInfoWidget(display,windows,text);
4035 highlight_info=composite_info;
4036 highlight_info.x=composite_info.x-windows->image.x;
4037 highlight_info.y=composite_info.y-windows->image.y;
4038 XHighlightRectangle(display,windows->image.id,
4039 windows->image.highlight_context,&highlight_info);
4041 Wait for next event.
4043 XScreenEvent(display,windows,&event,exception);
4044 XHighlightRectangle(display,windows->image.id,
4045 windows->image.highlight_context,&highlight_info);
4046 if (event.xany.window == windows->command.id)
4049 Select a command from the Command widget.
4051 id=XCommandWidget(display,windows,CompositeMenu,&event);
4054 switch (CompositeCommands[id])
4056 case CompositeOperatorsCommand:
4059 command[MaxTextExtent],
4063 Select a command from the pop-up menu.
4065 operators=GetCommandOptions(MagickComposeOptions);
4066 if (operators == (char **) NULL)
4068 entry=XMenuWidget(display,windows,CompositeMenu[id],
4069 (const char **) operators,command);
4071 compose=(CompositeOperator) ParseCommandOption(
4072 MagickComposeOptions,MagickFalse,operators[entry]);
4073 operators=DestroyStringList(operators);
4076 case CompositeDissolveCommand:
4079 factor[MaxTextExtent] = "20.0";
4082 Dissolve the two images a given percent.
4084 (void) XSetFunction(display,windows->image.highlight_context,
4086 (void) XDialogWidget(display,windows,"Dissolve",
4087 "Enter the blend factor (0.0 - 99.9%):",factor);
4088 (void) XSetFunction(display,windows->image.highlight_context,
4090 if (*factor == '\0')
4092 blend=StringToDouble(factor,(char **) NULL);
4093 compose=DissolveCompositeOp;
4096 case CompositeDisplaceCommand:
4099 Get horizontal and vertical scale displacement geometry.
4101 (void) XSetFunction(display,windows->image.highlight_context,
4103 (void) XDialogWidget(display,windows,"Displace",
4104 "Enter the horizontal and vertical scale:",displacement_geometry);
4105 (void) XSetFunction(display,windows->image.highlight_context,
4107 if (*displacement_geometry == '\0')
4109 compose=DisplaceCompositeOp;
4112 case CompositeHelpCommand:
4114 (void) XSetFunction(display,windows->image.highlight_context,
4116 XTextViewWidget(display,resource_info,windows,MagickFalse,
4117 "Help Viewer - Image Composite",ImageCompositeHelp);
4118 (void) XSetFunction(display,windows->image.highlight_context,
4122 case CompositeDismissCommand:
4140 if (IfMagickTrue(image->debug) )
4141 (void) LogMagickEvent(X11Event,GetMagickModule(),
4142 "Button Press: 0x%lx %u +%d+%d",event.xbutton.window,
4143 event.xbutton.button,event.xbutton.x,event.xbutton.y);
4144 if (event.xbutton.button != Button1)
4146 if (event.xbutton.window != windows->image.id)
4151 composite_info.width=composite_image->columns;
4152 composite_info.height=composite_image->rows;
4153 (void) XCheckDefineCursor(display,windows->image.id,cursor);
4154 composite_info.x=(ssize_t) windows->image.x+event.xbutton.x;
4155 composite_info.y=(ssize_t) windows->image.y+event.xbutton.y;
4160 if (IfMagickTrue(image->debug) )
4161 (void) LogMagickEvent(X11Event,GetMagickModule(),
4162 "Button Release: 0x%lx %u +%d+%d",event.xbutton.window,
4163 event.xbutton.button,event.xbutton.x,event.xbutton.y);
4164 if (event.xbutton.button != Button1)
4166 if (event.xbutton.window != windows->image.id)
4168 if ((composite_info.width != 0) && (composite_info.height != 0))
4171 User has selected the location of the composite image.
4173 composite_info.x=(ssize_t) windows->image.x+event.xbutton.x;
4174 composite_info.y=(ssize_t) windows->image.y+event.xbutton.y;
4184 command[MaxTextExtent];
4192 if (event.xkey.window != windows->image.id)
4195 Respond to a user key press.
4197 length=XLookupString((XKeyEvent *) &event.xkey,command,(int)
4198 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
4199 *(command+length)='\0';
4200 if (IfMagickTrue(image->debug) )
4201 (void) LogMagickEvent(X11Event,GetMagickModule(),
4202 "Key press: 0x%lx (%s)",(unsigned long) key_symbol,command);
4203 switch ((int) key_symbol)
4211 composite_image=DestroyImage(composite_image);
4219 (void) XSetFunction(display,windows->image.highlight_context,
4221 XTextViewWidget(display,resource_info,windows,MagickFalse,
4222 "Help Viewer - Image Composite",ImageCompositeHelp);
4223 (void) XSetFunction(display,windows->image.highlight_context,
4229 (void) XBell(display,0);
4238 Map and unmap Info widget as text cursor crosses its boundaries.
4242 if (IfMagickTrue(windows->info.mapped) )
4244 if ((x < (int) (windows->info.x+windows->info.width)) &&
4245 (y < (int) (windows->info.y+windows->info.height)))
4246 (void) XWithdrawWindow(display,windows->info.id,
4247 windows->info.screen);
4250 if ((x > (int) (windows->info.x+windows->info.width)) ||
4251 (y > (int) (windows->info.y+windows->info.height)))
4252 (void) XMapWindow(display,windows->info.id);
4253 composite_info.x=(ssize_t) windows->image.x+x;
4254 composite_info.y=(ssize_t) windows->image.y+y;
4259 if (IfMagickTrue(image->debug) )
4260 (void) LogMagickEvent(X11Event,GetMagickModule(),"Event type: %d",
4265 } while ((state & ExitState) == 0);
4266 (void) XSelectInput(display,windows->image.id,
4267 windows->image.attributes.event_mask);
4268 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
4269 XSetCursorState(display,windows,MagickFalse);
4270 (void) XFreeCursor(display,cursor);
4271 if ((state & EscapeState) != 0)
4274 Image compositing is relative to image configuration.
4276 XSetCursorState(display,windows,MagickTrue);
4277 XCheckRefreshWindows(display,windows);
4278 width=(unsigned int) image->columns;
4279 height=(unsigned int) image->rows;
4282 if (windows->image.crop_geometry != (char *) NULL)
4283 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
4284 scale_factor=(double) width/windows->image.ximage->width;
4285 composite_info.x+=x;
4286 composite_info.x=(ssize_t) (scale_factor*composite_info.x+0.5);
4287 composite_info.width=(unsigned int) (scale_factor*composite_info.width+0.5);
4288 scale_factor=(double) height/windows->image.ximage->height;
4289 composite_info.y+=y;
4290 composite_info.y=(ssize_t) (scale_factor*composite_info.y+0.5);
4291 composite_info.height=(unsigned int) (scale_factor*composite_info.height+0.5);
4292 if ((composite_info.width != composite_image->columns) ||
4293 (composite_info.height != composite_image->rows))
4299 Scale composite image.
4301 resize_image=ResizeImage(composite_image,composite_info.width,
4302 composite_info.height,composite_image->filter,exception);
4303 composite_image=DestroyImage(composite_image);
4304 if (resize_image == (Image *) NULL)
4306 XSetCursorState(display,windows,MagickFalse);
4307 return(MagickFalse);
4309 composite_image=resize_image;
4311 if (compose == DisplaceCompositeOp)
4312 (void) SetImageArtifact(composite_image,"compose:args",
4313 displacement_geometry);
4332 Create mattes for blending.
4334 (void) SetImageAlphaChannel(composite_image,OpaqueAlphaChannel,exception);
4335 opacity=(Quantum) (ScaleQuantumToChar(QuantumRange)-
4336 ((ssize_t) ScaleQuantumToChar(QuantumRange)*blend)/100);
4337 if (IfMagickFalse(SetImageStorageClass(image,DirectClass,exception)) )
4338 return(MagickFalse);
4339 image->alpha_trait=BlendPixelTrait;
4340 image_view=AcquireAuthenticCacheView(image,exception);
4341 for (y=0; y < (int) image->rows; y++)
4343 q=GetCacheViewAuthenticPixels(image_view,0,(ssize_t) y,image->columns,1,
4345 if (q == (Quantum *) NULL)
4347 for (x=0; x < (int) image->columns; x++)
4349 SetPixelAlpha(image,opacity,q);
4350 q+=GetPixelChannels(image);
4352 if (IfMagickFalse(SyncCacheViewAuthenticPixels(image_view,exception)) )
4355 image_view=DestroyCacheView(image_view);
4358 Composite image with X Image window.
4360 (void) CompositeImage(image,composite_image,compose,MagickTrue,
4361 composite_info.x,composite_info.y,exception);
4362 composite_image=DestroyImage(composite_image);
4363 XSetCursorState(display,windows,MagickFalse);
4365 Update image configuration.
4367 XConfigureImageColormap(display,resource_info,windows,image,exception);
4368 (void) XConfigureImage(display,resource_info,windows,image,exception);
4373 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4377 + X C o n f i g u r e I m a g e %
4381 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4383 % XConfigureImage() creates a new X image. It also notifies the window
4384 % manager of the new image size and configures the transient widows.
4386 % The format of the XConfigureImage method is:
4388 % MagickBooleanType XConfigureImage(Display *display,
4389 % XResourceInfo *resource_info,XWindows *windows,Image *image,
4390 % ExceptionInfo *exception)
4392 % A description of each parameter follows:
4394 % o display: Specifies a connection to an X server; returned from
4397 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
4399 % o windows: Specifies a pointer to a XWindows structure.
4401 % o image: the image.
4403 % o exception: return any errors or warnings in this structure.
4405 % o exception: return any errors or warnings in this structure.
4408 static MagickBooleanType XConfigureImage(Display *display,
4409 XResourceInfo *resource_info,XWindows *windows,Image *image,
4410 ExceptionInfo *exception)
4413 geometry[MaxTextExtent];
4434 Dismiss if window dimensions are zero.
4436 width=(unsigned int) windows->image.window_changes.width;
4437 height=(unsigned int) windows->image.window_changes.height;
4438 if (IfMagickTrue(image->debug) )
4439 (void) LogMagickEvent(X11Event,GetMagickModule(),
4440 "Configure Image: %dx%d=>%.20gx%.20g",windows->image.ximage->width,
4441 windows->image.ximage->height,(double) width,(double) height);
4442 if ((width*height) == 0)
4447 Resize image to fit Image window dimensions.
4449 XSetCursorState(display,windows,MagickTrue);
4450 (void) XFlush(display);
4451 if (((int) width != windows->image.ximage->width) ||
4452 ((int) height != windows->image.ximage->height))
4453 image->taint=MagickTrue;
4454 windows->magnify.x=(int)
4455 width*windows->magnify.x/windows->image.ximage->width;
4456 windows->magnify.y=(int)
4457 height*windows->magnify.y/windows->image.ximage->height;
4458 windows->image.x=(int) (width*windows->image.x/windows->image.ximage->width);
4459 windows->image.y=(int)
4460 (height*windows->image.y/windows->image.ximage->height);
4461 status=XMakeImage(display,resource_info,&windows->image,image,
4462 (unsigned int) width,(unsigned int) height,exception);
4463 if (IfMagickFalse(status) )
4464 XNoticeWidget(display,windows,"Unable to configure X image:",
4465 windows->image.name);
4467 Notify window manager of the new configuration.
4469 if (resource_info->image_geometry != (char *) NULL)
4470 (void) FormatLocaleString(geometry,MaxTextExtent,"%s>!",
4471 resource_info->image_geometry);
4473 (void) FormatLocaleString(geometry,MaxTextExtent,"%ux%u+0+0>!",
4474 XDisplayWidth(display,windows->image.screen),
4475 XDisplayHeight(display,windows->image.screen));
4476 (void) ParseMetaGeometry(geometry,&x,&y,&width,&height);
4477 window_changes.width=(int) width;
4478 if (window_changes.width > XDisplayWidth(display,windows->image.screen))
4479 window_changes.width=XDisplayWidth(display,windows->image.screen);
4480 window_changes.height=(int) height;
4481 if (window_changes.height > XDisplayHeight(display,windows->image.screen))
4482 window_changes.height=XDisplayHeight(display,windows->image.screen);
4483 mask=(size_t) (CWWidth | CWHeight);
4484 if (resource_info->backdrop)
4487 window_changes.x=(int)
4488 ((XDisplayWidth(display,windows->image.screen)/2)-(width/2));
4489 window_changes.y=(int)
4490 ((XDisplayHeight(display,windows->image.screen)/2)-(height/2));
4492 (void) XReconfigureWMWindow(display,windows->image.id,windows->image.screen,
4493 (unsigned int) mask,&window_changes);
4494 (void) XClearWindow(display,windows->image.id);
4495 XRefreshWindow(display,&windows->image,(XEvent *) NULL);
4497 Update Magnify window configuration.
4499 if (IfMagickTrue(windows->magnify.mapped) )
4500 XMakeMagnifyImage(display,windows,exception);
4501 windows->pan.crop_geometry=windows->image.crop_geometry;
4502 XBestIconSize(display,&windows->pan,image);
4503 while (((windows->pan.width << 1) < MaxIconSize) &&
4504 ((windows->pan.height << 1) < MaxIconSize))
4506 windows->pan.width<<=1;
4507 windows->pan.height<<=1;
4509 if (windows->pan.geometry != (char *) NULL)
4510 (void) XParseGeometry(windows->pan.geometry,&windows->pan.x,&windows->pan.y,
4511 &windows->pan.width,&windows->pan.height);
4512 window_changes.width=(int) windows->pan.width;
4513 window_changes.height=(int) windows->pan.height;
4514 size_hints=XAllocSizeHints();
4515 if (size_hints != (XSizeHints *) NULL)
4520 size_hints->flags=PSize | PMinSize | PMaxSize;
4521 size_hints->width=window_changes.width;
4522 size_hints->height=window_changes.height;
4523 size_hints->min_width=size_hints->width;
4524 size_hints->min_height=size_hints->height;
4525 size_hints->max_width=size_hints->width;
4526 size_hints->max_height=size_hints->height;
4527 (void) XSetNormalHints(display,windows->pan.id,size_hints);
4528 (void) XFree((void *) size_hints);
4530 (void) XReconfigureWMWindow(display,windows->pan.id,windows->pan.screen,
4531 (unsigned int) (CWWidth | CWHeight),&window_changes);
4533 Update icon window configuration.
4535 windows->icon.crop_geometry=windows->image.crop_geometry;
4536 XBestIconSize(display,&windows->icon,image);
4537 window_changes.width=(int) windows->icon.width;
4538 window_changes.height=(int) windows->icon.height;
4539 (void) XReconfigureWMWindow(display,windows->icon.id,windows->icon.screen,
4540 (unsigned int) (CWWidth | CWHeight),&window_changes);
4541 XSetCursorState(display,windows,MagickFalse);
4542 return(IsMagickTrue(status));
4546 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4550 + X C r o p I m a g e %
4554 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4556 % XCropImage() allows the user to select a region of the image and crop, copy,
4557 % or cut it. For copy or cut, the image can subsequently be composited onto
4558 % the image with XPasteImage.
4560 % The format of the XCropImage method is:
4562 % MagickBooleanType XCropImage(Display *display,
4563 % XResourceInfo *resource_info,XWindows *windows,Image *image,
4564 % const ClipboardMode mode,ExceptionInfo *exception)
4566 % A description of each parameter follows:
4568 % o display: Specifies a connection to an X server; returned from
4571 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
4573 % o windows: Specifies a pointer to a XWindows structure.
4575 % o image: the image; returned from ReadImage.
4577 % o mode: This unsigned value specified whether the image should be
4578 % cropped, copied, or cut.
4580 % o exception: return any errors or warnings in this structure.
4583 static MagickBooleanType XCropImage(Display *display,
4584 XResourceInfo *resource_info,XWindows *windows,Image *image,
4585 const ClipboardMode mode,ExceptionInfo *exception)
4594 *RectifyModeMenu[] =
4602 static const ModeType
4612 RectifyDismissCommand
4619 command[MaxTextExtent],
4620 text[MaxTextExtent];
4663 (void) CloneString(&windows->command.name,"Copy");
4668 (void) CloneString(&windows->command.name,"Crop");
4673 (void) CloneString(&windows->command.name,"Cut");
4677 RectifyModeMenu[0]=windows->command.name;
4678 windows->command.data=0;
4679 (void) XCommandWidget(display,windows,CropModeMenu,(XEvent *) NULL);
4680 (void) XMapRaised(display,windows->command.id);
4681 XClientMessage(display,windows->image.id,windows->im_protocols,
4682 windows->im_update_widget,CurrentTime);
4684 Track pointer until button 1 is pressed.
4686 XQueryPosition(display,windows->image.id,&x,&y);
4687 (void) XSelectInput(display,windows->image.id,
4688 windows->image.attributes.event_mask | PointerMotionMask);
4689 crop_info.x=(ssize_t) windows->image.x+x;
4690 crop_info.y=(ssize_t) windows->image.y+y;
4693 cursor=XCreateFontCursor(display,XC_fleur);
4697 if (IfMagickTrue(windows->info.mapped) )
4700 Display pointer position.
4702 (void) FormatLocaleString(text,MaxTextExtent," %+ld%+ld ",
4703 (long) crop_info.x,(long) crop_info.y);
4704 XInfoWidget(display,windows,text);
4707 Wait for next event.
4709 XScreenEvent(display,windows,&event,exception);
4710 if (event.xany.window == windows->command.id)
4713 Select a command from the Command widget.
4715 id=XCommandWidget(display,windows,CropModeMenu,&event);
4718 switch (CropCommands[id])
4720 case CropHelpCommand:
4726 XTextViewWidget(display,resource_info,windows,MagickFalse,
4727 "Help Viewer - Image Copy",ImageCopyHelp);
4732 XTextViewWidget(display,resource_info,windows,MagickFalse,
4733 "Help Viewer - Image Crop",ImageCropHelp);
4738 XTextViewWidget(display,resource_info,windows,MagickFalse,
4739 "Help Viewer - Image Cut",ImageCutHelp);
4745 case CropDismissCommand:
4763 if (event.xbutton.button != Button1)
4765 if (event.xbutton.window != windows->image.id)
4768 Note first corner of cropping rectangle-- exit loop.
4770 (void) XCheckDefineCursor(display,windows->image.id,cursor);
4771 crop_info.x=(ssize_t) windows->image.x+event.xbutton.x;
4772 crop_info.y=(ssize_t) windows->image.y+event.xbutton.y;
4782 if (event.xkey.window != windows->image.id)
4785 Respond to a user key press.
4787 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
4788 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
4789 switch ((int) key_symbol)
4808 XTextViewWidget(display,resource_info,windows,MagickFalse,
4809 "Help Viewer - Image Copy",ImageCopyHelp);
4814 XTextViewWidget(display,resource_info,windows,MagickFalse,
4815 "Help Viewer - Image Crop",ImageCropHelp);
4820 XTextViewWidget(display,resource_info,windows,MagickFalse,
4821 "Help Viewer - Image Cut",ImageCutHelp);
4829 (void) XBell(display,0);
4837 if (event.xmotion.window != windows->image.id)
4840 Map and unmap Info widget as text cursor crosses its boundaries.
4844 if (IfMagickTrue(windows->info.mapped) )
4846 if ((x < (int) (windows->info.x+windows->info.width)) &&
4847 (y < (int) (windows->info.y+windows->info.height)))
4848 (void) XWithdrawWindow(display,windows->info.id,
4849 windows->info.screen);
4852 if ((x > (int) (windows->info.x+windows->info.width)) ||
4853 (y > (int) (windows->info.y+windows->info.height)))
4854 (void) XMapWindow(display,windows->info.id);
4855 crop_info.x=(ssize_t) windows->image.x+x;
4856 crop_info.y=(ssize_t) windows->image.y+y;
4862 } while ((state & ExitState) == 0);
4863 (void) XSelectInput(display,windows->image.id,
4864 windows->image.attributes.event_mask);
4865 if ((state & EscapeState) != 0)
4868 User want to exit without cropping.
4870 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
4871 (void) XFreeCursor(display,cursor);
4874 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
4878 Size rectangle as pointer moves until the mouse button is released.
4880 x=(int) crop_info.x;
4881 y=(int) crop_info.y;
4887 highlight_info=crop_info;
4888 highlight_info.x=crop_info.x-windows->image.x;
4889 highlight_info.y=crop_info.y-windows->image.y;
4890 if ((highlight_info.width > 3) && (highlight_info.height > 3))
4893 Display info and draw cropping rectangle.
4895 if (IfMagickFalse(windows->info.mapped) )
4896 (void) XMapWindow(display,windows->info.id);
4897 (void) FormatLocaleString(text,MaxTextExtent,
4898 " %.20gx%.20g%+.20g%+.20g",(double) crop_info.width,(double)
4899 crop_info.height,(double) crop_info.x,(double) crop_info.y);
4900 XInfoWidget(display,windows,text);
4901 XHighlightRectangle(display,windows->image.id,
4902 windows->image.highlight_context,&highlight_info);
4905 if (IfMagickTrue(windows->info.mapped) )
4906 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
4908 Wait for next event.
4910 XScreenEvent(display,windows,&event,exception);
4911 if ((highlight_info.width > 3) && (highlight_info.height > 3))
4912 XHighlightRectangle(display,windows->image.id,
4913 windows->image.highlight_context,&highlight_info);
4918 crop_info.x=(ssize_t) windows->image.x+event.xbutton.x;
4919 crop_info.y=(ssize_t) windows->image.y+event.xbutton.y;
4925 User has committed to cropping rectangle.
4927 crop_info.x=(ssize_t) windows->image.x+event.xbutton.x;
4928 crop_info.y=(ssize_t) windows->image.y+event.xbutton.y;
4929 XSetCursorState(display,windows,MagickFalse);
4931 windows->command.data=0;
4932 (void) XCommandWidget(display,windows,RectifyModeMenu,
4940 crop_info.x=(ssize_t) windows->image.x+event.xmotion.x;
4941 crop_info.y=(ssize_t) windows->image.y+event.xmotion.y;
4946 if ((((int) crop_info.x != x) && ((int) crop_info.y != y)) ||
4947 ((state & ExitState) != 0))
4950 Check boundary conditions.
4952 if (crop_info.x < 0)
4955 if (crop_info.x > (ssize_t) windows->image.ximage->width)
4956 crop_info.x=(ssize_t) windows->image.ximage->width;
4957 if ((int) crop_info.x < x)
4958 crop_info.width=(unsigned int) (x-crop_info.x);
4961 crop_info.width=(unsigned int) (crop_info.x-x);
4962 crop_info.x=(ssize_t) x;
4964 if (crop_info.y < 0)
4967 if (crop_info.y > (ssize_t) windows->image.ximage->height)
4968 crop_info.y=(ssize_t) windows->image.ximage->height;
4969 if ((int) crop_info.y < y)
4970 crop_info.height=(unsigned int) (y-crop_info.y);
4973 crop_info.height=(unsigned int) (crop_info.y-y);
4974 crop_info.y=(ssize_t) y;
4977 } while ((state & ExitState) == 0);
4979 Wait for user to grab a corner of the rectangle or press return.
4982 (void) XMapWindow(display,windows->info.id);
4985 if (IfMagickTrue(windows->info.mapped) )
4988 Display pointer position.
4990 (void) FormatLocaleString(text,MaxTextExtent,
4991 " %.20gx%.20g%+.20g%+.20g",(double) crop_info.width,(double)
4992 crop_info.height,(double) crop_info.x,(double) crop_info.y);
4993 XInfoWidget(display,windows,text);
4995 highlight_info=crop_info;
4996 highlight_info.x=crop_info.x-windows->image.x;
4997 highlight_info.y=crop_info.y-windows->image.y;
4998 if ((highlight_info.width <= 3) || (highlight_info.height <= 3))
5004 XHighlightRectangle(display,windows->image.id,
5005 windows->image.highlight_context,&highlight_info);
5006 XScreenEvent(display,windows,&event,exception);
5007 if (event.xany.window == windows->command.id)
5010 Select a command from the Command widget.
5012 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
5013 id=XCommandWidget(display,windows,RectifyModeMenu,&event);
5014 (void) XSetFunction(display,windows->image.highlight_context,
5016 XHighlightRectangle(display,windows->image.id,
5017 windows->image.highlight_context,&highlight_info);
5019 switch (RectifyCommands[id])
5021 case RectifyCopyCommand:
5026 case RectifyHelpCommand:
5028 (void) XSetFunction(display,windows->image.highlight_context,
5034 XTextViewWidget(display,resource_info,windows,MagickFalse,
5035 "Help Viewer - Image Copy",ImageCopyHelp);
5040 XTextViewWidget(display,resource_info,windows,MagickFalse,
5041 "Help Viewer - Image Crop",ImageCropHelp);
5046 XTextViewWidget(display,resource_info,windows,MagickFalse,
5047 "Help Viewer - Image Cut",ImageCutHelp);
5051 (void) XSetFunction(display,windows->image.highlight_context,
5055 case RectifyDismissCommand:
5069 XHighlightRectangle(display,windows->image.id,
5070 windows->image.highlight_context,&highlight_info);
5075 if (event.xbutton.button != Button1)
5077 if (event.xbutton.window != windows->image.id)
5079 x=windows->image.x+event.xbutton.x;
5080 y=windows->image.y+event.xbutton.y;
5081 if ((x < (int) (crop_info.x+RoiDelta)) &&
5082 (x > (int) (crop_info.x-RoiDelta)) &&
5083 (y < (int) (crop_info.y+RoiDelta)) &&
5084 (y > (int) (crop_info.y-RoiDelta)))
5086 crop_info.x=(ssize_t) (crop_info.x+crop_info.width);
5087 crop_info.y=(ssize_t) (crop_info.y+crop_info.height);
5088 state|=UpdateConfigurationState;
5091 if ((x < (int) (crop_info.x+RoiDelta)) &&
5092 (x > (int) (crop_info.x-RoiDelta)) &&
5093 (y < (int) (crop_info.y+crop_info.height+RoiDelta)) &&
5094 (y > (int) (crop_info.y+crop_info.height-RoiDelta)))
5096 crop_info.x=(ssize_t) (crop_info.x+crop_info.width);
5097 state|=UpdateConfigurationState;
5100 if ((x < (int) (crop_info.x+crop_info.width+RoiDelta)) &&
5101 (x > (int) (crop_info.x+crop_info.width-RoiDelta)) &&
5102 (y < (int) (crop_info.y+RoiDelta)) &&
5103 (y > (int) (crop_info.y-RoiDelta)))
5105 crop_info.y=(ssize_t) (crop_info.y+crop_info.height);
5106 state|=UpdateConfigurationState;
5109 if ((x < (int) (crop_info.x+crop_info.width+RoiDelta)) &&
5110 (x > (int) (crop_info.x+crop_info.width-RoiDelta)) &&
5111 (y < (int) (crop_info.y+crop_info.height+RoiDelta)) &&
5112 (y > (int) (crop_info.y+crop_info.height-RoiDelta)))
5114 state|=UpdateConfigurationState;
5120 if (event.xbutton.window == windows->pan.id)
5121 if ((highlight_info.x != crop_info.x-windows->image.x) ||
5122 (highlight_info.y != crop_info.y-windows->image.y))
5123 XHighlightRectangle(display,windows->image.id,
5124 windows->image.highlight_context,&highlight_info);
5125 (void) XSetSelectionOwner(display,XA_PRIMARY,windows->image.id,
5126 event.xbutton.time);
5131 if (event.xexpose.window == windows->image.id)
5132 if (event.xexpose.count == 0)
5134 event.xexpose.x=(int) highlight_info.x;
5135 event.xexpose.y=(int) highlight_info.y;
5136 event.xexpose.width=(int) highlight_info.width;
5137 event.xexpose.height=(int) highlight_info.height;
5138 XRefreshWindow(display,&windows->image,&event);
5140 if (event.xexpose.window == windows->info.id)
5141 if (event.xexpose.count == 0)
5142 XInfoWidget(display,windows,text);
5147 if (event.xkey.window != windows->image.id)
5150 Respond to a user key press.
5152 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
5153 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
5154 switch ((int) key_symbol)
5167 crop_info.x=(ssize_t) (windows->image.width/2L-
5168 crop_info.width/2L);
5169 crop_info.y=(ssize_t) (windows->image.height/2L-
5170 crop_info.height/2L);
5202 (void) XSetFunction(display,windows->image.highlight_context,
5208 XTextViewWidget(display,resource_info,windows,MagickFalse,
5209 "Help Viewer - Image Copy",ImageCopyHelp);
5214 XTextViewWidget(display,resource_info,windows,MagickFalse,
5215 "Help Viewer - Image Cropg",ImageCropHelp);
5220 XTextViewWidget(display,resource_info,windows,MagickFalse,
5221 "Help Viewer - Image Cutg",ImageCutHelp);
5225 (void) XSetFunction(display,windows->image.highlight_context,
5231 (void) XBell(display,0);
5235 (void) XSetSelectionOwner(display,XA_PRIMARY,windows->image.id,
5243 if (event.xmotion.window != windows->image.id)
5246 Map and unmap Info widget as text cursor crosses its boundaries.
5250 if (IfMagickTrue(windows->info.mapped) )
5252 if ((x < (int) (windows->info.x+windows->info.width)) &&
5253 (y < (int) (windows->info.y+windows->info.height)))
5254 (void) XWithdrawWindow(display,windows->info.id,
5255 windows->info.screen);
5258 if ((x > (int) (windows->info.x+windows->info.width)) ||
5259 (y > (int) (windows->info.y+windows->info.height)))
5260 (void) XMapWindow(display,windows->info.id);
5261 crop_info.x=(ssize_t) windows->image.x+event.xmotion.x;
5262 crop_info.y=(ssize_t) windows->image.y+event.xmotion.y;
5265 case SelectionRequest:
5270 XSelectionRequestEvent
5274 Set primary selection.
5276 (void) FormatLocaleString(text,MaxTextExtent,
5277 "%.20gx%.20g%+.20g%+.20g",(double) crop_info.width,(double)
5278 crop_info.height,(double) crop_info.x,(double) crop_info.y);
5279 request=(&(event.xselectionrequest));
5280 (void) XChangeProperty(request->display,request->requestor,
5281 request->property,request->target,8,PropModeReplace,
5282 (unsigned char *) text,(int) strlen(text));
5283 notify.type=SelectionNotify;
5284 notify.display=request->display;
5285 notify.requestor=request->requestor;
5286 notify.selection=request->selection;
5287 notify.target=request->target;
5288 notify.time=request->time;
5289 if (request->property == None)
5290 notify.property=request->target;
5292 notify.property=request->property;
5293 (void) XSendEvent(request->display,request->requestor,False,0,
5294 (XEvent *) ¬ify);
5299 if ((state & UpdateConfigurationState) != 0)
5301 (void) XPutBackEvent(display,&event);
5302 (void) XCheckDefineCursor(display,windows->image.id,cursor);
5305 } while ((state & ExitState) == 0);
5306 } while ((state & ExitState) == 0);
5307 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
5308 XSetCursorState(display,windows,MagickFalse);
5309 if ((state & EscapeState) != 0)
5311 if (mode == CropMode)
5312 if (((int) crop_info.width != windows->image.ximage->width) ||
5313 ((int) crop_info.height != windows->image.ximage->height))
5316 Reconfigure Image window as defined by cropping rectangle.
5318 XSetCropGeometry(display,windows,&crop_info,image);
5319 windows->image.window_changes.width=(int) crop_info.width;
5320 windows->image.window_changes.height=(int) crop_info.height;
5321 (void) XConfigureImage(display,resource_info,windows,image,exception);
5325 Copy image before applying image transforms.
5327 XSetCursorState(display,windows,MagickTrue);
5328 XCheckRefreshWindows(display,windows);
5329 width=(unsigned int) image->columns;
5330 height=(unsigned int) image->rows;
5333 if (windows->image.crop_geometry != (char *) NULL)
5334 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
5335 scale_factor=(double) width/windows->image.ximage->width;
5337 crop_info.x=(ssize_t) (scale_factor*crop_info.x+0.5);
5338 crop_info.width=(unsigned int) (scale_factor*crop_info.width+0.5);
5339 scale_factor=(double) height/windows->image.ximage->height;
5341 crop_info.y=(ssize_t) (scale_factor*crop_info.y+0.5);
5342 crop_info.height=(unsigned int) (scale_factor*crop_info.height+0.5);
5343 crop_image=CropImage(image,&crop_info,exception);
5344 XSetCursorState(display,windows,MagickFalse);
5345 if (crop_image == (Image *) NULL)
5346 return(MagickFalse);
5347 if (resource_info->copy_image != (Image *) NULL)
5348 resource_info->copy_image=DestroyImage(resource_info->copy_image);
5349 resource_info->copy_image=crop_image;
5350 if (mode == CopyMode)
5352 (void) XConfigureImage(display,resource_info,windows,image,exception);
5358 if (IfMagickFalse(SetImageStorageClass(image,DirectClass,exception)) )
5359 return(MagickFalse);
5360 image->alpha_trait=BlendPixelTrait;
5361 image_view=AcquireAuthenticCacheView(image,exception);
5362 for (y=0; y < (int) crop_info.height; y++)
5364 q=GetCacheViewAuthenticPixels(image_view,crop_info.x,y+crop_info.y,
5365 crop_info.width,1,exception);
5366 if (q == (Quantum *) NULL)
5368 for (x=0; x < (int) crop_info.width; x++)
5370 SetPixelAlpha(image,TransparentAlpha,q);
5371 q+=GetPixelChannels(image);
5373 if (IfMagickFalse(SyncCacheViewAuthenticPixels(image_view,exception)) )
5376 image_view=DestroyCacheView(image_view);
5378 Update image configuration.
5380 XConfigureImageColormap(display,resource_info,windows,image,exception);
5381 (void) XConfigureImage(display,resource_info,windows,image,exception);
5386 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5390 + X D r a w I m a g e %
5394 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5396 % XDrawEditImage() draws a graphic element (point, line, rectangle, etc.) on
5399 % The format of the XDrawEditImage method is:
5401 % MagickBooleanType XDrawEditImage(Display *display,
5402 % XResourceInfo *resource_info,XWindows *windows,Image **image,
5403 % ExceptionInfo *exception)
5405 % A description of each parameter follows:
5407 % o display: Specifies a connection to an X server; returned from
5410 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5412 % o windows: Specifies a pointer to a XWindows structure.
5414 % o image: the image.
5416 % o exception: return any errors or warnings in this structure.
5419 static MagickBooleanType XDrawEditImage(Display *display,
5420 XResourceInfo *resource_info,XWindows *windows,Image **image,
5421 ExceptionInfo *exception)
5437 element = PointElement;
5439 static const ModeType
5452 stipple = (Pixmap) NULL;
5459 command[MaxTextExtent],
5460 text[MaxTextExtent];
5509 Allocate polygon info.
5511 max_coordinates=2048;
5512 coordinate_info=(XPoint *) AcquireQuantumMemory((size_t) max_coordinates,
5513 sizeof(*coordinate_info));
5514 if (coordinate_info == (XPoint *) NULL)
5516 (void) ThrowMagickException(exception,GetMagickModule(),
5517 ResourceLimitError,"MemoryAllocationFailed","`%s'","...");
5518 return(MagickFalse);
5523 (void) CloneString(&windows->command.name,"Draw");
5524 windows->command.data=4;
5525 (void) XCommandWidget(display,windows,DrawMenu,(XEvent *) NULL);
5526 (void) XMapRaised(display,windows->command.id);
5527 XClientMessage(display,windows->image.id,windows->im_protocols,
5528 windows->im_update_widget,CurrentTime);
5530 Wait for first button press.
5532 root_window=XRootWindow(display,XDefaultScreen(display));
5533 draw_info.stencil=OpaqueStencil;
5535 cursor=XCreateFontCursor(display,XC_tcross);
5538 XQueryPosition(display,windows->image.id,&x,&y);
5539 (void) XSelectInput(display,windows->image.id,
5540 windows->image.attributes.event_mask | PointerMotionMask);
5541 (void) XCheckDefineCursor(display,windows->image.id,cursor);
5545 if (IfMagickTrue(windows->info.mapped) )
5548 Display pointer position.
5550 (void) FormatLocaleString(text,MaxTextExtent," %+d%+d ",
5551 x+windows->image.x,y+windows->image.y);
5552 XInfoWidget(display,windows,text);
5555 Wait for next event.
5557 XScreenEvent(display,windows,&event,exception);
5558 if (event.xany.window == windows->command.id)
5561 Select a command from the Command widget.
5563 id=XCommandWidget(display,windows,DrawMenu,&event);
5566 switch (DrawCommands[id])
5568 case DrawElementCommand:
5587 Select a command from the pop-up menu.
5589 element=(ElementType) (XMenuWidget(display,windows,
5590 DrawMenu[id],Elements,command)+1);
5593 case DrawColorCommand:
5596 *ColorMenu[MaxNumberPens+1];
5608 Initialize menu selections.
5610 for (i=0; i < (int) (MaxNumberPens-2); i++)
5611 ColorMenu[i]=resource_info->pen_colors[i];
5612 ColorMenu[MaxNumberPens-2]="transparent";
5613 ColorMenu[MaxNumberPens-1]="Browser...";
5614 ColorMenu[MaxNumberPens]=(char *) NULL;
5616 Select a pen color from the pop-up menu.
5618 pen_number=XMenuWidget(display,windows,DrawMenu[id],
5619 (const char **) ColorMenu,command);
5622 transparent=pen_number == (MaxNumberPens-2) ? MagickTrue :
5624 if (IfMagickTrue(transparent) )
5626 draw_info.stencil=TransparentStencil;
5629 if (pen_number == (MaxNumberPens-1))
5632 color_name[MaxTextExtent] = "gray";
5635 Select a pen color from a dialog.
5637 resource_info->pen_colors[pen_number]=color_name;
5638 XColorBrowserWidget(display,windows,"Select",color_name);
5639 if (*color_name == '\0')
5645 (void) XParseColor(display,windows->map_info->colormap,
5646 resource_info->pen_colors[pen_number],&color);
5647 XBestPixel(display,windows->map_info->colormap,(XColor *) NULL,
5648 (unsigned int) MaxColors,&color);
5649 windows->pixel_info->pen_colors[pen_number]=color;
5650 pen_id=(unsigned int) pen_number;
5651 draw_info.stencil=OpaqueStencil;
5654 case DrawStippleCommand:
5666 filename[MaxTextExtent] = "\0";
5683 Select a command from the pop-up menu.
5685 StipplesMenu[7]="Open...";
5686 entry=XMenuWidget(display,windows,DrawMenu[id],StipplesMenu,
5690 if (stipple != (Pixmap) NULL)
5691 (void) XFreePixmap(display,stipple);
5692 stipple=(Pixmap) NULL;
5699 stipple=XCreateBitmapFromData(display,root_window,
5700 (char *) BricksBitmap,BricksWidth,BricksHeight);
5705 stipple=XCreateBitmapFromData(display,root_window,
5706 (char *) DiagonalBitmap,DiagonalWidth,DiagonalHeight);
5711 stipple=XCreateBitmapFromData(display,root_window,
5712 (char *) ScalesBitmap,ScalesWidth,ScalesHeight);
5717 stipple=XCreateBitmapFromData(display,root_window,
5718 (char *) VerticalBitmap,VerticalWidth,VerticalHeight);
5723 stipple=XCreateBitmapFromData(display,root_window,
5724 (char *) WavyBitmap,WavyWidth,WavyHeight);
5729 stipple=XCreateBitmapFromData(display,root_window,
5730 (char *) HighlightBitmap,HighlightWidth,
5737 stipple=XCreateBitmapFromData(display,root_window,
5738 (char *) OpaqueBitmap,OpaqueWidth,OpaqueHeight);
5744 XFileBrowserWidget(display,windows,"Stipple",filename);
5745 if (*filename == '\0')
5750 XSetCursorState(display,windows,MagickTrue);
5751 XCheckRefreshWindows(display,windows);
5752 image_info=AcquireImageInfo();
5753 (void) CopyMagickString(image_info->filename,filename,
5755 stipple_image=ReadImage(image_info,exception);
5756 CatchException(exception);
5757 XSetCursorState(display,windows,MagickFalse);
5758 if (stipple_image == (Image *) NULL)
5760 (void) AcquireUniqueFileResource(filename);
5761 (void) FormatLocaleString(stipple_image->filename,MaxTextExtent,
5763 (void) WriteImage(image_info,stipple_image,exception);
5764 stipple_image=DestroyImage(stipple_image);
5765 image_info=DestroyImageInfo(image_info);
5766 status=XReadBitmapFile(display,root_window,filename,&width,
5767 &height,&stipple,&x,&y);
5768 (void) RelinquishUniqueFileResource(filename);
5769 if ((status != BitmapSuccess) != 0)
5770 XNoticeWidget(display,windows,"Unable to read X bitmap image:",
5774 case DrawWidthCommand:
5777 width[MaxTextExtent] = "0";
5792 Select a command from the pop-up menu.
5794 entry=XMenuWidget(display,windows,DrawMenu[id],WidthsMenu,
5800 line_width=(unsigned int) StringToUnsignedLong(
5804 (void) XDialogWidget(display,windows,"Ok","Enter line width:",
5808 line_width=(unsigned int) StringToUnsignedLong(width);
5811 case DrawUndoCommand:
5813 (void) XMagickCommand(display,resource_info,windows,UndoCommand,
5817 case DrawHelpCommand:
5819 XTextViewWidget(display,resource_info,windows,MagickFalse,
5820 "Help Viewer - Image Rotation",ImageDrawHelp);
5821 (void) XCheckDefineCursor(display,windows->image.id,cursor);
5824 case DrawDismissCommand:
5836 (void) XCheckDefineCursor(display,windows->image.id,cursor);
5843 if (event.xbutton.button != Button1)
5845 if (event.xbutton.window != windows->image.id)
5864 if (event.xkey.window != windows->image.id)
5867 Respond to a user key press.
5869 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
5870 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
5871 switch ((int) key_symbol)
5886 XTextViewWidget(display,resource_info,windows,MagickFalse,
5887 "Help Viewer - Image Rotation",ImageDrawHelp);
5892 (void) XBell(display,0);
5901 Map and unmap Info widget as text cursor crosses its boundaries.
5905 if (IfMagickTrue(windows->info.mapped) )
5907 if ((x < (int) (windows->info.x+windows->info.width)) &&
5908 (y < (int) (windows->info.y+windows->info.height)))
5909 (void) XWithdrawWindow(display,windows->info.id,
5910 windows->info.screen);
5913 if ((x > (int) (windows->info.x+windows->info.width)) ||
5914 (y > (int) (windows->info.y+windows->info.height)))
5915 (void) XMapWindow(display,windows->info.id);
5919 } while ((state & ExitState) == 0);
5920 (void) XSelectInput(display,windows->image.id,
5921 windows->image.attributes.event_mask);
5922 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
5923 if ((state & EscapeState) != 0)
5926 Draw element as pointer moves until the button is released.
5934 rectangle_info.x=(ssize_t) x;
5935 rectangle_info.y=(ssize_t) y;
5936 rectangle_info.width=0;
5937 rectangle_info.height=0;
5938 number_coordinates=1;
5939 coordinate_info->x=x;
5940 coordinate_info->y=y;
5941 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
5950 if (number_coordinates > 1)
5952 (void) XDrawLines(display,windows->image.id,
5953 windows->image.highlight_context,coordinate_info,
5954 number_coordinates,CoordModeOrigin);
5955 (void) FormatLocaleString(text,MaxTextExtent," %+d%+d",
5956 coordinate_info[number_coordinates-1].x,
5957 coordinate_info[number_coordinates-1].y);
5958 XInfoWidget(display,windows,text);
5967 Display angle of the line.
5969 degrees=RadiansToDegrees(-atan2((double) (line_info.y2-
5970 line_info.y1),(double) (line_info.x2-line_info.x1)));
5971 (void) FormatLocaleString(text,MaxTextExtent," %g",
5973 XInfoWidget(display,windows,text);
5974 XHighlightLine(display,windows->image.id,
5975 windows->image.highlight_context,&line_info);
5978 if (IfMagickTrue(windows->info.mapped) )
5979 (void) XWithdrawWindow(display,windows->info.id,
5980 windows->info.screen);
5983 case RectangleElement:
5984 case FillRectangleElement:
5986 if ((rectangle_info.width > 3) && (rectangle_info.height > 3))
5989 Display info and draw drawing rectangle.
5991 (void) FormatLocaleString(text,MaxTextExtent,
5992 " %.20gx%.20g%+.20g%+.20g",(double) rectangle_info.width,
5993 (double) rectangle_info.height,(double) rectangle_info.x,
5994 (double) rectangle_info.y);
5995 XInfoWidget(display,windows,text);
5996 XHighlightRectangle(display,windows->image.id,
5997 windows->image.highlight_context,&rectangle_info);
6000 if (IfMagickTrue(windows->info.mapped) )
6001 (void) XWithdrawWindow(display,windows->info.id,
6002 windows->info.screen);
6006 case FillCircleElement:
6007 case EllipseElement:
6008 case FillEllipseElement:
6010 if ((rectangle_info.width > 3) && (rectangle_info.height > 3))
6013 Display info and draw drawing rectangle.
6015 (void) FormatLocaleString(text,MaxTextExtent,
6016 " %.20gx%.20g%+.20g%+.20g",(double) rectangle_info.width,
6017 (double) rectangle_info.height,(double) rectangle_info.x,
6018 (double) rectangle_info.y);
6019 XInfoWidget(display,windows,text);
6020 XHighlightEllipse(display,windows->image.id,
6021 windows->image.highlight_context,&rectangle_info);
6024 if (IfMagickTrue(windows->info.mapped) )
6025 (void) XWithdrawWindow(display,windows->info.id,
6026 windows->info.screen);
6029 case PolygonElement:
6030 case FillPolygonElement:
6032 if (number_coordinates > 1)
6033 (void) XDrawLines(display,windows->image.id,
6034 windows->image.highlight_context,coordinate_info,
6035 number_coordinates,CoordModeOrigin);
6039 Display angle of the line.
6041 degrees=RadiansToDegrees(-atan2((double) (line_info.y2-
6042 line_info.y1),(double) (line_info.x2-line_info.x1)));
6043 (void) FormatLocaleString(text,MaxTextExtent," %g",
6045 XInfoWidget(display,windows,text);
6046 XHighlightLine(display,windows->image.id,
6047 windows->image.highlight_context,&line_info);
6050 if (IfMagickTrue(windows->info.mapped) )
6051 (void) XWithdrawWindow(display,windows->info.id,
6052 windows->info.screen);
6057 Wait for next event.
6059 XScreenEvent(display,windows,&event,exception);
6065 if (number_coordinates > 1)
6066 (void) XDrawLines(display,windows->image.id,
6067 windows->image.highlight_context,coordinate_info,
6068 number_coordinates,CoordModeOrigin);
6074 XHighlightLine(display,windows->image.id,
6075 windows->image.highlight_context,&line_info);
6078 case RectangleElement:
6079 case FillRectangleElement:
6081 if ((rectangle_info.width > 3) && (rectangle_info.height > 3))
6082 XHighlightRectangle(display,windows->image.id,
6083 windows->image.highlight_context,&rectangle_info);
6087 case FillCircleElement:
6088 case EllipseElement:
6089 case FillEllipseElement:
6091 if ((rectangle_info.width > 3) && (rectangle_info.height > 3))
6092 XHighlightEllipse(display,windows->image.id,
6093 windows->image.highlight_context,&rectangle_info);
6096 case PolygonElement:
6097 case FillPolygonElement:
6099 if (number_coordinates > 1)
6100 (void) XDrawLines(display,windows->image.id,
6101 windows->image.highlight_context,coordinate_info,
6102 number_coordinates,CoordModeOrigin);
6104 XHighlightLine(display,windows->image.id,
6105 windows->image.highlight_context,&line_info);
6116 User has committed to element.
6118 line_info.x2=event.xbutton.x;
6119 line_info.y2=event.xbutton.y;
6120 rectangle_info.x=(ssize_t) event.xbutton.x;
6121 rectangle_info.y=(ssize_t) event.xbutton.y;
6122 coordinate_info[number_coordinates].x=event.xbutton.x;
6123 coordinate_info[number_coordinates].y=event.xbutton.y;
6124 if (((element != PolygonElement) &&
6125 (element != FillPolygonElement)) || (distance <= 9))
6130 number_coordinates++;
6131 if (number_coordinates < (int) max_coordinates)
6133 line_info.x1=event.xbutton.x;
6134 line_info.y1=event.xbutton.y;
6137 max_coordinates<<=1;
6138 coordinate_info=(XPoint *) ResizeQuantumMemory(coordinate_info,
6139 max_coordinates,sizeof(*coordinate_info));
6140 if (coordinate_info == (XPoint *) NULL)
6141 (void) ThrowMagickException(exception,GetMagickModule(),
6142 ResourceLimitError,"MemoryAllocationFailed","`%s'","...");
6149 if (event.xmotion.window != windows->image.id)
6151 if (element != PointElement)
6153 line_info.x2=event.xmotion.x;
6154 line_info.y2=event.xmotion.y;
6155 rectangle_info.x=(ssize_t) event.xmotion.x;
6156 rectangle_info.y=(ssize_t) event.xmotion.y;
6159 coordinate_info[number_coordinates].x=event.xbutton.x;
6160 coordinate_info[number_coordinates].y=event.xbutton.y;
6161 number_coordinates++;
6162 if (number_coordinates < (int) max_coordinates)
6164 max_coordinates<<=1;
6165 coordinate_info=(XPoint *) ResizeQuantumMemory(coordinate_info,
6166 max_coordinates,sizeof(*coordinate_info));
6167 if (coordinate_info == (XPoint *) NULL)
6168 (void) ThrowMagickException(exception,GetMagickModule(),
6169 ResourceLimitError,"MemoryAllocationFailed","`%s'","...");
6176 Check boundary conditions.
6178 if (line_info.x2 < 0)
6181 if (line_info.x2 > (int) windows->image.width)
6182 line_info.x2=(short) windows->image.width;
6183 if (line_info.y2 < 0)
6186 if (line_info.y2 > (int) windows->image.height)
6187 line_info.y2=(short) windows->image.height;
6188 distance=(unsigned int)
6189 (((line_info.x2-line_info.x1+1)*(line_info.x2-line_info.x1+1))+
6190 ((line_info.y2-line_info.y1+1)*(line_info.y2-line_info.y1+1)));
6191 if ((((int) rectangle_info.x != x) && ((int) rectangle_info.y != y)) ||
6192 ((state & ExitState) != 0))
6194 if (rectangle_info.x < 0)
6197 if (rectangle_info.x > (ssize_t) windows->image.width)
6198 rectangle_info.x=(ssize_t) windows->image.width;
6199 if ((int) rectangle_info.x < x)
6200 rectangle_info.width=(unsigned int) (x-rectangle_info.x);
6203 rectangle_info.width=(unsigned int) (rectangle_info.x-x);
6204 rectangle_info.x=(ssize_t) x;
6206 if (rectangle_info.y < 0)
6209 if (rectangle_info.y > (ssize_t) windows->image.height)
6210 rectangle_info.y=(ssize_t) windows->image.height;
6211 if ((int) rectangle_info.y < y)
6212 rectangle_info.height=(unsigned int) (y-rectangle_info.y);
6215 rectangle_info.height=(unsigned int) (rectangle_info.y-y);
6216 rectangle_info.y=(ssize_t) y;
6219 } while ((state & ExitState) == 0);
6220 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
6221 if ((element == PointElement) || (element == PolygonElement) ||
6222 (element == FillPolygonElement))
6225 Determine polygon bounding box.
6227 rectangle_info.x=(ssize_t) coordinate_info->x;
6228 rectangle_info.y=(ssize_t) coordinate_info->y;
6229 x=coordinate_info->x;
6230 y=coordinate_info->y;
6231 for (i=1; i < number_coordinates; i++)
6233 if (coordinate_info[i].x > x)
6234 x=coordinate_info[i].x;
6235 if (coordinate_info[i].y > y)
6236 y=coordinate_info[i].y;
6237 if ((ssize_t) coordinate_info[i].x < rectangle_info.x)
6238 rectangle_info.x=MagickMax((ssize_t) coordinate_info[i].x,0);
6239 if ((ssize_t) coordinate_info[i].y < rectangle_info.y)
6240 rectangle_info.y=MagickMax((ssize_t) coordinate_info[i].y,0);
6242 rectangle_info.width=(size_t) (x-rectangle_info.x);
6243 rectangle_info.height=(size_t) (y-rectangle_info.y);
6244 for (i=0; i < number_coordinates; i++)
6246 coordinate_info[i].x-=rectangle_info.x;
6247 coordinate_info[i].y-=rectangle_info.y;
6254 if ((element == RectangleElement) ||
6255 (element == CircleElement) || (element == EllipseElement))
6257 rectangle_info.width--;
6258 rectangle_info.height--;
6261 Drawing is relative to image configuration.
6263 draw_info.x=(int) rectangle_info.x;
6264 draw_info.y=(int) rectangle_info.y;
6265 (void) XMagickCommand(display,resource_info,windows,SaveToUndoBufferCommand,
6267 width=(unsigned int) (*image)->columns;
6268 height=(unsigned int) (*image)->rows;
6271 if (windows->image.crop_geometry != (char *) NULL)
6272 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
6273 draw_info.x+=windows->image.x-(line_width/2);
6274 if (draw_info.x < 0)
6276 draw_info.x=(int) (width*draw_info.x/windows->image.ximage->width);
6277 draw_info.y+=windows->image.y-(line_width/2);
6278 if (draw_info.y < 0)
6280 draw_info.y=(int) height*draw_info.y/windows->image.ximage->height;
6281 draw_info.width=(unsigned int) rectangle_info.width+(line_width << 1);
6282 if (draw_info.width > (unsigned int) (*image)->columns)
6283 draw_info.width=(unsigned int) (*image)->columns;
6284 draw_info.height=(unsigned int) rectangle_info.height+(line_width << 1);
6285 if (draw_info.height > (unsigned int) (*image)->rows)
6286 draw_info.height=(unsigned int) (*image)->rows;
6287 (void) FormatLocaleString(draw_info.geometry,MaxTextExtent,"%ux%u%+d%+d",
6288 width*draw_info.width/windows->image.ximage->width,
6289 height*draw_info.height/windows->image.ximage->height,
6290 draw_info.x+x,draw_info.y+y);
6292 Initialize drawing attributes.
6294 draw_info.degrees=0.0;
6295 draw_info.element=element;
6296 draw_info.stipple=stipple;
6297 draw_info.line_width=line_width;
6298 draw_info.line_info=line_info;
6299 if (line_info.x1 > (int) (line_width/2))
6300 draw_info.line_info.x1=(short) line_width/2;
6301 if (line_info.y1 > (int) (line_width/2))
6302 draw_info.line_info.y1=(short) line_width/2;
6303 draw_info.line_info.x2=(short) (line_info.x2-line_info.x1+(line_width/2));
6304 draw_info.line_info.y2=(short) (line_info.y2-line_info.y1+(line_width/2));
6305 if ((draw_info.line_info.x2 < 0) && (draw_info.line_info.y2 < 0))
6307 draw_info.line_info.x2=(-draw_info.line_info.x2);
6308 draw_info.line_info.y2=(-draw_info.line_info.y2);
6310 if (draw_info.line_info.x2 < 0)
6312 draw_info.line_info.x2=(-draw_info.line_info.x2);
6313 Swap(draw_info.line_info.x1,draw_info.line_info.x2);
6315 if (draw_info.line_info.y2 < 0)
6317 draw_info.line_info.y2=(-draw_info.line_info.y2);
6318 Swap(draw_info.line_info.y1,draw_info.line_info.y2);
6320 draw_info.rectangle_info=rectangle_info;
6321 if (draw_info.rectangle_info.x > (ssize_t) (line_width/2))
6322 draw_info.rectangle_info.x=(ssize_t) line_width/2;
6323 if (draw_info.rectangle_info.y > (ssize_t) (line_width/2))
6324 draw_info.rectangle_info.y=(ssize_t) line_width/2;
6325 draw_info.number_coordinates=(unsigned int) number_coordinates;
6326 draw_info.coordinate_info=coordinate_info;
6327 windows->pixel_info->pen_color=windows->pixel_info->pen_colors[pen_id];
6329 Draw element on image.
6331 XSetCursorState(display,windows,MagickTrue);
6332 XCheckRefreshWindows(display,windows);
6333 status=XDrawImage(display,windows->pixel_info,&draw_info,*image,exception);
6334 XSetCursorState(display,windows,MagickFalse);
6336 Update image colormap and return to image drawing.
6338 XConfigureImageColormap(display,resource_info,windows,*image,exception);
6339 (void) XConfigureImage(display,resource_info,windows,*image,exception);
6341 XSetCursorState(display,windows,MagickFalse);
6342 coordinate_info=(XPoint *) RelinquishMagickMemory(coordinate_info);
6343 return(IsMagickTrue(status));
6347 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6351 + X D r a w P a n R e c t a n g l e %
6355 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6357 % XDrawPanRectangle() draws a rectangle in the pan window. The pan window
6358 % displays a zoom image and the rectangle shows which portion of the image is
6359 % displayed in the Image window.
6361 % The format of the XDrawPanRectangle method is:
6363 % XDrawPanRectangle(Display *display,XWindows *windows)
6365 % A description of each parameter follows:
6367 % o display: Specifies a connection to an X server; returned from
6370 % o windows: Specifies a pointer to a XWindows structure.
6373 static void XDrawPanRectangle(Display *display,XWindows *windows)
6382 Determine dimensions of the panning rectangle.
6384 scale_factor=(double) windows->pan.width/windows->image.ximage->width;
6385 highlight_info.x=(ssize_t) (scale_factor*windows->image.x+0.5);
6386 highlight_info.width=(unsigned int) (scale_factor*windows->image.width+0.5);
6387 scale_factor=(double)
6388 windows->pan.height/windows->image.ximage->height;
6389 highlight_info.y=(ssize_t) (scale_factor*windows->image.y+0.5);
6390 highlight_info.height=(unsigned int) (scale_factor*windows->image.height+0.5);
6392 Display the panning rectangle.
6394 (void) XClearWindow(display,windows->pan.id);
6395 XHighlightRectangle(display,windows->pan.id,windows->pan.annotate_context,
6400 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6404 + X I m a g e C a c h e %
6408 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6410 % XImageCache() handles the creation, manipulation, and destruction of the
6411 % image cache (undo and redo buffers).
6413 % The format of the XImageCache method is:
6415 % void XImageCache(Display *display,XResourceInfo *resource_info,
6416 % XWindows *windows,const CommandType command,Image **image,
6417 % ExceptionInfo *exception)
6419 % A description of each parameter follows:
6421 % o display: Specifies a connection to an X server; returned from
6424 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
6426 % o windows: Specifies a pointer to a XWindows structure.
6428 % o command: Specifies a command to perform.
6430 % o image: the image; XImageCache may transform the image and return a new
6433 % o exception: return any errors or warnings in this structure.
6436 static void XImageCache(Display *display,XResourceInfo *resource_info,
6437 XWindows *windows,const CommandType command,Image **image,
6438 ExceptionInfo *exception)
6444 *redo_image = (Image *) NULL,
6445 *undo_image = (Image *) NULL;
6449 case FreeBuffersCommand:
6452 Free memory from the undo and redo cache.
6454 while (undo_image != (Image *) NULL)
6456 cache_image=undo_image;
6457 undo_image=GetPreviousImageInList(undo_image);
6458 cache_image->list=DestroyImage(cache_image->list);
6459 cache_image=DestroyImage(cache_image);
6461 undo_image=NewImageList();
6462 if (redo_image != (Image *) NULL)
6463 redo_image=DestroyImage(redo_image);
6464 redo_image=NewImageList();
6470 image_geometry[MaxTextExtent];
6473 Undo the last image transformation.
6475 if (undo_image == (Image *) NULL)
6477 (void) XBell(display,0);
6480 cache_image=undo_image;
6481 undo_image=GetPreviousImageInList(undo_image);
6482 windows->image.window_changes.width=(int) cache_image->columns;
6483 windows->image.window_changes.height=(int) cache_image->rows;
6484 (void) FormatLocaleString(image_geometry,MaxTextExtent,"%dx%d!",
6485 windows->image.ximage->width,windows->image.ximage->height);
6486 (void) TransformImage(image,windows->image.crop_geometry,image_geometry,
6488 if (windows->image.crop_geometry != (char *) NULL)
6489 windows->image.crop_geometry=(char *) RelinquishMagickMemory(
6490 windows->image.crop_geometry);
6491 windows->image.crop_geometry=cache_image->geometry;
6492 if (redo_image != (Image *) NULL)
6493 redo_image=DestroyImage(redo_image);
6494 redo_image=(*image);
6495 *image=cache_image->list;
6496 cache_image=DestroyImage(cache_image);
6497 if (IfMagickTrue(windows->image.orphan) )
6499 XConfigureImageColormap(display,resource_info,windows,*image,exception);
6500 (void) XConfigureImage(display,resource_info,windows,*image,exception);
6506 case HalfSizeCommand:
6507 case OriginalSizeCommand:
6508 case DoubleSizeCommand:
6515 case RotateRightCommand:
6516 case RotateLeftCommand:
6521 case ContrastStretchCommand:
6522 case SigmoidalContrastCommand:
6523 case NormalizeCommand:
6524 case EqualizeCommand:
6526 case SaturationCommand:
6527 case BrightnessCommand:
6531 case GrayscaleCommand:
6533 case QuantizeCommand:
6534 case DespeckleCommand:
6536 case ReduceNoiseCommand:
6537 case AddNoiseCommand:
6538 case SharpenCommand:
6540 case ThresholdCommand:
6541 case EdgeDetectCommand:
6545 case SegmentCommand:
6546 case SolarizeCommand:
6547 case SepiaToneCommand:
6549 case ImplodeCommand:
6550 case VignetteCommand:
6552 case OilPaintCommand:
6553 case CharcoalDrawCommand:
6554 case AnnotateCommand:
6555 case AddBorderCommand:
6556 case AddFrameCommand:
6557 case CompositeCommand:
6558 case CommentCommand:
6560 case RegionofInterestCommand:
6561 case SaveToUndoBufferCommand:
6570 bytes=(ssize_t) ((*image)->columns*(*image)->rows*sizeof(PixelInfo));
6571 if (undo_image != (Image *) NULL)
6574 Ensure the undo cache has enough memory available.
6576 previous_image=undo_image;
6577 while (previous_image != (Image *) NULL)
6579 bytes+=previous_image->list->columns*previous_image->list->rows*
6581 if (bytes <= (ssize_t) (resource_info->undo_cache << 20))
6583 previous_image=GetPreviousImageInList(previous_image);
6586 bytes-=previous_image->list->columns*previous_image->list->rows*
6588 if (previous_image == undo_image)
6589 undo_image=NewImageList();
6591 previous_image->next->previous=NewImageList();
6594 while (previous_image != (Image *) NULL)
6597 Delete any excess memory from undo cache.
6599 cache_image=previous_image;
6600 previous_image=GetPreviousImageInList(previous_image);
6601 cache_image->list=DestroyImage(cache_image->list);
6602 cache_image=DestroyImage(cache_image);
6605 if (bytes > (ssize_t) (resource_info->undo_cache << 20))
6608 Save image before transformations are applied.
6610 cache_image=AcquireImage((ImageInfo *) NULL,exception);
6611 if (cache_image == (Image *) NULL)
6613 XSetCursorState(display,windows,MagickTrue);
6614 XCheckRefreshWindows(display,windows);
6615 cache_image->list=CloneImage(*image,0,0,MagickTrue,exception);
6616 XSetCursorState(display,windows,MagickFalse);
6617 if (cache_image->list == (Image *) NULL)
6619 cache_image=DestroyImage(cache_image);
6622 cache_image->columns=(size_t) windows->image.ximage->width;
6623 cache_image->rows=(size_t) windows->image.ximage->height;
6624 cache_image->geometry=windows->image.crop_geometry;
6625 if (windows->image.crop_geometry != (char *) NULL)
6627 cache_image->geometry=AcquireString((char *) NULL);
6628 (void) CopyMagickString(cache_image->geometry,
6629 windows->image.crop_geometry,MaxTextExtent);
6631 if (undo_image == (Image *) NULL)
6633 undo_image=cache_image;
6636 undo_image->next=cache_image;
6637 undo_image->next->previous=undo_image;
6638 undo_image=undo_image->next;
6644 if (command == RedoCommand)
6647 Redo the last image transformation.
6649 if (redo_image == (Image *) NULL)
6651 (void) XBell(display,0);
6654 windows->image.window_changes.width=(int) redo_image->columns;
6655 windows->image.window_changes.height=(int) redo_image->rows;
6656 if (windows->image.crop_geometry != (char *) NULL)
6657 windows->image.crop_geometry=(char *)
6658 RelinquishMagickMemory(windows->image.crop_geometry);
6659 windows->image.crop_geometry=redo_image->geometry;
6660 *image=DestroyImage(*image);
6662 redo_image=NewImageList();
6663 if (IfMagickTrue(windows->image.orphan) )
6665 XConfigureImageColormap(display,resource_info,windows,*image,exception);
6666 (void) XConfigureImage(display,resource_info,windows,*image,exception);
6669 if (command != InfoCommand)
6674 XSetCursorState(display,windows,MagickTrue);
6675 XCheckRefreshWindows(display,windows);
6676 XDisplayImageInfo(display,resource_info,windows,undo_image,*image,exception);
6677 XSetCursorState(display,windows,MagickFalse);
6681 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6685 + X I m a g e W i n d o w C o m m a n d %
6689 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6691 % XImageWindowCommand() makes a transform to the image or Image window as
6692 % specified by a user menu button or keyboard command.
6694 % The format of the XImageWindowCommand method is:
6696 % CommandType XImageWindowCommand(Display *display,
6697 % XResourceInfo *resource_info,XWindows *windows,
6698 % const MagickStatusType state,KeySym key_symbol,Image **image,
6699 % ExceptionInfo *exception)
6701 % A description of each parameter follows:
6703 % o nexus: Method XImageWindowCommand returns an image when the
6704 % user chooses 'Open Image' from the command menu. Otherwise a null
6705 % image is returned.
6707 % o display: Specifies a connection to an X server; returned from
6710 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
6712 % o windows: Specifies a pointer to a XWindows structure.
6714 % o state: key mask.
6716 % o key_symbol: Specifies a command to perform.
6718 % o image: the image; XImageWIndowCommand may transform the image and
6719 % return a new image pointer.
6721 % o exception: return any errors or warnings in this structure.
6724 static CommandType XImageWindowCommand(Display *display,
6725 XResourceInfo *resource_info,XWindows *windows,const MagickStatusType state,
6726 KeySym key_symbol,Image **image,ExceptionInfo *exception)
6729 delta[MaxTextExtent] = "";
6732 Digits[] = "01234567890";
6737 if ((key_symbol >= XK_0) && (key_symbol <= XK_9))
6739 if (((last_symbol < XK_0) || (last_symbol > XK_9)))
6742 resource_info->quantum=1;
6744 last_symbol=key_symbol;
6745 delta[strlen(delta)+1]='\0';
6746 delta[strlen(delta)]=Digits[key_symbol-XK_0];
6747 resource_info->quantum=StringToLong(delta);
6748 return(NullCommand);
6750 last_symbol=key_symbol;
6751 if (resource_info->immutable)
6754 Virtual image window has a restricted command set.
6759 return(InfoCommand);
6762 return(PrintCommand);
6764 return(NextCommand);
6767 return(QuitCommand);
6771 return(NullCommand);
6773 switch ((int) key_symbol)
6777 if ((state & ControlMask) == 0)
6779 return(OpenCommand);
6782 return(NextCommand);
6784 return(FormerCommand);
6787 if ((state & Mod1Mask) != 0)
6788 return(SwirlCommand);
6789 if ((state & ControlMask) == 0)
6790 return(ShearCommand);
6791 return(SaveCommand);
6796 if ((state & Mod1Mask) != 0)
6797 return(OilPaintCommand);
6798 if ((state & Mod4Mask) != 0)
6799 return(ColorCommand);
6800 if ((state & ControlMask) == 0)
6801 return(NullCommand);
6802 return(PrintCommand);
6806 if ((state & Mod4Mask) != 0)
6807 return(DrawCommand);
6808 if ((state & ControlMask) == 0)
6809 return(NullCommand);
6810 return(DeleteCommand);
6814 if ((state & ControlMask) == 0)
6815 return(NullCommand);
6816 return(SelectCommand);
6820 if ((state & ControlMask) == 0)
6821 return(NullCommand);
6826 return(QuitCommand);
6830 if ((state & ControlMask) == 0)
6831 return(NullCommand);
6832 return(UndoCommand);
6837 if ((state & ControlMask) == 0)
6838 return(RollCommand);
6839 return(RedoCommand);
6843 if ((state & ControlMask) == 0)
6844 return(NullCommand);
6849 if ((state & Mod1Mask) != 0)
6850 return(CharcoalDrawCommand);
6851 if ((state & ControlMask) == 0)
6852 return(CropCommand);
6853 return(CopyCommand);
6858 if ((state & Mod4Mask) != 0)
6859 return(CompositeCommand);
6860 if ((state & ControlMask) == 0)
6861 return(FlipCommand);
6862 return(PasteCommand);
6865 return(HalfSizeCommand);
6867 return(OriginalSizeCommand);
6869 return(DoubleSizeCommand);
6871 return(ResizeCommand);
6873 return(RefreshCommand);
6874 case XK_bracketleft:
6875 return(ChopCommand);
6877 return(FlopCommand);
6879 return(RotateRightCommand);
6881 return(RotateLeftCommand);
6883 return(RotateCommand);
6885 return(TrimCommand);
6889 return(SaturationCommand);
6891 return(BrightnessCommand);
6893 return(GammaCommand);
6895 return(SpiffCommand);
6897 return(DullCommand);
6899 return(NormalizeCommand);
6901 return(EqualizeCommand);
6903 return(NegateCommand);
6905 return(GrayscaleCommand);
6907 return(QuantizeCommand);
6909 return(DespeckleCommand);
6911 return(EmbossCommand);
6913 return(ReduceNoiseCommand);
6915 return(AddNoiseCommand);
6917 return(SharpenCommand);
6919 return(BlurCommand);
6921 return(ThresholdCommand);
6923 return(EdgeDetectCommand);
6925 return(SpreadCommand);
6927 return(ShadeCommand);
6929 return(RaiseCommand);
6931 return(SegmentCommand);
6934 if ((state & Mod1Mask) == 0)
6935 return(NullCommand);
6936 return(ImplodeCommand);
6940 if ((state & Mod1Mask) == 0)
6941 return(NullCommand);
6942 return(WaveCommand);
6946 if ((state & Mod4Mask) == 0)
6947 return(NullCommand);
6948 return(MatteCommand);
6952 if ((state & Mod4Mask) == 0)
6953 return(NullCommand);
6954 return(AddBorderCommand);
6958 if ((state & Mod4Mask) == 0)
6959 return(NullCommand);
6960 return(AddFrameCommand);
6964 if ((state & Mod4Mask) == 0)
6965 return(NullCommand);
6966 return(CommentCommand);
6970 if ((state & Mod1Mask) != 0)
6971 return(ApplyCommand);
6972 if ((state & Mod4Mask) != 0)
6973 return(AnnotateCommand);
6974 if ((state & ControlMask) == 0)
6975 return(NullCommand);
6976 return(RegionofInterestCommand);
6979 return(InfoCommand);
6981 return(ZoomCommand);
6984 if ((state & ShiftMask) == 0)
6985 return(NullCommand);
6986 return(ShowPreviewCommand);
6989 return(LaunchCommand);
6991 return(HelpCommand);
6993 return(BrowseDocumentationCommand);
6996 (void) XMapRaised(display,windows->command.id);
6997 return(NullCommand);
7004 XTranslateImage(display,windows,*image,key_symbol);
7005 return(NullCommand);
7016 if ((state & Mod1Mask) != 0)
7022 Trim one pixel from edge of image.
7026 crop_info.width=(size_t) windows->image.ximage->width;
7027 crop_info.height=(size_t) windows->image.ximage->height;
7028 if ((key_symbol == XK_Up) || (key_symbol == XK_KP_Up))
7030 if (resource_info->quantum >= (int) crop_info.height)
7031 resource_info->quantum=(int) crop_info.height-1;
7032 crop_info.height-=resource_info->quantum;
7034 if ((key_symbol == XK_Down) || (key_symbol == XK_KP_Down))
7036 if (resource_info->quantum >= (int) (crop_info.height-crop_info.y))
7037 resource_info->quantum=(int) (crop_info.height-crop_info.y-1);
7038 crop_info.y+=resource_info->quantum;
7039 crop_info.height-=resource_info->quantum;
7041 if ((key_symbol == XK_Left) || (key_symbol == XK_KP_Left))
7043 if (resource_info->quantum >= (int) crop_info.width)
7044 resource_info->quantum=(int) crop_info.width-1;
7045 crop_info.width-=resource_info->quantum;
7047 if ((key_symbol == XK_Right) || (key_symbol == XK_KP_Right))
7049 if (resource_info->quantum >= (int) (crop_info.width-crop_info.x))
7050 resource_info->quantum=(int) (crop_info.width-crop_info.x-1);
7051 crop_info.x+=resource_info->quantum;
7052 crop_info.width-=resource_info->quantum;
7054 if ((int) (windows->image.x+windows->image.width) >
7055 (int) crop_info.width)
7056 windows->image.x=(int) (crop_info.width-windows->image.width);
7057 if ((int) (windows->image.y+windows->image.height) >
7058 (int) crop_info.height)
7059 windows->image.y=(int) (crop_info.height-windows->image.height);
7060 XSetCropGeometry(display,windows,&crop_info,*image);
7061 windows->image.window_changes.width=(int) crop_info.width;
7062 windows->image.window_changes.height=(int) crop_info.height;
7063 (void) XSetWindowBackgroundPixmap(display,windows->image.id,None);
7064 (void) XConfigureImage(display,resource_info,windows,*image,
7066 return(NullCommand);
7068 XTranslateImage(display,windows,*image,key_symbol);
7069 return(NullCommand);
7072 return(NullCommand);
7074 return(NullCommand);
7078 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7082 + X M a g i c k C o m m a n d %
7086 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7088 % XMagickCommand() makes a transform to the image or Image window as
7089 % specified by a user menu button or keyboard command.
7091 % The format of the XMagickCommand method is:
7093 % Image *XMagickCommand(Display *display,XResourceInfo *resource_info,
7094 % XWindows *windows,const CommandType command,Image **image,
7095 % ExceptionInfo *exception)
7097 % A description of each parameter follows:
7099 % o display: Specifies a connection to an X server; returned from
7102 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
7104 % o windows: Specifies a pointer to a XWindows structure.
7106 % o command: Specifies a command to perform.
7108 % o image: the image; XMagickCommand may transform the image and return a
7109 % new image pointer.
7111 % o exception: return any errors or warnings in this structure.
7114 static Image *XMagickCommand(Display *display,XResourceInfo *resource_info,
7115 XWindows *windows,const CommandType command,Image **image,
7116 ExceptionInfo *exception)
7119 filename[MaxTextExtent],
7120 geometry[MaxTextExtent],
7121 modulate_factors[MaxTextExtent];
7150 color[MaxTextExtent] = "gray";
7157 Process user command.
7159 XCheckRefreshWindows(display,windows);
7160 XImageCache(display,resource_info,windows,command,image,exception);
7161 nexus=NewImageList();
7162 windows->image.window_changes.width=windows->image.ximage->width;
7163 windows->image.window_changes.height=windows->image.ximage->height;
7164 image_info=CloneImageInfo(resource_info->image_info);
7165 SetGeometryInfo(&geometry_info);
7166 GetQuantizeInfo(&quantize_info);
7174 nexus=XOpenImage(display,resource_info,windows,MagickFalse);
7182 for (i=0; i < resource_info->quantum; i++)
7183 XClientMessage(display,windows->image.id,windows->im_protocols,
7184 windows->im_next_image,CurrentTime);
7190 Display former image.
7192 for (i=0; i < resource_info->quantum; i++)
7193 XClientMessage(display,windows->image.id,windows->im_protocols,
7194 windows->im_former_image,CurrentTime);
7205 if (*resource_info->home_directory == '\0')
7206 (void) CopyMagickString(resource_info->home_directory,".",
7208 status=chdir(resource_info->home_directory);
7210 (void) ThrowMagickException(exception,GetMagickModule(),FileOpenError,
7211 "UnableToOpenFile","%s",resource_info->home_directory);
7212 nexus=XOpenImage(display,resource_info,windows,MagickTrue);
7220 status=XSaveImage(display,resource_info,windows,*image,exception);
7221 if (IfMagickFalse(status) )
7224 message[MaxTextExtent];
7226 (void) FormatLocaleString(message,MaxTextExtent,"%s:%s",
7227 exception->reason != (char *) NULL ? exception->reason : "",
7228 exception->description != (char *) NULL ? exception->description :
7230 XNoticeWidget(display,windows,"Unable to save file:",message);
7240 status=XPrintImage(display,resource_info,windows,*image,exception);
7241 if (IfMagickFalse(status) )
7244 message[MaxTextExtent];
7246 (void) FormatLocaleString(message,MaxTextExtent,"%s:%s",
7247 exception->reason != (char *) NULL ? exception->reason : "",
7248 exception->description != (char *) NULL ? exception->description :
7250 XNoticeWidget(display,windows,"Unable to print file:",message);
7258 filename[MaxTextExtent] = "\0";
7263 XFileBrowserWidget(display,windows,"Delete",filename);
7264 if (*filename == '\0')
7266 status=ShredFile(filename);
7267 if (IfMagickTrue(status) )
7268 XNoticeWidget(display,windows,"Unable to delete image file:",filename);
7277 color[MaxTextExtent] = "gray",
7278 geometry[MaxTextExtent] = "640x480";
7281 *format = "gradient";
7284 Query user for canvas geometry.
7286 status=XDialogWidget(display,windows,"New","Enter image geometry:",
7288 if (*geometry == '\0')
7292 XColorBrowserWidget(display,windows,"Select",color);
7298 (void) FormatLocaleString(image_info->filename,MaxTextExtent,
7299 "%s:%s",format,color);
7300 (void) CloneString(&image_info->size,geometry);
7301 nexus=ReadImage(image_info,exception);
7302 CatchException(exception);
7303 XClientMessage(display,windows->image.id,windows->im_protocols,
7304 windows->im_next_image,CurrentTime);
7307 case VisualDirectoryCommand:
7310 Visual Image directory.
7312 nexus=XVisualDirectoryImage(display,resource_info,windows,exception);
7320 if (IfMagickFalse(resource_info->confirm_exit) )
7321 XClientMessage(display,windows->image.id,windows->im_protocols,
7322 windows->im_exit,CurrentTime);
7329 Confirm program exit.
7331 status=XConfirmWidget(display,windows,"Do you really want to exit",
7332 resource_info->client_name);
7334 XClientMessage(display,windows->image.id,windows->im_protocols,
7335 windows->im_exit,CurrentTime);
7344 (void) XCropImage(display,resource_info,windows,*image,CutMode,exception);
7352 (void) XCropImage(display,resource_info,windows,*image,CopyMode,
7361 status=XPasteImage(display,resource_info,windows,*image,exception);
7362 if (IfMagickFalse(status) )
7364 XNoticeWidget(display,windows,"Unable to paste X image",
7365 (*image)->filename);
7370 case HalfSizeCommand:
7375 windows->image.window_changes.width=windows->image.ximage->width/2;
7376 windows->image.window_changes.height=windows->image.ximage->height/2;
7377 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7380 case OriginalSizeCommand:
7383 Original image size.
7385 windows->image.window_changes.width=(int) (*image)->columns;
7386 windows->image.window_changes.height=(int) (*image)->rows;
7387 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7390 case DoubleSizeCommand:
7393 Double the image size.
7395 windows->image.window_changes.width=windows->image.ximage->width << 1;
7396 windows->image.window_changes.height=windows->image.ximage->height << 1;
7397 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7416 width=(size_t) windows->image.ximage->width;
7417 height=(size_t) windows->image.ximage->height;
7420 (void) FormatLocaleString(geometry,MaxTextExtent,"%.20gx%.20g+0+0",
7421 (double) width,(double) height);
7422 status=XDialogWidget(display,windows,"Resize",
7423 "Enter resize geometry (e.g. 640x480, 200%):",geometry);
7424 if (*geometry == '\0')
7427 (void) ConcatenateMagickString(geometry,"!",MaxTextExtent);
7428 (void) ParseMetaGeometry(geometry,&x,&y,&width,&height);
7429 windows->image.window_changes.width=(int) width;
7430 windows->image.window_changes.height=(int) height;
7431 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7437 image_geometry[MaxTextExtent];
7439 if ((windows->image.crop_geometry == (char *) NULL) &&
7440 ((int) (*image)->columns == windows->image.ximage->width) &&
7441 ((int) (*image)->rows == windows->image.ximage->height))
7444 Apply size transforms to image.
7446 XSetCursorState(display,windows,MagickTrue);
7447 XCheckRefreshWindows(display,windows);
7449 Crop and/or scale displayed image.
7451 (void) FormatLocaleString(image_geometry,MaxTextExtent,"%dx%d!",
7452 windows->image.ximage->width,windows->image.ximage->height);
7453 (void) TransformImage(image,windows->image.crop_geometry,image_geometry,
7455 if (windows->image.crop_geometry != (char *) NULL)
7456 windows->image.crop_geometry=(char *) RelinquishMagickMemory(
7457 windows->image.crop_geometry);
7460 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7461 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7464 case RefreshCommand:
7466 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7469 case RestoreCommand:
7472 Restore Image window to its original size.
7474 if ((windows->image.width == (unsigned int) (*image)->columns) &&
7475 (windows->image.height == (unsigned int) (*image)->rows) &&
7476 (windows->image.crop_geometry == (char *) NULL))
7478 (void) XBell(display,0);
7481 windows->image.window_changes.width=(int) (*image)->columns;
7482 windows->image.window_changes.height=(int) (*image)->rows;
7483 if (windows->image.crop_geometry != (char *) NULL)
7485 windows->image.crop_geometry=(char *)
7486 RelinquishMagickMemory(windows->image.crop_geometry);
7487 windows->image.crop_geometry=(char *) NULL;
7491 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7492 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7500 (void) XCropImage(display,resource_info,windows,*image,CropMode,
7509 status=XChopImage(display,resource_info,windows,image,exception);
7510 if (IfMagickFalse(status) )
7512 XNoticeWidget(display,windows,"Unable to cut X image",
7513 (*image)->filename);
7524 Flop image scanlines.
7526 XSetCursorState(display,windows,MagickTrue);
7527 XCheckRefreshWindows(display,windows);
7528 flop_image=FlopImage(*image,exception);
7529 if (flop_image != (Image *) NULL)
7531 *image=DestroyImage(*image);
7534 CatchException(exception);
7535 XSetCursorState(display,windows,MagickFalse);
7536 if (windows->image.crop_geometry != (char *) NULL)
7541 width=(unsigned int) (*image)->columns;
7542 height=(unsigned int) (*image)->rows;
7543 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,
7545 (void) FormatLocaleString(windows->image.crop_geometry,MaxTextExtent,
7546 "%ux%u%+d%+d",width,height,(int) (*image)->columns-(int) width-x,y);
7548 if (IfMagickTrue(windows->image.orphan) )
7550 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7559 Flip image scanlines.
7561 XSetCursorState(display,windows,MagickTrue);
7562 XCheckRefreshWindows(display,windows);
7563 flip_image=FlipImage(*image,exception);
7564 if (flip_image != (Image *) NULL)
7566 *image=DestroyImage(*image);
7569 CatchException(exception);
7570 XSetCursorState(display,windows,MagickFalse);
7571 if (windows->image.crop_geometry != (char *) NULL)
7576 width=(unsigned int) (*image)->columns;
7577 height=(unsigned int) (*image)->rows;
7578 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,
7580 (void) FormatLocaleString(windows->image.crop_geometry,MaxTextExtent,
7581 "%ux%u%+d%+d",width,height,x,(int) (*image)->rows-(int) height-y);
7583 if (IfMagickTrue(windows->image.orphan) )
7585 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7588 case RotateRightCommand:
7591 Rotate image 90 degrees clockwise.
7593 status=XRotateImage(display,resource_info,windows,90.0,image,exception);
7594 if (IfMagickFalse(status) )
7596 XNoticeWidget(display,windows,"Unable to rotate X image",
7597 (*image)->filename);
7602 case RotateLeftCommand:
7605 Rotate image 90 degrees counter-clockwise.
7607 status=XRotateImage(display,resource_info,windows,-90.0,image,exception);
7608 if (IfMagickFalse(status) )
7610 XNoticeWidget(display,windows,"Unable to rotate X image",
7611 (*image)->filename);
7621 status=XRotateImage(display,resource_info,windows,0.0,image,exception);
7622 if (IfMagickFalse(status) )
7624 XNoticeWidget(display,windows,"Unable to rotate X image",
7625 (*image)->filename);
7636 geometry[MaxTextExtent] = "45.0x45.0";
7639 Query user for shear color and geometry.
7641 XColorBrowserWidget(display,windows,"Select",color);
7644 (void) XDialogWidget(display,windows,"Shear","Enter shear geometry:",
7646 if (*geometry == '\0')
7651 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image,
7653 XSetCursorState(display,windows,MagickTrue);
7654 XCheckRefreshWindows(display,windows);
7655 (void) QueryColorCompliance(color,AllCompliance,
7656 &(*image)->background_color,exception);
7657 flags=ParseGeometry(geometry,&geometry_info);
7658 if ((flags & SigmaValue) == 0)
7659 geometry_info.sigma=geometry_info.rho;
7660 shear_image=ShearImage(*image,geometry_info.rho,geometry_info.sigma,
7662 if (shear_image != (Image *) NULL)
7664 *image=DestroyImage(*image);
7667 CatchException(exception);
7668 XSetCursorState(display,windows,MagickFalse);
7669 if (IfMagickTrue(windows->image.orphan) )
7671 windows->image.window_changes.width=(int) (*image)->columns;
7672 windows->image.window_changes.height=(int) (*image)->rows;
7673 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7674 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7683 geometry[MaxTextExtent] = "+2+2";
7686 Query user for the roll geometry.
7688 (void) XDialogWidget(display,windows,"Roll","Enter roll geometry:",
7690 if (*geometry == '\0')
7695 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image,
7697 XSetCursorState(display,windows,MagickTrue);
7698 XCheckRefreshWindows(display,windows);
7699 (void) ParsePageGeometry(*image,geometry,&page_geometry,
7701 roll_image=RollImage(*image,page_geometry.x,page_geometry.y,
7703 if (roll_image != (Image *) NULL)
7705 *image=DestroyImage(*image);
7708 CatchException(exception);
7709 XSetCursorState(display,windows,MagickFalse);
7710 if (IfMagickTrue(windows->image.orphan) )
7712 windows->image.window_changes.width=(int) (*image)->columns;
7713 windows->image.window_changes.height=(int) (*image)->rows;
7714 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7715 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7721 fuzz[MaxTextExtent];
7724 Query user for the fuzz factor.
7726 (void) FormatLocaleString(fuzz,MaxTextExtent,"%g%%",100.0*
7727 (*image)->fuzz/(QuantumRange+1.0));
7728 (void) XDialogWidget(display,windows,"Trim","Enter fuzz factor:",fuzz);
7731 (*image)->fuzz=StringToDoubleInterval(fuzz,(double) QuantumRange+1.0);
7735 status=XTrimImage(display,resource_info,windows,*image,exception);
7736 if (IfMagickFalse(status) )
7738 XNoticeWidget(display,windows,"Unable to trim X image",
7739 (*image)->filename);
7747 hue_percent[MaxTextExtent] = "110";
7750 Query user for percent hue change.
7752 (void) XDialogWidget(display,windows,"Apply",
7753 "Enter percent change in image hue (0-200):",hue_percent);
7754 if (*hue_percent == '\0')
7759 XSetCursorState(display,windows,MagickTrue);
7760 XCheckRefreshWindows(display,windows);
7761 (void) CopyMagickString(modulate_factors,"100.0/100.0/",MaxTextExtent);
7762 (void) ConcatenateMagickString(modulate_factors,hue_percent,
7764 (void) ModulateImage(*image,modulate_factors,exception);
7765 XSetCursorState(display,windows,MagickFalse);
7766 if (IfMagickTrue(windows->image.orphan) )
7768 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7769 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7772 case SaturationCommand:
7775 saturation_percent[MaxTextExtent] = "110";
7778 Query user for percent saturation change.
7780 (void) XDialogWidget(display,windows,"Apply",
7781 "Enter percent change in color saturation (0-200):",saturation_percent);
7782 if (*saturation_percent == '\0')
7785 Vary color saturation.
7787 XSetCursorState(display,windows,MagickTrue);
7788 XCheckRefreshWindows(display,windows);
7789 (void) CopyMagickString(modulate_factors,"100.0/",MaxTextExtent);
7790 (void) ConcatenateMagickString(modulate_factors,saturation_percent,
7792 (void) ModulateImage(*image,modulate_factors,exception);
7793 XSetCursorState(display,windows,MagickFalse);
7794 if (IfMagickTrue(windows->image.orphan) )
7796 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7797 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7800 case BrightnessCommand:
7803 brightness_percent[MaxTextExtent] = "110";
7806 Query user for percent brightness change.
7808 (void) XDialogWidget(display,windows,"Apply",
7809 "Enter percent change in color brightness (0-200):",brightness_percent);
7810 if (*brightness_percent == '\0')
7813 Vary the color brightness.
7815 XSetCursorState(display,windows,MagickTrue);
7816 XCheckRefreshWindows(display,windows);
7817 (void) CopyMagickString(modulate_factors,brightness_percent,
7819 (void) ModulateImage(*image,modulate_factors,exception);
7820 XSetCursorState(display,windows,MagickFalse);
7821 if (IfMagickTrue(windows->image.orphan) )
7823 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7824 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7830 factor[MaxTextExtent] = "1.6";
7833 Query user for gamma value.
7835 (void) XDialogWidget(display,windows,"Gamma",
7836 "Enter gamma value (e.g. 1.2):",factor);
7837 if (*factor == '\0')
7840 Gamma correct image.
7842 XSetCursorState(display,windows,MagickTrue);
7843 XCheckRefreshWindows(display,windows);
7844 (void) GammaImage(*image,atof(factor),exception);
7845 XSetCursorState(display,windows,MagickFalse);
7846 if (IfMagickTrue(windows->image.orphan) )
7848 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7849 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7855 Sharpen the image contrast.
7857 XSetCursorState(display,windows,MagickTrue);
7858 XCheckRefreshWindows(display,windows);
7859 (void) ContrastImage(*image,MagickTrue,exception);
7860 XSetCursorState(display,windows,MagickFalse);
7861 if (IfMagickTrue(windows->image.orphan) )
7863 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7864 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7870 Dull the image contrast.
7872 XSetCursorState(display,windows,MagickTrue);
7873 XCheckRefreshWindows(display,windows);
7874 (void) ContrastImage(*image,MagickFalse,exception);
7875 XSetCursorState(display,windows,MagickFalse);
7876 if (IfMagickTrue(windows->image.orphan) )
7878 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7879 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7882 case ContrastStretchCommand:
7889 levels[MaxTextExtent] = "1%";
7892 Query user for gamma value.
7894 (void) XDialogWidget(display,windows,"Contrast Stretch",
7895 "Enter black and white points:",levels);
7896 if (*levels == '\0')
7899 Contrast stretch image.
7901 XSetCursorState(display,windows,MagickTrue);
7902 XCheckRefreshWindows(display,windows);
7903 flags=ParseGeometry(levels,&geometry_info);
7904 black_point=geometry_info.rho;
7905 white_point=(flags & SigmaValue) != 0 ? geometry_info.sigma : black_point;
7906 if ((flags & PercentValue) != 0)
7908 black_point*=(double) (*image)->columns*(*image)->rows/100.0;
7909 white_point*=(double) (*image)->columns*(*image)->rows/100.0;
7911 white_point=(double) (*image)->columns*(*image)->rows-white_point;
7912 (void) ContrastStretchImage(*image,black_point,white_point,
7914 XSetCursorState(display,windows,MagickFalse);
7915 if (IfMagickTrue(windows->image.orphan) )
7917 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7918 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7921 case SigmoidalContrastCommand:
7930 levels[MaxTextExtent] = "3x50%";
7933 Query user for gamma value.
7935 (void) XDialogWidget(display,windows,"Sigmoidal Contrast",
7936 "Enter contrast and midpoint:",levels);
7937 if (*levels == '\0')
7940 Contrast stretch image.
7942 XSetCursorState(display,windows,MagickTrue);
7943 XCheckRefreshWindows(display,windows);
7944 flags=ParseGeometry(levels,&geometry_info);
7945 if ((flags & SigmaValue) == 0)
7946 geometry_info.sigma=1.0*QuantumRange/2.0;
7947 if ((flags & PercentValue) != 0)
7948 geometry_info.sigma=1.0*QuantumRange*geometry_info.sigma/100.0;
7949 (void) SigmoidalContrastImage(*image,MagickTrue,geometry_info.rho,
7950 geometry_info.sigma,exception);
7951 XSetCursorState(display,windows,MagickFalse);
7952 if (IfMagickTrue(windows->image.orphan) )
7954 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7955 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7958 case NormalizeCommand:
7961 Perform histogram normalization on the image.
7963 XSetCursorState(display,windows,MagickTrue);
7964 XCheckRefreshWindows(display,windows);
7965 (void) NormalizeImage(*image,exception);
7966 XSetCursorState(display,windows,MagickFalse);
7967 if (IfMagickTrue(windows->image.orphan) )
7969 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7970 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7973 case EqualizeCommand:
7976 Perform histogram equalization on the image.
7978 XSetCursorState(display,windows,MagickTrue);
7979 XCheckRefreshWindows(display,windows);
7980 (void) EqualizeImage(*image,exception);
7981 XSetCursorState(display,windows,MagickFalse);
7982 if (IfMagickTrue(windows->image.orphan) )
7984 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7985 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7991 Negate colors in image.
7993 XSetCursorState(display,windows,MagickTrue);
7994 XCheckRefreshWindows(display,windows);
7995 (void) NegateImage(*image,MagickFalse,exception);
7996 XSetCursorState(display,windows,MagickFalse);
7997 if (IfMagickTrue(windows->image.orphan) )
7999 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8000 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8003 case GrayscaleCommand:
8006 Convert image to grayscale.
8008 XSetCursorState(display,windows,MagickTrue);
8009 XCheckRefreshWindows(display,windows);
8010 (void) SetImageType(*image,(*image)->alpha_trait != BlendPixelTrait ?
8011 GrayscaleType : GrayscaleMatteType,exception);
8012 XSetCursorState(display,windows,MagickFalse);
8013 if (IfMagickTrue(windows->image.orphan) )
8015 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8016 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8025 filename[MaxTextExtent] = "\0";
8028 Request image file name from user.
8030 XFileBrowserWidget(display,windows,"Map",filename);
8031 if (*filename == '\0')
8036 XSetCursorState(display,windows,MagickTrue);
8037 XCheckRefreshWindows(display,windows);
8038 (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
8039 affinity_image=ReadImage(image_info,exception);
8040 if (affinity_image != (Image *) NULL)
8042 (void) RemapImage(&quantize_info,*image,affinity_image,exception);
8043 affinity_image=DestroyImage(affinity_image);
8045 CatchException(exception);
8046 XSetCursorState(display,windows,MagickFalse);
8047 if (IfMagickTrue(windows->image.orphan) )
8049 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8050 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8053 case QuantizeCommand:
8059 colors[MaxTextExtent] = "256";
8062 Query user for maximum number of colors.
8064 status=XDialogWidget(display,windows,"Quantize",
8065 "Maximum number of colors:",colors);
8066 if (*colors == '\0')
8069 Color reduce the image.
8071 XSetCursorState(display,windows,MagickTrue);
8072 XCheckRefreshWindows(display,windows);
8073 quantize_info.number_colors=StringToUnsignedLong(colors);
8074 quantize_info.dither_method=status != 0 ? RiemersmaDitherMethod :
8076 (void) QuantizeImage(&quantize_info,*image,exception);
8077 XSetCursorState(display,windows,MagickFalse);
8078 if (IfMagickTrue(windows->image.orphan) )
8080 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8081 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8084 case DespeckleCommand:
8092 XSetCursorState(display,windows,MagickTrue);
8093 XCheckRefreshWindows(display,windows);
8094 despeckle_image=DespeckleImage(*image,exception);
8095 if (despeckle_image != (Image *) NULL)
8097 *image=DestroyImage(*image);
8098 *image=despeckle_image;
8100 CatchException(exception);
8101 XSetCursorState(display,windows,MagickFalse);
8102 if (IfMagickTrue(windows->image.orphan) )
8104 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8105 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8114 radius[MaxTextExtent] = "0.0x1.0";
8117 Query user for emboss radius.
8119 (void) XDialogWidget(display,windows,"Emboss",
8120 "Enter the emboss radius and standard deviation:",radius);
8121 if (*radius == '\0')
8124 Reduce noise in the image.
8126 XSetCursorState(display,windows,MagickTrue);
8127 XCheckRefreshWindows(display,windows);
8128 flags=ParseGeometry(radius,&geometry_info);
8129 if ((flags & SigmaValue) == 0)
8130 geometry_info.sigma=1.0;
8131 emboss_image=EmbossImage(*image,geometry_info.rho,geometry_info.sigma,
8133 if (emboss_image != (Image *) NULL)
8135 *image=DestroyImage(*image);
8136 *image=emboss_image;
8138 CatchException(exception);
8139 XSetCursorState(display,windows,MagickFalse);
8140 if (IfMagickTrue(windows->image.orphan) )
8142 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8143 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8146 case ReduceNoiseCommand:
8152 radius[MaxTextExtent] = "0";
8155 Query user for noise radius.
8157 (void) XDialogWidget(display,windows,"Reduce Noise",
8158 "Enter the noise radius:",radius);
8159 if (*radius == '\0')
8162 Reduce noise in the image.
8164 XSetCursorState(display,windows,MagickTrue);
8165 XCheckRefreshWindows(display,windows);
8166 flags=ParseGeometry(radius,&geometry_info);
8167 noise_image=StatisticImage(*image,NonpeakStatistic,(size_t)
8168 geometry_info.rho,(size_t) geometry_info.rho,exception);
8169 if (noise_image != (Image *) NULL)
8171 *image=DestroyImage(*image);
8174 CatchException(exception);
8175 XSetCursorState(display,windows,MagickFalse);
8176 if (IfMagickTrue(windows->image.orphan) )
8178 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8179 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8182 case AddNoiseCommand:
8191 noise_type[MaxTextExtent] = "Gaussian";
8194 Add noise to the image.
8196 noises=GetCommandOptions(MagickNoiseOptions);
8197 if (noises == (char **) NULL)
8199 XListBrowserWidget(display,windows,&windows->widget,
8200 (const char **) noises,"Add Noise",
8201 "Select a type of noise to add to your image:",noise_type);
8202 noises=DestroyStringList(noises);
8203 if (*noise_type == '\0')
8205 XSetCursorState(display,windows,MagickTrue);
8206 XCheckRefreshWindows(display,windows);
8207 noise_image=AddNoiseImage(*image,(NoiseType) ParseCommandOption(
8208 MagickNoiseOptions,MagickFalse,noise_type),1.0,exception);
8209 if (noise_image != (Image *) NULL)
8211 *image=DestroyImage(*image);
8214 CatchException(exception);
8215 XSetCursorState(display,windows,MagickFalse);
8216 if (IfMagickTrue(windows->image.orphan) )
8218 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8219 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8222 case SharpenCommand:
8228 radius[MaxTextExtent] = "0.0x1.0";
8231 Query user for sharpen radius.
8233 (void) XDialogWidget(display,windows,"Sharpen",
8234 "Enter the sharpen radius and standard deviation:",radius);
8235 if (*radius == '\0')
8238 Sharpen image scanlines.
8240 XSetCursorState(display,windows,MagickTrue);
8241 XCheckRefreshWindows(display,windows);
8242 flags=ParseGeometry(radius,&geometry_info);
8243 sharp_image=SharpenImage(*image,geometry_info.rho,geometry_info.sigma,
8245 if (sharp_image != (Image *) NULL)
8247 *image=DestroyImage(*image);
8250 CatchException(exception);
8251 XSetCursorState(display,windows,MagickFalse);
8252 if (IfMagickTrue(windows->image.orphan) )
8254 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8255 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8264 radius[MaxTextExtent] = "0.0x1.0";
8267 Query user for blur radius.
8269 (void) XDialogWidget(display,windows,"Blur",
8270 "Enter the blur radius and standard deviation:",radius);
8271 if (*radius == '\0')
8276 XSetCursorState(display,windows,MagickTrue);
8277 XCheckRefreshWindows(display,windows);
8278 flags=ParseGeometry(radius,&geometry_info);
8279 blur_image=BlurImage(*image,geometry_info.rho,geometry_info.sigma,
8281 if (blur_image != (Image *) NULL)
8283 *image=DestroyImage(*image);
8286 CatchException(exception);
8287 XSetCursorState(display,windows,MagickFalse);
8288 if (IfMagickTrue(windows->image.orphan) )
8290 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8291 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8294 case ThresholdCommand:
8300 factor[MaxTextExtent] = "128";
8303 Query user for threshold value.
8305 (void) XDialogWidget(display,windows,"Threshold",
8306 "Enter threshold value:",factor);
8307 if (*factor == '\0')
8310 Gamma correct image.
8312 XSetCursorState(display,windows,MagickTrue);
8313 XCheckRefreshWindows(display,windows);
8314 threshold=StringToDoubleInterval(factor,(double) QuantumRange+1.0);
8315 (void) BilevelImage(*image,threshold,exception);
8316 XSetCursorState(display,windows,MagickFalse);
8317 if (IfMagickTrue(windows->image.orphan) )
8319 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8320 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8323 case EdgeDetectCommand:
8329 radius[MaxTextExtent] = "0";
8332 Query user for edge factor.
8334 (void) XDialogWidget(display,windows,"Detect Edges",
8335 "Enter the edge detect radius:",radius);
8336 if (*radius == '\0')
8339 Detect edge in image.
8341 XSetCursorState(display,windows,MagickTrue);
8342 XCheckRefreshWindows(display,windows);
8343 flags=ParseGeometry(radius,&geometry_info);
8344 edge_image=EdgeImage(*image,geometry_info.rho,exception);
8345 if (edge_image != (Image *) NULL)
8347 *image=DestroyImage(*image);
8350 CatchException(exception);
8351 XSetCursorState(display,windows,MagickFalse);
8352 if (IfMagickTrue(windows->image.orphan) )
8354 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8355 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8364 amount[MaxTextExtent] = "2";
8367 Query user for spread amount.
8369 (void) XDialogWidget(display,windows,"Spread",
8370 "Enter the displacement amount:",amount);
8371 if (*amount == '\0')
8374 Displace image pixels by a random amount.
8376 XSetCursorState(display,windows,MagickTrue);
8377 XCheckRefreshWindows(display,windows);
8378 flags=ParseGeometry(amount,&geometry_info);
8379 spread_image=EdgeImage(*image,geometry_info.rho,exception);
8380 if (spread_image != (Image *) NULL)
8382 *image=DestroyImage(*image);
8383 *image=spread_image;
8385 CatchException(exception);
8386 XSetCursorState(display,windows,MagickFalse);
8387 if (IfMagickTrue(windows->image.orphan) )
8389 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8390 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8402 geometry[MaxTextExtent] = "30x30";
8405 Query user for the shade geometry.
8407 status=XDialogWidget(display,windows,"Shade",
8408 "Enter the azimuth and elevation of the light source:",geometry);
8409 if (*geometry == '\0')
8414 XSetCursorState(display,windows,MagickTrue);
8415 XCheckRefreshWindows(display,windows);
8416 flags=ParseGeometry(geometry,&geometry_info);
8417 if ((flags & SigmaValue) == 0)
8418 geometry_info.sigma=1.0;
8419 shade_image=ShadeImage(*image,IsMagickTrue(status),
8420 geometry_info.rho,geometry_info.sigma,exception);
8421 if (shade_image != (Image *) NULL)
8423 *image=DestroyImage(*image);
8426 CatchException(exception);
8427 XSetCursorState(display,windows,MagickFalse);
8428 if (IfMagickTrue(windows->image.orphan) )
8430 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8431 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8437 bevel_width[MaxTextExtent] = "10";
8440 Query user for bevel width.
8442 (void) XDialogWidget(display,windows,"Raise","Bevel width:",bevel_width);
8443 if (*bevel_width == '\0')
8448 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image,
8450 XSetCursorState(display,windows,MagickTrue);
8451 XCheckRefreshWindows(display,windows);
8452 (void) ParsePageGeometry(*image,bevel_width,&page_geometry,
8454 (void) RaiseImage(*image,&page_geometry,MagickTrue,exception);
8455 XSetCursorState(display,windows,MagickFalse);
8456 if (IfMagickTrue(windows->image.orphan) )
8458 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8459 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8462 case SegmentCommand:
8465 threshold[MaxTextExtent] = "1.0x1.5";
8468 Query user for smoothing threshold.
8470 (void) XDialogWidget(display,windows,"Segment","Smooth threshold:",
8472 if (*threshold == '\0')
8477 XSetCursorState(display,windows,MagickTrue);
8478 XCheckRefreshWindows(display,windows);
8479 flags=ParseGeometry(threshold,&geometry_info);
8480 if ((flags & SigmaValue) == 0)
8481 geometry_info.sigma=1.0;
8482 (void) SegmentImage(*image,sRGBColorspace,MagickFalse,geometry_info.rho,
8483 geometry_info.sigma,exception);
8484 XSetCursorState(display,windows,MagickFalse);
8485 if (IfMagickTrue(windows->image.orphan) )
8487 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8488 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8491 case SepiaToneCommand:
8500 factor[MaxTextExtent] = "80%";
8503 Query user for sepia-tone factor.
8505 (void) XDialogWidget(display,windows,"Sepia Tone",
8506 "Enter the sepia tone factor (0 - 99.9%):",factor);
8507 if (*factor == '\0')
8510 Sepia tone image pixels.
8512 XSetCursorState(display,windows,MagickTrue);
8513 XCheckRefreshWindows(display,windows);
8514 threshold=StringToDoubleInterval(factor,(double) QuantumRange+1.0);
8515 sepia_image=SepiaToneImage(*image,threshold,exception);
8516 if (sepia_image != (Image *) NULL)
8518 *image=DestroyImage(*image);
8521 CatchException(exception);
8522 XSetCursorState(display,windows,MagickFalse);
8523 if (IfMagickTrue(windows->image.orphan) )
8525 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8526 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8529 case SolarizeCommand:
8535 factor[MaxTextExtent] = "60%";
8538 Query user for solarize factor.
8540 (void) XDialogWidget(display,windows,"Solarize",
8541 "Enter the solarize factor (0 - 99.9%):",factor);
8542 if (*factor == '\0')
8545 Solarize image pixels.
8547 XSetCursorState(display,windows,MagickTrue);
8548 XCheckRefreshWindows(display,windows);
8549 threshold=StringToDoubleInterval(factor,(double) QuantumRange+1.0);
8550 (void) SolarizeImage(*image,threshold,exception);
8551 XSetCursorState(display,windows,MagickFalse);
8552 if (IfMagickTrue(windows->image.orphan) )
8554 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8555 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8564 degrees[MaxTextExtent] = "60";
8567 Query user for swirl angle.
8569 (void) XDialogWidget(display,windows,"Swirl","Enter the swirl angle:",
8571 if (*degrees == '\0')
8574 Swirl image pixels about the center.
8576 XSetCursorState(display,windows,MagickTrue);
8577 XCheckRefreshWindows(display,windows);
8578 flags=ParseGeometry(degrees,&geometry_info);
8579 swirl_image=SwirlImage(*image,geometry_info.rho,(*image)->interpolate,
8581 if (swirl_image != (Image *) NULL)
8583 *image=DestroyImage(*image);
8586 CatchException(exception);
8587 XSetCursorState(display,windows,MagickFalse);
8588 if (IfMagickTrue(windows->image.orphan) )
8590 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8591 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8594 case ImplodeCommand:
8600 factor[MaxTextExtent] = "0.3";
8603 Query user for implode factor.
8605 (void) XDialogWidget(display,windows,"Implode",
8606 "Enter the implosion/explosion factor (-1.0 - 1.0):",factor);
8607 if (*factor == '\0')
8610 Implode image pixels about the center.
8612 XSetCursorState(display,windows,MagickTrue);
8613 XCheckRefreshWindows(display,windows);
8614 flags=ParseGeometry(factor,&geometry_info);
8615 implode_image=ImplodeImage(*image,geometry_info.rho,(*image)->interpolate,
8617 if (implode_image != (Image *) NULL)
8619 *image=DestroyImage(*image);
8620 *image=implode_image;
8622 CatchException(exception);
8623 XSetCursorState(display,windows,MagickFalse);
8624 if (IfMagickTrue(windows->image.orphan) )
8626 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8627 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8630 case VignetteCommand:
8636 geometry[MaxTextExtent] = "0x20";
8639 Query user for the vignette geometry.
8641 (void) XDialogWidget(display,windows,"Vignette",
8642 "Enter the radius, sigma, and x and y offsets:",geometry);
8643 if (*geometry == '\0')
8646 Soften the edges of the image in vignette style
8648 XSetCursorState(display,windows,MagickTrue);
8649 XCheckRefreshWindows(display,windows);
8650 flags=ParseGeometry(geometry,&geometry_info);
8651 if ((flags & SigmaValue) == 0)
8652 geometry_info.sigma=1.0;
8653 if ((flags & XiValue) == 0)
8654 geometry_info.xi=0.1*(*image)->columns;
8655 if ((flags & PsiValue) == 0)
8656 geometry_info.psi=0.1*(*image)->rows;
8657 vignette_image=VignetteImage(*image,geometry_info.rho,0.0,(ssize_t)
8658 ceil(geometry_info.xi-0.5),(ssize_t) ceil(geometry_info.psi-0.5),
8660 if (vignette_image != (Image *) NULL)
8662 *image=DestroyImage(*image);
8663 *image=vignette_image;
8665 CatchException(exception);
8666 XSetCursorState(display,windows,MagickFalse);
8667 if (IfMagickTrue(windows->image.orphan) )
8669 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8670 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8679 geometry[MaxTextExtent] = "25x150";
8682 Query user for the wave geometry.
8684 (void) XDialogWidget(display,windows,"Wave",
8685 "Enter the amplitude and length of the wave:",geometry);
8686 if (*geometry == '\0')
8689 Alter an image along a sine wave.
8691 XSetCursorState(display,windows,MagickTrue);
8692 XCheckRefreshWindows(display,windows);
8693 flags=ParseGeometry(geometry,&geometry_info);
8694 if ((flags & SigmaValue) == 0)
8695 geometry_info.sigma=1.0;
8696 wave_image=WaveImage(*image,geometry_info.rho,geometry_info.sigma,
8697 (*image)->interpolate,exception);
8698 if (wave_image != (Image *) NULL)
8700 *image=DestroyImage(*image);
8703 CatchException(exception);
8704 XSetCursorState(display,windows,MagickFalse);
8705 if (IfMagickTrue(windows->image.orphan) )
8707 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8708 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8711 case OilPaintCommand:
8717 radius[MaxTextExtent] = "0";
8720 Query user for circular neighborhood radius.
8722 (void) XDialogWidget(display,windows,"Oil Paint",
8723 "Enter the mask radius:",radius);
8724 if (*radius == '\0')
8727 OilPaint image scanlines.
8729 XSetCursorState(display,windows,MagickTrue);
8730 XCheckRefreshWindows(display,windows);
8731 flags=ParseGeometry(radius,&geometry_info);
8732 paint_image=OilPaintImage(*image,geometry_info.rho,geometry_info.sigma,
8734 if (paint_image != (Image *) NULL)
8736 *image=DestroyImage(*image);
8739 CatchException(exception);
8740 XSetCursorState(display,windows,MagickFalse);
8741 if (IfMagickTrue(windows->image.orphan) )
8743 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8744 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8747 case CharcoalDrawCommand:
8753 radius[MaxTextExtent] = "0x1";
8756 Query user for charcoal radius.
8758 (void) XDialogWidget(display,windows,"Charcoal Draw",
8759 "Enter the charcoal radius and sigma:",radius);
8760 if (*radius == '\0')
8765 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image,
8767 XSetCursorState(display,windows,MagickTrue);
8768 XCheckRefreshWindows(display,windows);
8769 flags=ParseGeometry(radius,&geometry_info);
8770 if ((flags & SigmaValue) == 0)
8771 geometry_info.sigma=geometry_info.rho;
8772 charcoal_image=CharcoalImage(*image,geometry_info.rho,geometry_info.sigma,
8774 if (charcoal_image != (Image *) NULL)
8776 *image=DestroyImage(*image);
8777 *image=charcoal_image;
8779 CatchException(exception);
8780 XSetCursorState(display,windows,MagickFalse);
8781 if (IfMagickTrue(windows->image.orphan) )
8783 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8784 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8787 case AnnotateCommand:
8790 Annotate the image with text.
8792 status=XAnnotateEditImage(display,resource_info,windows,*image,exception);
8793 if (IfMagickFalse(status) )
8795 XNoticeWidget(display,windows,"Unable to annotate X image",
8796 (*image)->filename);
8806 status=XDrawEditImage(display,resource_info,windows,image,exception);
8807 if (IfMagickFalse(status) )
8809 XNoticeWidget(display,windows,"Unable to draw on the X image",
8810 (*image)->filename);
8820 status=XColorEditImage(display,resource_info,windows,image,exception);
8821 if (IfMagickFalse(status) )
8823 XNoticeWidget(display,windows,"Unable to pixel edit X image",
8824 (*image)->filename);
8834 status=XMatteEditImage(display,resource_info,windows,image,exception);
8835 if (IfMagickFalse(status) )
8837 XNoticeWidget(display,windows,"Unable to matte edit X image",
8838 (*image)->filename);
8843 case CompositeCommand:
8848 status=XCompositeImage(display,resource_info,windows,*image,
8850 if (IfMagickFalse(status) )
8852 XNoticeWidget(display,windows,"Unable to composite X image",
8853 (*image)->filename);
8858 case AddBorderCommand:
8864 geometry[MaxTextExtent] = "6x6";
8867 Query user for border color and geometry.
8869 XColorBrowserWidget(display,windows,"Select",color);
8872 (void) XDialogWidget(display,windows,"Add Border",
8873 "Enter border geometry:",geometry);
8874 if (*geometry == '\0')
8877 Add a border to the image.
8879 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image,
8881 XSetCursorState(display,windows,MagickTrue);
8882 XCheckRefreshWindows(display,windows);
8883 (void) QueryColorCompliance(color,AllCompliance,&(*image)->border_color,
8885 (void) ParsePageGeometry(*image,geometry,&page_geometry,
8887 border_image=BorderImage(*image,&page_geometry,(*image)->compose,
8889 if (border_image != (Image *) NULL)
8891 *image=DestroyImage(*image);
8892 *image=border_image;
8894 CatchException(exception);
8895 XSetCursorState(display,windows,MagickFalse);
8896 if (IfMagickTrue(windows->image.orphan) )
8898 windows->image.window_changes.width=(int) (*image)->columns;
8899 windows->image.window_changes.height=(int) (*image)->rows;
8900 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8901 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8904 case AddFrameCommand:
8913 geometry[MaxTextExtent] = "6x6";
8916 Query user for frame color and geometry.
8918 XColorBrowserWidget(display,windows,"Select",color);
8921 (void) XDialogWidget(display,windows,"Add Frame","Enter frame geometry:",
8923 if (*geometry == '\0')
8926 Surround image with an ornamental border.
8928 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image,
8930 XSetCursorState(display,windows,MagickTrue);
8931 XCheckRefreshWindows(display,windows);
8932 (void) QueryColorCompliance(color,AllCompliance,&(*image)->matte_color,
8934 (void) ParsePageGeometry(*image,geometry,&page_geometry,
8936 frame_info.width=page_geometry.width;
8937 frame_info.height=page_geometry.height;
8938 frame_info.outer_bevel=page_geometry.x;
8939 frame_info.inner_bevel=page_geometry.y;
8940 frame_info.x=(ssize_t) frame_info.width;
8941 frame_info.y=(ssize_t) frame_info.height;
8942 frame_info.width=(*image)->columns+2*frame_info.width;
8943 frame_info.height=(*image)->rows+2*frame_info.height;
8944 frame_image=FrameImage(*image,&frame_info,(*image)->compose,exception);
8945 if (frame_image != (Image *) NULL)
8947 *image=DestroyImage(*image);
8950 CatchException(exception);
8951 XSetCursorState(display,windows,MagickFalse);
8952 if (IfMagickTrue(windows->image.orphan) )
8954 windows->image.window_changes.width=(int) (*image)->columns;
8955 windows->image.window_changes.height=(int) (*image)->rows;
8956 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8957 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8960 case CommentCommand:
8974 unique_file=AcquireUniqueFileResource(image_info->filename);
8975 if (unique_file == -1)
8976 XNoticeWidget(display,windows,"Unable to edit image comment",
8977 image_info->filename);
8978 value=GetImageProperty(*image,"comment",exception);
8979 if (value == (char *) NULL)
8980 unique_file=close(unique_file)-1;
8986 file=fdopen(unique_file,"w");
8987 if (file == (FILE *) NULL)
8989 XNoticeWidget(display,windows,"Unable to edit image comment",
8990 image_info->filename);
8993 for (p=value; *p != '\0'; p++)
8994 (void) fputc((int) *p,file);
8995 (void) fputc('\n',file);
8996 (void) fclose(file);
8998 XSetCursorState(display,windows,MagickTrue);
8999 XCheckRefreshWindows(display,windows);
9000 status=InvokeDelegate(image_info,*image,"edit",(char *) NULL,
9002 if (IfMagickFalse(status) )
9003 XNoticeWidget(display,windows,"Unable to edit image comment",
9010 comment=FileToString(image_info->filename,~0UL,exception);
9011 if (comment != (char *) NULL)
9013 (void) SetImageProperty(*image,"comment",comment,exception);
9014 (*image)->taint=MagickTrue;
9017 (void) RelinquishUniqueFileResource(image_info->filename);
9018 XSetCursorState(display,windows,MagickFalse);
9026 XSetCursorState(display,windows,MagickTrue);
9027 XCheckRefreshWindows(display,windows);
9028 (void) AcquireUniqueFilename(filename);
9029 (void) FormatLocaleString((*image)->filename,MaxTextExtent,"launch:%s",
9031 status=WriteImage(image_info,*image,exception);
9032 if (IfMagickFalse(status) )
9033 XNoticeWidget(display,windows,"Unable to launch image editor",
9037 nexus=ReadImage(resource_info->image_info,exception);
9038 CatchException(exception);
9039 XClientMessage(display,windows->image.id,windows->im_protocols,
9040 windows->im_next_image,CurrentTime);
9042 (void) RelinquishUniqueFileResource(filename);
9043 XSetCursorState(display,windows,MagickFalse);
9046 case RegionofInterestCommand:
9049 Apply an image processing technique to a region of interest.
9051 (void) XROIImage(display,resource_info,windows,image,exception);
9061 if (IfMagickTrue(windows->magnify.mapped) )
9062 (void) XRaiseWindow(display,windows->magnify.id);
9068 XSetCursorState(display,windows,MagickTrue);
9069 (void) XMapRaised(display,windows->magnify.id);
9070 XSetCursorState(display,windows,MagickFalse);
9074 case ShowPreviewCommand:
9083 preview_type[MaxTextExtent] = "Gamma";
9086 Select preview type from menu.
9088 previews=GetCommandOptions(MagickPreviewOptions);
9089 if (previews == (char **) NULL)
9091 XListBrowserWidget(display,windows,&windows->widget,
9092 (const char **) previews,"Preview",
9093 "Select an enhancement, effect, or F/X:",preview_type);
9094 previews=DestroyStringList(previews);
9095 if (*preview_type == '\0')
9100 XSetCursorState(display,windows,MagickTrue);
9101 XCheckRefreshWindows(display,windows);
9102 image_info->preview_type=(PreviewType)
9103 ParseCommandOption(MagickPreviewOptions,MagickFalse,preview_type);
9104 image_info->group=(ssize_t) windows->image.id;
9105 (void) DeleteImageProperty(*image,"label");
9106 (void) SetImageProperty(*image,"label","Preview",exception);
9107 (void) AcquireUniqueFilename(filename);
9108 (void) FormatLocaleString((*image)->filename,MaxTextExtent,"preview:%s",
9110 status=WriteImage(image_info,*image,exception);
9111 (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
9112 preview_image=ReadImage(image_info,exception);
9113 (void) RelinquishUniqueFileResource(filename);
9114 if (preview_image == (Image *) NULL)
9116 (void) FormatLocaleString(preview_image->filename,MaxTextExtent,"show:%s",
9118 status=WriteImage(image_info,preview_image,exception);
9119 preview_image=DestroyImage(preview_image);
9120 if (IfMagickFalse(status) )
9121 XNoticeWidget(display,windows,"Unable to show image preview",
9122 (*image)->filename);
9123 XDelay(display,1500);
9124 XSetCursorState(display,windows,MagickFalse);
9127 case ShowHistogramCommand:
9133 Show image histogram.
9135 XSetCursorState(display,windows,MagickTrue);
9136 XCheckRefreshWindows(display,windows);
9137 image_info->group=(ssize_t) windows->image.id;
9138 (void) DeleteImageProperty(*image,"label");
9139 (void) SetImageProperty(*image,"label","Histogram",exception);
9140 (void) AcquireUniqueFilename(filename);
9141 (void) FormatLocaleString((*image)->filename,MaxTextExtent,"histogram:%s",
9143 status=WriteImage(image_info,*image,exception);
9144 (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
9145 histogram_image=ReadImage(image_info,exception);
9146 (void) RelinquishUniqueFileResource(filename);
9147 if (histogram_image == (Image *) NULL)
9149 (void) FormatLocaleString(histogram_image->filename,MaxTextExtent,
9150 "show:%s",filename);
9151 status=WriteImage(image_info,histogram_image,exception);
9152 histogram_image=DestroyImage(histogram_image);
9153 if (IfMagickFalse(status) )
9154 XNoticeWidget(display,windows,"Unable to show histogram",
9155 (*image)->filename);
9156 XDelay(display,1500);
9157 XSetCursorState(display,windows,MagickFalse);
9160 case ShowMatteCommand:
9165 if ((*image)->alpha_trait != BlendPixelTrait)
9167 XNoticeWidget(display,windows,
9168 "Image does not have any matte information",(*image)->filename);
9174 XSetCursorState(display,windows,MagickTrue);
9175 XCheckRefreshWindows(display,windows);
9176 image_info->group=(ssize_t) windows->image.id;
9177 (void) DeleteImageProperty(*image,"label");
9178 (void) SetImageProperty(*image,"label","Matte",exception);
9179 (void) AcquireUniqueFilename(filename);
9180 (void) FormatLocaleString((*image)->filename,MaxTextExtent,"matte:%s",
9182 status=WriteImage(image_info,*image,exception);
9183 (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
9184 matte_image=ReadImage(image_info,exception);
9185 (void) RelinquishUniqueFileResource(filename);
9186 if (matte_image == (Image *) NULL)
9188 (void) FormatLocaleString(matte_image->filename,MaxTextExtent,"show:%s",
9190 status=WriteImage(image_info,matte_image,exception);
9191 matte_image=DestroyImage(matte_image);
9192 if (IfMagickFalse(status) )
9193 XNoticeWidget(display,windows,"Unable to show matte",
9194 (*image)->filename);
9195 XDelay(display,1500);
9196 XSetCursorState(display,windows,MagickFalse);
9199 case BackgroundCommand:
9204 status=XBackgroundImage(display,resource_info,windows,image,exception);
9205 if (IfMagickFalse(status) )
9207 nexus=CloneImage(*image,0,0,MagickTrue,exception);
9208 if (nexus != (Image *) NULL)
9209 XClientMessage(display,windows->image.id,windows->im_protocols,
9210 windows->im_next_image,CurrentTime);
9213 case SlideShowCommand:
9216 delay[MaxTextExtent] = "5";
9219 Display next image after pausing.
9221 (void) XDialogWidget(display,windows,"Slide Show",
9222 "Pause how many 1/100ths of a second between images:",delay);
9225 resource_info->delay=StringToUnsignedLong(delay);
9226 XClientMessage(display,windows->image.id,windows->im_protocols,
9227 windows->im_next_image,CurrentTime);
9230 case PreferencesCommand:
9233 Set user preferences.
9235 status=XPreferencesWidget(display,resource_info,windows);
9236 if (IfMagickFalse(status) )
9238 nexus=CloneImage(*image,0,0,MagickTrue,exception);
9239 if (nexus != (Image *) NULL)
9240 XClientMessage(display,windows->image.id,windows->im_protocols,
9241 windows->im_next_image,CurrentTime);
9247 User requested help.
9249 XTextViewWidget(display,resource_info,windows,MagickFalse,
9250 "Help Viewer - Display",DisplayHelp);
9253 case BrowseDocumentationCommand:
9263 Browse the ImageMagick documentation.
9265 root_window=XRootWindow(display,XDefaultScreen(display));
9266 mozilla_atom=XInternAtom(display,"_MOZILLA_VERSION",MagickFalse);
9267 mozilla_window=XWindowByProperty(display,root_window,mozilla_atom);
9268 if (mozilla_window != (Window) NULL)
9271 command[MaxTextExtent],
9275 Display documentation using Netscape remote control.
9277 url=GetMagickHomeURL();
9278 (void) FormatLocaleString(command,MaxTextExtent,
9279 "openurl(%s,new-tab)",url);
9280 url=DestroyString(url);
9281 mozilla_atom=XInternAtom(display,"_MOZILLA_COMMAND",MagickFalse);
9282 (void) XChangeProperty(display,mozilla_window,mozilla_atom,XA_STRING,
9283 8,PropModeReplace,(unsigned char *) command,(int) strlen(command));
9284 XSetCursorState(display,windows,MagickFalse);
9287 XSetCursorState(display,windows,MagickTrue);
9288 XCheckRefreshWindows(display,windows);
9289 status=InvokeDelegate(image_info,*image,"browse",(char *) NULL,
9291 if (IfMagickFalse(status) )
9292 XNoticeWidget(display,windows,"Unable to browse documentation",
9294 XDelay(display,1500);
9295 XSetCursorState(display,windows,MagickFalse);
9298 case VersionCommand:
9300 XNoticeWidget(display,windows,GetMagickVersion((size_t *) NULL),
9301 GetMagickCopyright());
9304 case SaveToUndoBufferCommand:
9308 (void) XBell(display,0);
9312 image_info=DestroyImageInfo(image_info);
9317 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9321 + X M a g n i f y I m a g e %
9325 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9327 % XMagnifyImage() magnifies portions of the image as indicated by the pointer.
9328 % The magnified portion is displayed in a separate window.
9330 % The format of the XMagnifyImage method is:
9332 % void XMagnifyImage(Display *display,XWindows *windows,XEvent *event,
9333 % ExceptionInfo *exception)
9335 % A description of each parameter follows:
9337 % o display: Specifies a connection to an X server; returned from
9340 % o windows: Specifies a pointer to a XWindows structure.
9342 % o event: Specifies a pointer to a XEvent structure. If it is NULL,
9343 % the entire image is refreshed.
9345 % o exception: return any errors or warnings in this structure.
9348 static void XMagnifyImage(Display *display,XWindows *windows,XEvent *event,
9349 ExceptionInfo *exception)
9352 text[MaxTextExtent];
9362 Update magnified image until the mouse button is released.
9364 (void) XCheckDefineCursor(display,windows->image.id,windows->magnify.cursor);
9368 windows->magnify.x=(int) windows->image.x+x;
9369 windows->magnify.y=(int) windows->image.y+y;
9373 Map and unmap Info widget as text cursor crosses its boundaries.
9375 if (IfMagickTrue(windows->info.mapped) )
9377 if ((x < (int) (windows->info.x+windows->info.width)) &&
9378 (y < (int) (windows->info.y+windows->info.height)))
9379 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
9382 if ((x > (int) (windows->info.x+windows->info.width)) ||
9383 (y > (int) (windows->info.y+windows->info.height)))
9384 (void) XMapWindow(display,windows->info.id);
9385 if (IfMagickTrue(windows->info.mapped) )
9388 Display pointer position.
9390 (void) FormatLocaleString(text,MaxTextExtent," %+d%+d ",
9391 windows->magnify.x,windows->magnify.y);
9392 XInfoWidget(display,windows,text);
9395 Wait for next event.
9397 XScreenEvent(display,windows,event,exception);
9398 switch (event->type)
9405 User has finished magnifying image.
9424 Check boundary conditions.
9429 if (x >= (int) windows->image.width)
9430 x=(int) windows->image.width-1;
9434 if (y >= (int) windows->image.height)
9435 y=(int) windows->image.height-1;
9436 } while ((state & ExitState) == 0);
9438 Display magnified image.
9440 XSetCursorState(display,windows,MagickFalse);
9444 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9448 + X M a g n i f y W i n d o w C o m m a n d %
9452 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9454 % XMagnifyWindowCommand() moves the image within an Magnify window by one
9455 % pixel as specified by the key symbol.
9457 % The format of the XMagnifyWindowCommand method is:
9459 % void XMagnifyWindowCommand(Display *display,XWindows *windows,
9460 % const MagickStatusType state,const KeySym key_symbol,
9461 % ExceptionInfo *exception)
9463 % A description of each parameter follows:
9465 % o display: Specifies a connection to an X server; returned from
9468 % o windows: Specifies a pointer to a XWindows structure.
9470 % o state: key mask.
9472 % o key_symbol: Specifies a KeySym which indicates which side of the image
9475 % o exception: return any errors or warnings in this structure.
9478 static void XMagnifyWindowCommand(Display *display,XWindows *windows,
9479 const MagickStatusType state,const KeySym key_symbol,ExceptionInfo *exception)
9485 User specified a magnify factor or position.
9488 if ((state & Mod1Mask) != 0)
9490 switch ((int) key_symbol)
9494 (void) XWithdrawWindow(display,windows->magnify.id,
9495 windows->magnify.screen);
9501 windows->magnify.x=(int) windows->image.width/2;
9502 windows->magnify.y=(int) windows->image.height/2;
9508 if (windows->magnify.x > 0)
9509 windows->magnify.x-=quantum;
9515 if (windows->magnify.y > 0)
9516 windows->magnify.y-=quantum;
9522 if (windows->magnify.x < (int) (windows->image.ximage->width-1))
9523 windows->magnify.x+=quantum;
9529 if (windows->magnify.y < (int) (windows->image.ximage->height-1))
9530 windows->magnify.y+=quantum;
9544 windows->magnify.data=(key_symbol-XK_0);
9558 windows->magnify.data=(key_symbol-XK_KP_0);
9564 XMakeMagnifyImage(display,windows,exception);
9568 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9572 + X M a k e P a n I m a g e %
9576 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9578 % XMakePanImage() creates a thumbnail of the image and displays it in the Pan
9581 % The format of the XMakePanImage method is:
9583 % void XMakePanImage(Display *display,XResourceInfo *resource_info,
9584 % XWindows *windows,Image *image,ExceptionInfo *exception)
9586 % A description of each parameter follows:
9588 % o display: Specifies a connection to an X server; returned from
9591 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
9593 % o windows: Specifies a pointer to a XWindows structure.
9595 % o image: the image.
9597 % o exception: return any errors or warnings in this structure.
9600 static void XMakePanImage(Display *display,XResourceInfo *resource_info,
9601 XWindows *windows,Image *image,ExceptionInfo *exception)
9607 Create and display image for panning icon.
9609 XSetCursorState(display,windows,MagickTrue);
9610 XCheckRefreshWindows(display,windows);
9611 windows->pan.x=(int) windows->image.x;
9612 windows->pan.y=(int) windows->image.y;
9613 status=XMakeImage(display,resource_info,&windows->pan,image,
9614 windows->pan.width,windows->pan.height,exception);
9615 if (IfMagickFalse(status) )
9616 ThrowXWindowException(ResourceLimitError,
9617 "MemoryAllocationFailed",image->filename);
9618 (void) XSetWindowBackgroundPixmap(display,windows->pan.id,
9619 windows->pan.pixmap);
9620 (void) XClearWindow(display,windows->pan.id);
9621 XDrawPanRectangle(display,windows);
9622 XSetCursorState(display,windows,MagickFalse);
9626 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9630 + X M a t t a E d i t I m a g e %
9634 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9636 % XMatteEditImage() allows the user to interactively change the Matte channel
9637 % of an image. If the image is PseudoClass it is promoted to DirectClass
9638 % before the matte information is stored.
9640 % The format of the XMatteEditImage method is:
9642 % MagickBooleanType XMatteEditImage(Display *display,
9643 % XResourceInfo *resource_info,XWindows *windows,Image **image,
9644 % ExceptionInfo *exception)
9646 % A description of each parameter follows:
9648 % o display: Specifies a connection to an X server; returned from
9651 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
9653 % o windows: Specifies a pointer to a XWindows structure.
9655 % o image: the image; returned from ReadImage.
9657 % o exception: return any errors or warnings in this structure.
9660 static MagickBooleanType XMatteEditImage(Display *display,
9661 XResourceInfo *resource_info,XWindows *windows,Image **image,
9662 ExceptionInfo *exception)
9665 matte[MaxTextExtent] = "0";
9680 static const ModeType
9681 MatteEditCommands[] =
9684 MatteEditBorderCommand,
9685 MatteEditFuzzCommand,
9686 MatteEditValueCommand,
9687 MatteEditUndoCommand,
9688 MatteEditHelpCommand,
9689 MatteEditDismissCommand
9693 method = PointMethod;
9696 border_color = { 0, 0, 0, 0, 0, 0 };
9699 command[MaxTextExtent],
9700 text[MaxTextExtent];
9732 (void) CloneString(&windows->command.name,"Matte Edit");
9733 windows->command.data=4;
9734 (void) XCommandWidget(display,windows,MatteEditMenu,(XEvent *) NULL);
9735 (void) XMapRaised(display,windows->command.id);
9736 XClientMessage(display,windows->image.id,windows->im_protocols,
9737 windows->im_update_widget,CurrentTime);
9741 cursor=XMakeCursor(display,windows->image.id,windows->map_info->colormap,
9742 resource_info->background_color,resource_info->foreground_color);
9743 (void) XCheckDefineCursor(display,windows->image.id,cursor);
9745 Track pointer until button 1 is pressed.
9747 XQueryPosition(display,windows->image.id,&x,&y);
9748 (void) XSelectInput(display,windows->image.id,
9749 windows->image.attributes.event_mask | PointerMotionMask);
9753 if (IfMagickTrue(windows->info.mapped) )
9756 Display pointer position.
9758 (void) FormatLocaleString(text,MaxTextExtent," %+d%+d ",
9759 x+windows->image.x,y+windows->image.y);
9760 XInfoWidget(display,windows,text);
9763 Wait for next event.
9765 XScreenEvent(display,windows,&event,exception);
9766 if (event.xany.window == windows->command.id)
9769 Select a command from the Command widget.
9771 id=XCommandWidget(display,windows,MatteEditMenu,&event);
9774 (void) XCheckDefineCursor(display,windows->image.id,cursor);
9777 switch (MatteEditCommands[id])
9779 case MatteEditMethod:
9785 Select a method from the pop-up menu.
9787 methods=GetCommandOptions(MagickMethodOptions);
9788 if (methods == (char **) NULL)
9790 entry=XMenuWidget(display,windows,MatteEditMenu[id],
9791 (const char **) methods,command);
9793 method=(PaintMethod) ParseCommandOption(MagickMethodOptions,
9794 MagickFalse,methods[entry]);
9795 methods=DestroyStringList(methods);
9798 case MatteEditBorderCommand:
9801 *ColorMenu[MaxNumberPens];
9807 Initialize menu selections.
9809 for (i=0; i < (int) (MaxNumberPens-2); i++)
9810 ColorMenu[i]=resource_info->pen_colors[i];
9811 ColorMenu[MaxNumberPens-2]="Browser...";
9812 ColorMenu[MaxNumberPens-1]=(const char *) NULL;
9814 Select a pen color from the pop-up menu.
9816 pen_number=XMenuWidget(display,windows,MatteEditMenu[id],
9817 (const char **) ColorMenu,command);
9820 if (pen_number == (MaxNumberPens-2))
9823 color_name[MaxTextExtent] = "gray";
9826 Select a pen color from a dialog.
9828 resource_info->pen_colors[pen_number]=color_name;
9829 XColorBrowserWidget(display,windows,"Select",color_name);
9830 if (*color_name == '\0')
9836 (void) XParseColor(display,windows->map_info->colormap,
9837 resource_info->pen_colors[pen_number],&border_color);
9840 case MatteEditFuzzCommand:
9843 fuzz[MaxTextExtent];
9858 Select a command from the pop-up menu.
9860 entry=XMenuWidget(display,windows,MatteEditMenu[id],FuzzMenu,
9866 (*image)->fuzz=StringToDoubleInterval(FuzzMenu[entry],(double)
9870 (void) CopyMagickString(fuzz,"20%",MaxTextExtent);
9871 (void) XDialogWidget(display,windows,"Ok",
9872 "Enter fuzz factor (0.0 - 99.9%):",fuzz);
9875 (void) ConcatenateMagickString(fuzz,"%",MaxTextExtent);
9876 (*image)->fuzz=StringToDoubleInterval(fuzz,(double) QuantumRange+
9880 case MatteEditValueCommand:
9883 message[MaxTextExtent];
9895 Select a command from the pop-up menu.
9897 entry=XMenuWidget(display,windows,MatteEditMenu[id],MatteMenu,
9903 (void) FormatLocaleString(matte,MaxTextExtent,QuantumFormat,
9905 if (LocaleCompare(MatteMenu[entry],"Transparent") == 0)
9906 (void) FormatLocaleString(matte,MaxTextExtent,QuantumFormat,
9907 (Quantum) TransparentAlpha);
9910 (void) FormatLocaleString(message,MaxTextExtent,
9911 "Enter matte value (0 - " QuantumFormat "):",(Quantum)
9913 (void) XDialogWidget(display,windows,"Matte",message,matte);
9918 case MatteEditUndoCommand:
9920 (void) XMagickCommand(display,resource_info,windows,UndoCommand,
9924 case MatteEditHelpCommand:
9926 XTextViewWidget(display,resource_info,windows,MagickFalse,
9927 "Help Viewer - Matte Edit",ImageMatteEditHelp);
9930 case MatteEditDismissCommand:
9942 (void) XCheckDefineCursor(display,windows->image.id,cursor);
9949 if (event.xbutton.button != Button1)
9951 if ((event.xbutton.window != windows->image.id) &&
9952 (event.xbutton.window != windows->magnify.id))
9959 (void) XMagickCommand(display,resource_info,windows,
9960 SaveToUndoBufferCommand,image,exception);
9961 state|=UpdateConfigurationState;
9966 if (event.xbutton.button != Button1)
9968 if ((event.xbutton.window != windows->image.id) &&
9969 (event.xbutton.window != windows->magnify.id))
9972 Update colormap information.
9976 XConfigureImageColormap(display,resource_info,windows,*image,exception);
9977 (void) XConfigureImage(display,resource_info,windows,*image,exception);
9978 XInfoWidget(display,windows,text);
9979 (void) XCheckDefineCursor(display,windows->image.id,cursor);
9980 state&=(~UpdateConfigurationState);
9988 command[MaxTextExtent];
9993 if (event.xkey.window == windows->magnify.id)
9998 window=windows->magnify.id;
9999 while (XCheckWindowEvent(display,window,KeyPressMask,&event)) ;
10001 if (event.xkey.window != windows->image.id)
10004 Respond to a user key press.
10006 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
10007 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
10008 switch ((int) key_symbol)
10022 XTextViewWidget(display,resource_info,windows,MagickFalse,
10023 "Help Viewer - Matte Edit",ImageMatteEditHelp);
10028 (void) XBell(display,0);
10037 Map and unmap Info widget as cursor crosses its boundaries.
10041 if (IfMagickTrue(windows->info.mapped) )
10043 if ((x < (int) (windows->info.x+windows->info.width)) &&
10044 (y < (int) (windows->info.y+windows->info.height)))
10045 (void) XWithdrawWindow(display,windows->info.id,
10046 windows->info.screen);
10049 if ((x > (int) (windows->info.x+windows->info.width)) ||
10050 (y > (int) (windows->info.y+windows->info.height)))
10051 (void) XMapWindow(display,windows->info.id);
10057 if (event.xany.window == windows->magnify.id)
10059 x=windows->magnify.x-windows->image.x;
10060 y=windows->magnify.y-windows->image.y;
10064 if ((state & UpdateConfigurationState) != 0)
10074 Matte edit is relative to image configuration.
10076 (void) XClearArea(display,windows->image.id,x_offset,y_offset,1,1,
10078 XPutPixel(windows->image.ximage,x_offset,y_offset,
10079 windows->pixel_info->background_color.pixel);
10080 width=(unsigned int) (*image)->columns;
10081 height=(unsigned int) (*image)->rows;
10084 if (windows->image.crop_geometry != (char *) NULL)
10085 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,
10087 x_offset=(int) (width*(windows->image.x+x_offset)/
10088 windows->image.ximage->width+x);
10089 y_offset=(int) (height*(windows->image.y+y_offset)/
10090 windows->image.ximage->height+y);
10091 if ((x_offset < 0) || (y_offset < 0))
10093 if ((x_offset >= (int) (*image)->columns) ||
10094 (y_offset >= (int) (*image)->rows))
10096 if (IfMagickFalse(SetImageStorageClass(*image,DirectClass,exception)) )
10097 return(MagickFalse);
10098 if ((*image)->alpha_trait != BlendPixelTrait)
10099 (void) SetImageAlphaChannel(*image,OpaqueAlphaChannel,exception);
10100 image_view=AcquireAuthenticCacheView(*image,exception);
10107 Update matte information using point algorithm.
10109 q=GetCacheViewAuthenticPixels(image_view,(ssize_t) x_offset,
10110 (ssize_t) y_offset,1,1,exception);
10111 if (q == (Quantum *) NULL)
10113 SetPixelAlpha(*image,(Quantum) StringToLong(matte),q);
10114 (void) SyncCacheViewAuthenticPixels(image_view,exception);
10117 case ReplaceMethod:
10124 Update matte information using replace algorithm.
10126 (void) GetOneCacheViewVirtualPixelInfo(image_view,(ssize_t)
10127 x_offset,(ssize_t) y_offset,&target,exception);
10128 for (y=0; y < (int) (*image)->rows; y++)
10130 q=GetCacheViewAuthenticPixels(image_view,0,(ssize_t) y,
10131 (*image)->columns,1,exception);
10132 if (q == (Quantum *) NULL)
10134 for (x=0; x < (int) (*image)->columns; x++)
10136 GetPixelInfoPixel(*image,q,&pixel);
10137 if (IsFuzzyEquivalencePixelInfo(&pixel,&target))
10138 SetPixelAlpha(*image,(Quantum) StringToLong(matte),q);
10139 q+=GetPixelChannels(*image);
10141 if (IfMagickFalse(SyncCacheViewAuthenticPixels(image_view,exception)) )
10146 case FloodfillMethod:
10147 case FillToBorderMethod:
10159 Update matte information using floodfill algorithm.
10161 (void) GetOneVirtualPixelInfo(*image,
10162 GetPixelCacheVirtualMethod(*image),(ssize_t) x_offset,(ssize_t)
10163 y_offset,&target,exception);
10164 if (method == FillToBorderMethod)
10166 target.red=(double) ScaleShortToQuantum(
10168 target.green=(double) ScaleShortToQuantum(
10169 border_color.green);
10170 target.blue=(double) ScaleShortToQuantum(
10171 border_color.blue);
10173 draw_info=CloneDrawInfo(resource_info->image_info,
10174 (DrawInfo *) NULL);
10175 draw_info->fill.alpha=(double) ClampToQuantum(
10176 StringToDouble(matte,(char **) NULL));
10177 channel_mask=SetImageChannelMask(*image,AlphaChannel);
10178 (void) FloodfillPaintImage(*image,draw_info,&target,(ssize_t)
10179 x_offset,(ssize_t) y_offset,
10180 IsMagickFalse(method == FloodfillMethod),exception);
10181 (void) SetPixelChannelMask(*image,channel_mask);
10182 draw_info=DestroyDrawInfo(draw_info);
10188 Update matte information using reset algorithm.
10190 if (IfMagickFalse(SetImageStorageClass(*image,DirectClass,exception)) )
10191 return(MagickFalse);
10192 for (y=0; y < (int) (*image)->rows; y++)
10194 q=QueueCacheViewAuthenticPixels(image_view,0,(ssize_t) y,
10195 (*image)->columns,1,exception);
10196 if (q == (Quantum *) NULL)
10198 for (x=0; x < (int) (*image)->columns; x++)
10200 SetPixelAlpha(*image,(Quantum) StringToLong(matte),q);
10201 q+=GetPixelChannels(*image);
10203 if (IfMagickFalse(SyncCacheViewAuthenticPixels(image_view,exception)) )
10206 if (StringToLong(matte) == (long) OpaqueAlpha)
10207 (*image)->alpha_trait=UndefinedPixelTrait;
10211 image_view=DestroyCacheView(image_view);
10212 state&=(~UpdateConfigurationState);
10214 } while ((state & ExitState) == 0);
10215 (void) XSelectInput(display,windows->image.id,
10216 windows->image.attributes.event_mask);
10217 XSetCursorState(display,windows,MagickFalse);
10218 (void) XFreeCursor(display,cursor);
10219 return(MagickTrue);
10223 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10227 + X O p e n I m a g e %
10231 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10233 % XOpenImage() loads an image from a file.
10235 % The format of the XOpenImage method is:
10237 % Image *XOpenImage(Display *display,XResourceInfo *resource_info,
10238 % XWindows *windows,const unsigned int command)
10240 % A description of each parameter follows:
10242 % o display: Specifies a connection to an X server; returned from
10245 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
10247 % o windows: Specifies a pointer to a XWindows structure.
10249 % o command: A value other than zero indicates that the file is selected
10250 % from the command line argument list.
10253 static Image *XOpenImage(Display *display,XResourceInfo *resource_info,
10254 XWindows *windows,const MagickBooleanType command)
10269 filename[MaxTextExtent] = "\0";
10272 Request file name from user.
10274 if (IfMagickFalse(command) )
10275 XFileBrowserWidget(display,windows,"Open",filename);
10291 Select next image from the command line.
10293 status=XGetCommand(display,windows->image.id,&files,&count);
10296 ThrowXWindowException(XServerError,"UnableToGetProperty","...");
10297 return((Image *) NULL);
10299 filelist=(char **) AcquireQuantumMemory((size_t) count,sizeof(*filelist));
10300 if (filelist == (char **) NULL)
10302 ThrowXWindowException(ResourceLimitError,
10303 "MemoryAllocationFailed","...");
10304 (void) XFreeStringList(files);
10305 return((Image *) NULL);
10308 for (i=1; i < count; i++)
10309 if (*files[i] != '-')
10310 filelist[j++]=files[i];
10311 filelist[j]=(char *) NULL;
10312 XListBrowserWidget(display,windows,&windows->widget,
10313 (const char **) filelist,"Load","Select Image to Load:",filename);
10314 filelist=(char **) RelinquishMagickMemory(filelist);
10315 (void) XFreeStringList(files);
10317 if (*filename == '\0')
10318 return((Image *) NULL);
10319 image_info=CloneImageInfo(resource_info->image_info);
10320 (void) SetImageInfoProgressMonitor(image_info,(MagickProgressMonitor) NULL,
10322 (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
10323 exception=AcquireExceptionInfo();
10324 (void) SetImageInfo(image_info,0,exception);
10325 if (LocaleCompare(image_info->magick,"X") == 0)
10328 seconds[MaxTextExtent];
10331 User may want to delay the X server screen grab.
10333 (void) CopyMagickString(seconds,"0",MaxTextExtent);
10334 (void) XDialogWidget(display,windows,"Grab","Enter any delay in seconds:",
10336 if (*seconds == '\0')
10337 return((Image *) NULL);
10338 XDelay(display,(size_t) (1000*StringToLong(seconds)));
10340 magick_info=GetMagickInfo(image_info->magick,exception);
10341 if ((magick_info != (const MagickInfo *) NULL) &&
10342 IfMagickTrue(magick_info->raw))
10345 geometry[MaxTextExtent];
10348 Request image size from the user.
10350 (void) CopyMagickString(geometry,"512x512",MaxTextExtent);
10351 if (image_info->size != (char *) NULL)
10352 (void) CopyMagickString(geometry,image_info->size,MaxTextExtent);
10353 (void) XDialogWidget(display,windows,"Load","Enter the image geometry:",
10355 (void) CloneString(&image_info->size,geometry);
10360 XSetCursorState(display,windows,MagickTrue);
10361 XCheckRefreshWindows(display,windows);
10362 (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
10363 nexus=ReadImage(image_info,exception);
10364 CatchException(exception);
10365 XSetCursorState(display,windows,MagickFalse);
10366 if (nexus != (Image *) NULL)
10367 XClientMessage(display,windows->image.id,windows->im_protocols,
10368 windows->im_next_image,CurrentTime);
10376 Unknown image format.
10378 text=FileToString(filename,~0UL,exception);
10379 if (text == (char *) NULL)
10380 return((Image *) NULL);
10381 textlist=StringToList(text);
10382 if (textlist != (char **) NULL)
10385 title[MaxTextExtent];
10390 (void) FormatLocaleString(title,MaxTextExtent,
10391 "Unknown format: %s",filename);
10392 XTextViewWidget(display,resource_info,windows,MagickTrue,title,
10393 (const char **) textlist);
10394 for (i=0; textlist[i] != (char *) NULL; i++)
10395 textlist[i]=DestroyString(textlist[i]);
10396 textlist=(char **) RelinquishMagickMemory(textlist);
10398 text=DestroyString(text);
10400 exception=DestroyExceptionInfo(exception);
10401 image_info=DestroyImageInfo(image_info);
10406 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10410 + X P a n I m a g e %
10414 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10416 % XPanImage() pans the image until the mouse button is released.
10418 % The format of the XPanImage method is:
10420 % void XPanImage(Display *display,XWindows *windows,XEvent *event,
10421 % ExceptionInfo *exception)
10423 % A description of each parameter follows:
10425 % o display: Specifies a connection to an X server; returned from
10428 % o windows: Specifies a pointer to a XWindows structure.
10430 % o event: Specifies a pointer to a XEvent structure. If it is NULL,
10431 % the entire image is refreshed.
10433 % o exception: return any errors or warnings in this structure.
10436 static void XPanImage(Display *display,XWindows *windows,XEvent *event,
10437 ExceptionInfo *exception)
10440 text[MaxTextExtent];
10458 if ((windows->image.ximage->width > (int) windows->image.width) &&
10459 (windows->image.ximage->height > (int) windows->image.height))
10460 cursor=XCreateFontCursor(display,XC_fleur);
10462 if (windows->image.ximage->width > (int) windows->image.width)
10463 cursor=XCreateFontCursor(display,XC_sb_h_double_arrow);
10465 if (windows->image.ximage->height > (int) windows->image.height)
10466 cursor=XCreateFontCursor(display,XC_sb_v_double_arrow);
10468 cursor=XCreateFontCursor(display,XC_arrow);
10469 (void) XCheckDefineCursor(display,windows->pan.id,cursor);
10471 Pan image as pointer moves until the mouse button is released.
10473 x_factor=(double) windows->image.ximage->width/windows->pan.width;
10474 y_factor=(double) windows->image.ximage->height/windows->pan.height;
10475 pan_info.width=windows->pan.width*windows->image.width/
10476 windows->image.ximage->width;
10477 pan_info.height=windows->pan.height*windows->image.height/
10478 windows->image.ximage->height;
10481 state=UpdateConfigurationState;
10484 switch (event->type)
10489 User choose an initial pan location.
10491 pan_info.x=(ssize_t) event->xbutton.x;
10492 pan_info.y=(ssize_t) event->xbutton.y;
10493 state|=UpdateConfigurationState;
10496 case ButtonRelease:
10499 User has finished panning the image.
10501 pan_info.x=(ssize_t) event->xbutton.x;
10502 pan_info.y=(ssize_t) event->xbutton.y;
10503 state|=UpdateConfigurationState | ExitState;
10508 pan_info.x=(ssize_t) event->xmotion.x;
10509 pan_info.y=(ssize_t) event->xmotion.y;
10510 state|=UpdateConfigurationState;
10515 if ((state & UpdateConfigurationState) != 0)
10518 Check boundary conditions.
10520 if (pan_info.x < (ssize_t) (pan_info.width/2))
10523 pan_info.x=(ssize_t) (x_factor*(pan_info.x-(pan_info.width/2)));
10524 if (pan_info.x < 0)
10527 if ((int) (pan_info.x+windows->image.width) >
10528 windows->image.ximage->width)
10529 pan_info.x=(ssize_t)
10530 (windows->image.ximage->width-windows->image.width);
10531 if (pan_info.y < (ssize_t) (pan_info.height/2))
10534 pan_info.y=(ssize_t) (y_factor*(pan_info.y-(pan_info.height/2)));
10535 if (pan_info.y < 0)
10538 if ((int) (pan_info.y+windows->image.height) >
10539 windows->image.ximage->height)
10540 pan_info.y=(ssize_t)
10541 (windows->image.ximage->height-windows->image.height);
10542 if ((windows->image.x != (int) pan_info.x) ||
10543 (windows->image.y != (int) pan_info.y))
10546 Display image pan offset.
10548 windows->image.x=(int) pan_info.x;
10549 windows->image.y=(int) pan_info.y;
10550 (void) FormatLocaleString(text,MaxTextExtent," %ux%u%+d%+d ",
10551 windows->image.width,windows->image.height,windows->image.x,
10553 XInfoWidget(display,windows,text);
10555 Refresh Image window.
10557 XDrawPanRectangle(display,windows);
10558 XRefreshWindow(display,&windows->image,(XEvent *) NULL);
10560 state&=(~UpdateConfigurationState);
10563 Wait for next event.
10565 if ((state & ExitState) == 0)
10566 XScreenEvent(display,windows,event,exception);
10567 } while ((state & ExitState) == 0);
10571 (void) XCheckDefineCursor(display,windows->pan.id,windows->pan.cursor);
10572 (void) XFreeCursor(display,cursor);
10573 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
10577 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10581 + X P a s t e I m a g e %
10585 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10587 % XPasteImage() pastes an image previously saved with XCropImage in the X
10588 % window image at a location the user chooses with the pointer.
10590 % The format of the XPasteImage method is:
10592 % MagickBooleanType XPasteImage(Display *display,
10593 % XResourceInfo *resource_info,XWindows *windows,Image *image,
10594 % ExceptionInfo *exception)
10596 % A description of each parameter follows:
10598 % o display: Specifies a connection to an X server; returned from
10601 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
10603 % o windows: Specifies a pointer to a XWindows structure.
10605 % o image: the image; returned from ReadImage.
10607 % o exception: return any errors or warnings in this structure.
10610 static MagickBooleanType XPasteImage(Display *display,
10611 XResourceInfo *resource_info,XWindows *windows,Image *image,
10612 ExceptionInfo *exception)
10623 static const ModeType
10626 PasteOperatorsCommand,
10628 PasteDismissCommand
10631 static CompositeOperator
10632 compose = CopyCompositeOp;
10635 text[MaxTextExtent];
10669 if (resource_info->copy_image == (Image *) NULL)
10670 return(MagickFalse);
10671 paste_image=CloneImage(resource_info->copy_image,0,0,MagickTrue,exception);
10673 Map Command widget.
10675 (void) CloneString(&windows->command.name,"Paste");
10676 windows->command.data=1;
10677 (void) XCommandWidget(display,windows,PasteMenu,(XEvent *) NULL);
10678 (void) XMapRaised(display,windows->command.id);
10679 XClientMessage(display,windows->image.id,windows->im_protocols,
10680 windows->im_update_widget,CurrentTime);
10682 Track pointer until button 1 is pressed.
10684 XSetCursorState(display,windows,MagickFalse);
10685 XQueryPosition(display,windows->image.id,&x,&y);
10686 (void) XSelectInput(display,windows->image.id,
10687 windows->image.attributes.event_mask | PointerMotionMask);
10688 paste_info.x=(ssize_t) windows->image.x+x;
10689 paste_info.y=(ssize_t) windows->image.y+y;
10690 paste_info.width=0;
10691 paste_info.height=0;
10692 cursor=XCreateFontCursor(display,XC_ul_angle);
10693 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
10694 state=DefaultState;
10697 if (IfMagickTrue(windows->info.mapped) )
10700 Display pointer position.
10702 (void) FormatLocaleString(text,MaxTextExtent," %+ld%+ld ",
10703 (long) paste_info.x,(long) paste_info.y);
10704 XInfoWidget(display,windows,text);
10706 highlight_info=paste_info;
10707 highlight_info.x=paste_info.x-windows->image.x;
10708 highlight_info.y=paste_info.y-windows->image.y;
10709 XHighlightRectangle(display,windows->image.id,
10710 windows->image.highlight_context,&highlight_info);
10712 Wait for next event.
10714 XScreenEvent(display,windows,&event,exception);
10715 XHighlightRectangle(display,windows->image.id,
10716 windows->image.highlight_context,&highlight_info);
10717 if (event.xany.window == windows->command.id)
10720 Select a command from the Command widget.
10722 id=XCommandWidget(display,windows,PasteMenu,&event);
10725 switch (PasteCommands[id])
10727 case PasteOperatorsCommand:
10730 command[MaxTextExtent],
10734 Select a command from the pop-up menu.
10736 operators=GetCommandOptions(MagickComposeOptions);
10737 if (operators == (char **) NULL)
10739 entry=XMenuWidget(display,windows,PasteMenu[id],
10740 (const char **) operators,command);
10742 compose=(CompositeOperator) ParseCommandOption(
10743 MagickComposeOptions,MagickFalse,operators[entry]);
10744 operators=DestroyStringList(operators);
10747 case PasteHelpCommand:
10749 XTextViewWidget(display,resource_info,windows,MagickFalse,
10750 "Help Viewer - Image Composite",ImagePasteHelp);
10753 case PasteDismissCommand:
10758 state|=EscapeState;
10767 switch (event.type)
10771 if (IfMagickTrue(image->debug) )
10772 (void) LogMagickEvent(X11Event,GetMagickModule(),
10773 "Button Press: 0x%lx %u +%d+%d",event.xbutton.window,
10774 event.xbutton.button,event.xbutton.x,event.xbutton.y);
10775 if (event.xbutton.button != Button1)
10777 if (event.xbutton.window != windows->image.id)
10780 Paste rectangle is relative to image configuration.
10782 width=(unsigned int) image->columns;
10783 height=(unsigned int) image->rows;
10786 if (windows->image.crop_geometry != (char *) NULL)
10787 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,
10789 scale_factor=(double) windows->image.ximage->width/width;
10790 paste_info.width=(unsigned int) (scale_factor*paste_image->columns+0.5);
10791 scale_factor=(double) windows->image.ximage->height/height;
10792 paste_info.height=(unsigned int) (scale_factor*paste_image->rows+0.5);
10793 (void) XCheckDefineCursor(display,windows->image.id,cursor);
10794 paste_info.x=(ssize_t) windows->image.x+event.xbutton.x;
10795 paste_info.y=(ssize_t) windows->image.y+event.xbutton.y;
10798 case ButtonRelease:
10800 if (IfMagickTrue(image->debug) )
10801 (void) LogMagickEvent(X11Event,GetMagickModule(),
10802 "Button Release: 0x%lx %u +%d+%d",event.xbutton.window,
10803 event.xbutton.button,event.xbutton.x,event.xbutton.y);
10804 if (event.xbutton.button != Button1)
10806 if (event.xbutton.window != windows->image.id)
10808 if ((paste_info.width != 0) && (paste_info.height != 0))
10811 User has selected the location of the paste image.
10813 paste_info.x=(ssize_t) windows->image.x+event.xbutton.x;
10814 paste_info.y=(ssize_t) windows->image.y+event.xbutton.y;
10824 command[MaxTextExtent];
10832 if (event.xkey.window != windows->image.id)
10835 Respond to a user key press.
10837 length=XLookupString((XKeyEvent *) &event.xkey,command,(int)
10838 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
10839 *(command+length)='\0';
10840 if (IfMagickTrue(image->debug) )
10841 (void) LogMagickEvent(X11Event,GetMagickModule(),
10842 "Key press: 0x%lx (%s)",(long) key_symbol,command);
10843 switch ((int) key_symbol)
10851 paste_image=DestroyImage(paste_image);
10852 state|=EscapeState;
10859 (void) XSetFunction(display,windows->image.highlight_context,
10861 XTextViewWidget(display,resource_info,windows,MagickFalse,
10862 "Help Viewer - Image Composite",ImagePasteHelp);
10863 (void) XSetFunction(display,windows->image.highlight_context,
10869 (void) XBell(display,0);
10878 Map and unmap Info widget as text cursor crosses its boundaries.
10882 if (IfMagickTrue(windows->info.mapped) )
10884 if ((x < (int) (windows->info.x+windows->info.width)) &&
10885 (y < (int) (windows->info.y+windows->info.height)))
10886 (void) XWithdrawWindow(display,windows->info.id,
10887 windows->info.screen);
10890 if ((x > (int) (windows->info.x+windows->info.width)) ||
10891 (y > (int) (windows->info.y+windows->info.height)))
10892 (void) XMapWindow(display,windows->info.id);
10893 paste_info.x=(ssize_t) windows->image.x+x;
10894 paste_info.y=(ssize_t) windows->image.y+y;
10899 if (IfMagickTrue(image->debug) )
10900 (void) LogMagickEvent(X11Event,GetMagickModule(),"Event type: %d",
10905 } while ((state & ExitState) == 0);
10906 (void) XSelectInput(display,windows->image.id,
10907 windows->image.attributes.event_mask);
10908 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
10909 XSetCursorState(display,windows,MagickFalse);
10910 (void) XFreeCursor(display,cursor);
10911 if ((state & EscapeState) != 0)
10912 return(MagickTrue);
10914 Image pasting is relative to image configuration.
10916 XSetCursorState(display,windows,MagickTrue);
10917 XCheckRefreshWindows(display,windows);
10918 width=(unsigned int) image->columns;
10919 height=(unsigned int) image->rows;
10922 if (windows->image.crop_geometry != (char *) NULL)
10923 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
10924 scale_factor=(double) width/windows->image.ximage->width;
10926 paste_info.x=(ssize_t) (scale_factor*paste_info.x+0.5);
10927 paste_info.width=(unsigned int) (scale_factor*paste_info.width+0.5);
10928 scale_factor=(double) height/windows->image.ximage->height;
10930 paste_info.y=(ssize_t) (scale_factor*paste_info.y*scale_factor+0.5);
10931 paste_info.height=(unsigned int) (scale_factor*paste_info.height+0.5);
10933 Paste image with X Image window.
10935 (void) CompositeImage(image,paste_image,compose,MagickTrue,paste_info.x,
10936 paste_info.y,exception);
10937 paste_image=DestroyImage(paste_image);
10938 XSetCursorState(display,windows,MagickFalse);
10940 Update image colormap.
10942 XConfigureImageColormap(display,resource_info,windows,image,exception);
10943 (void) XConfigureImage(display,resource_info,windows,image,exception);
10944 return(MagickTrue);
10948 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10952 + X P r i n t I m a g e %
10956 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10958 % XPrintImage() prints an image to a Postscript printer.
10960 % The format of the XPrintImage method is:
10962 % MagickBooleanType XPrintImage(Display *display,
10963 % XResourceInfo *resource_info,XWindows *windows,Image *image,
10964 % ExceptionInfo *exception)
10966 % A description of each parameter follows:
10968 % o display: Specifies a connection to an X server; returned from
10971 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
10973 % o windows: Specifies a pointer to a XWindows structure.
10975 % o image: the image.
10977 % o exception: return any errors or warnings in this structure.
10980 static MagickBooleanType XPrintImage(Display *display,
10981 XResourceInfo *resource_info,XWindows *windows,Image *image,
10982 ExceptionInfo *exception)
10985 filename[MaxTextExtent],
10986 geometry[MaxTextExtent];
10998 Request Postscript page geometry from user.
11000 image_info=CloneImageInfo(resource_info->image_info);
11001 (void) FormatLocaleString(geometry,MaxTextExtent,"Letter");
11002 if (image_info->page != (char *) NULL)
11003 (void) CopyMagickString(geometry,image_info->page,MaxTextExtent);
11004 XListBrowserWidget(display,windows,&windows->widget,PageSizes,"Select",
11005 "Select Postscript Page Geometry:",geometry);
11006 if (*geometry == '\0')
11007 return(MagickTrue);
11008 image_info->page=GetPageGeometry(geometry);
11010 Apply image transforms.
11012 XSetCursorState(display,windows,MagickTrue);
11013 XCheckRefreshWindows(display,windows);
11014 print_image=CloneImage(image,0,0,MagickTrue,exception);
11015 if (print_image == (Image *) NULL)
11016 return(MagickFalse);
11017 (void) FormatLocaleString(geometry,MaxTextExtent,"%dx%d!",
11018 windows->image.ximage->width,windows->image.ximage->height);
11019 (void) TransformImage(&print_image,windows->image.crop_geometry,geometry,
11024 (void) AcquireUniqueFilename(filename);
11025 (void) FormatLocaleString(print_image->filename,MaxTextExtent,"print:%s",
11027 status=WriteImage(image_info,print_image,exception);
11028 (void) RelinquishUniqueFileResource(filename);
11029 print_image=DestroyImage(print_image);
11030 image_info=DestroyImageInfo(image_info);
11031 XSetCursorState(display,windows,MagickFalse);
11032 return(IsMagickTrue(status));
11036 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
11040 + X R O I I m a g e %
11044 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
11046 % XROIImage() applies an image processing technique to a region of interest.
11048 % The format of the XROIImage method is:
11050 % MagickBooleanType XROIImage(Display *display,
11051 % XResourceInfo *resource_info,XWindows *windows,Image **image,
11052 % ExceptionInfo *exception)
11054 % A description of each parameter follows:
11056 % o display: Specifies a connection to an X server; returned from
11059 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
11061 % o windows: Specifies a pointer to a XWindows structure.
11063 % o image: the image; returned from ReadImage.
11065 % o exception: return any errors or warnings in this structure.
11068 static MagickBooleanType XROIImage(Display *display,
11069 XResourceInfo *resource_info,XWindows *windows,Image **image,
11070 ExceptionInfo *exception)
11072 #define ApplyMenus 7
11122 "Contrast Stretch...",
11123 "Sigmoidal Contrast...",
11157 "Charcoal Draw...",
11160 *MiscellanyMenu[] =
11171 **Menus[ApplyMenus] =
11182 static const CommandType
11205 TransformCommands[] =
11209 RotateRightCommand,
11212 EnhanceCommands[] =
11220 ContrastStretchCommand,
11221 SigmoidalContrastCommand,
11229 EffectsCommands[] =
11233 ReduceNoiseCommand,
11252 CharcoalDrawCommand
11254 MiscellanyCommands[] =
11258 ShowPreviewCommand,
11259 ShowHistogramCommand,
11268 static const CommandType
11269 *Commands[ApplyMenus] =
11281 command[MaxTextExtent],
11282 text[MaxTextExtent];
11302 MagickProgressMonitor
11321 Map Command widget.
11323 (void) CloneString(&windows->command.name,"ROI");
11324 windows->command.data=0;
11325 (void) XCommandWidget(display,windows,ROIMenu,(XEvent *) NULL);
11326 (void) XMapRaised(display,windows->command.id);
11327 XClientMessage(display,windows->image.id,windows->im_protocols,
11328 windows->im_update_widget,CurrentTime);
11330 Track pointer until button 1 is pressed.
11332 XQueryPosition(display,windows->image.id,&x,&y);
11333 (void) XSelectInput(display,windows->image.id,
11334 windows->image.attributes.event_mask | PointerMotionMask);
11335 roi_info.x=(ssize_t) windows->image.x+x;
11336 roi_info.y=(ssize_t) windows->image.y+y;
11339 cursor=XCreateFontCursor(display,XC_fleur);
11340 state=DefaultState;
11343 if (IfMagickTrue(windows->info.mapped) )
11346 Display pointer position.
11348 (void) FormatLocaleString(text,MaxTextExtent," %+ld%+ld ",
11349 (long) roi_info.x,(long) roi_info.y);
11350 XInfoWidget(display,windows,text);
11353 Wait for next event.
11355 XScreenEvent(display,windows,&event,exception);
11356 if (event.xany.window == windows->command.id)
11359 Select a command from the Command widget.
11361 id=XCommandWidget(display,windows,ROIMenu,&event);
11364 switch (ROICommands[id])
11366 case ROIHelpCommand:
11368 XTextViewWidget(display,resource_info,windows,MagickFalse,
11369 "Help Viewer - Region of Interest",ImageROIHelp);
11372 case ROIDismissCommand:
11377 state|=EscapeState;
11386 switch (event.type)
11390 if (event.xbutton.button != Button1)
11392 if (event.xbutton.window != windows->image.id)
11395 Note first corner of region of interest rectangle-- exit loop.
11397 (void) XCheckDefineCursor(display,windows->image.id,cursor);
11398 roi_info.x=(ssize_t) windows->image.x+event.xbutton.x;
11399 roi_info.y=(ssize_t) windows->image.y+event.xbutton.y;
11403 case ButtonRelease:
11412 if (event.xkey.window != windows->image.id)
11415 Respond to a user key press.
11417 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
11418 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
11419 switch ((int) key_symbol)
11427 state|=EscapeState;
11434 XTextViewWidget(display,resource_info,windows,MagickFalse,
11435 "Help Viewer - Region of Interest",ImageROIHelp);
11440 (void) XBell(display,0);
11449 Map and unmap Info widget as text cursor crosses its boundaries.
11453 if (IfMagickTrue(windows->info.mapped) )
11455 if ((x < (int) (windows->info.x+windows->info.width)) &&
11456 (y < (int) (windows->info.y+windows->info.height)))
11457 (void) XWithdrawWindow(display,windows->info.id,
11458 windows->info.screen);
11461 if ((x > (int) (windows->info.x+windows->info.width)) ||
11462 (y > (int) (windows->info.y+windows->info.height)))
11463 (void) XMapWindow(display,windows->info.id);
11464 roi_info.x=(ssize_t) windows->image.x+x;
11465 roi_info.y=(ssize_t) windows->image.y+y;
11471 } while ((state & ExitState) == 0);
11472 (void) XSelectInput(display,windows->image.id,
11473 windows->image.attributes.event_mask);
11474 if ((state & EscapeState) != 0)
11477 User want to exit without region of interest.
11479 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
11480 (void) XFreeCursor(display,cursor);
11481 return(MagickTrue);
11483 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
11487 Size rectangle as pointer moves until the mouse button is released.
11489 x=(int) roi_info.x;
11490 y=(int) roi_info.y;
11493 state=DefaultState;
11496 highlight_info=roi_info;
11497 highlight_info.x=roi_info.x-windows->image.x;
11498 highlight_info.y=roi_info.y-windows->image.y;
11499 if ((highlight_info.width > 3) && (highlight_info.height > 3))
11502 Display info and draw region of interest rectangle.
11504 if (IfMagickFalse(windows->info.mapped) )
11505 (void) XMapWindow(display,windows->info.id);
11506 (void) FormatLocaleString(text,MaxTextExtent,
11507 " %.20gx%.20g%+.20g%+.20g",(double) roi_info.width,(double)
11508 roi_info.height,(double) roi_info.x,(double) roi_info.y);
11509 XInfoWidget(display,windows,text);
11510 XHighlightRectangle(display,windows->image.id,
11511 windows->image.highlight_context,&highlight_info);
11514 if (IfMagickTrue(windows->info.mapped) )
11515 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
11517 Wait for next event.
11519 XScreenEvent(display,windows,&event,exception);
11520 if ((highlight_info.width > 3) && (highlight_info.height > 3))
11521 XHighlightRectangle(display,windows->image.id,
11522 windows->image.highlight_context,&highlight_info);
11523 switch (event.type)
11527 roi_info.x=(ssize_t) windows->image.x+event.xbutton.x;
11528 roi_info.y=(ssize_t) windows->image.y+event.xbutton.y;
11531 case ButtonRelease:
11534 User has committed to region of interest rectangle.
11536 roi_info.x=(ssize_t) windows->image.x+event.xbutton.x;
11537 roi_info.y=(ssize_t) windows->image.y+event.xbutton.y;
11538 XSetCursorState(display,windows,MagickFalse);
11540 if (LocaleCompare(windows->command.name,"Apply") == 0)
11542 (void) CloneString(&windows->command.name,"Apply");
11543 windows->command.data=ApplyMenus;
11544 (void) XCommandWidget(display,windows,ApplyMenu,(XEvent *) NULL);
11551 roi_info.x=(ssize_t) windows->image.x+event.xmotion.x;
11552 roi_info.y=(ssize_t) windows->image.y+event.xmotion.y;
11557 if ((((int) roi_info.x != x) && ((int) roi_info.y != y)) ||
11558 ((state & ExitState) != 0))
11561 Check boundary conditions.
11563 if (roi_info.x < 0)
11566 if (roi_info.x > (ssize_t) windows->image.ximage->width)
11567 roi_info.x=(ssize_t) windows->image.ximage->width;
11568 if ((int) roi_info.x < x)
11569 roi_info.width=(unsigned int) (x-roi_info.x);
11572 roi_info.width=(unsigned int) (roi_info.x-x);
11573 roi_info.x=(ssize_t) x;
11575 if (roi_info.y < 0)
11578 if (roi_info.y > (ssize_t) windows->image.ximage->height)
11579 roi_info.y=(ssize_t) windows->image.ximage->height;
11580 if ((int) roi_info.y < y)
11581 roi_info.height=(unsigned int) (y-roi_info.y);
11584 roi_info.height=(unsigned int) (roi_info.y-y);
11585 roi_info.y=(ssize_t) y;
11588 } while ((state & ExitState) == 0);
11590 Wait for user to grab a corner of the rectangle or press return.
11592 state=DefaultState;
11593 command_type=NullCommand;
11594 (void) XMapWindow(display,windows->info.id);
11597 if (IfMagickTrue(windows->info.mapped) )
11600 Display pointer position.
11602 (void) FormatLocaleString(text,MaxTextExtent,
11603 " %.20gx%.20g%+.20g%+.20g",(double) roi_info.width,(double)
11604 roi_info.height,(double) roi_info.x,(double) roi_info.y);
11605 XInfoWidget(display,windows,text);
11607 highlight_info=roi_info;
11608 highlight_info.x=roi_info.x-windows->image.x;
11609 highlight_info.y=roi_info.y-windows->image.y;
11610 if ((highlight_info.width <= 3) || (highlight_info.height <= 3))
11612 state|=EscapeState;
11616 if ((state & UpdateRegionState) != 0)
11618 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
11619 switch (command_type)
11624 (void) XMagickCommand(display,resource_info,windows,command_type,
11631 Region of interest is relative to image configuration.
11633 progress_monitor=SetImageProgressMonitor(*image,
11634 (MagickProgressMonitor) NULL,(*image)->client_data);
11635 crop_info=roi_info;
11636 width=(unsigned int) (*image)->columns;
11637 height=(unsigned int) (*image)->rows;
11640 if (windows->image.crop_geometry != (char *) NULL)
11641 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,
11643 scale_factor=(double) width/windows->image.ximage->width;
11645 crop_info.x=(ssize_t) (scale_factor*crop_info.x+0.5);
11646 crop_info.width=(unsigned int) (scale_factor*crop_info.width+0.5);
11647 scale_factor=(double)
11648 height/windows->image.ximage->height;
11650 crop_info.y=(ssize_t) (scale_factor*crop_info.y+0.5);
11651 crop_info.height=(unsigned int)
11652 (scale_factor*crop_info.height+0.5);
11653 roi_image=CropImage(*image,&crop_info,exception);
11654 (void) SetImageProgressMonitor(*image,progress_monitor,
11655 (*image)->client_data);
11656 if (roi_image == (Image *) NULL)
11659 Apply image processing technique to the region of interest.
11661 windows->image.orphan=MagickTrue;
11662 (void) XMagickCommand(display,resource_info,windows,command_type,
11663 &roi_image,exception);
11664 progress_monitor=SetImageProgressMonitor(*image,
11665 (MagickProgressMonitor) NULL,(*image)->client_data);
11666 (void) XMagickCommand(display,resource_info,windows,
11667 SaveToUndoBufferCommand,image,exception);
11668 windows->image.orphan=MagickFalse;
11669 (void) CompositeImage(*image,roi_image,CopyCompositeOp,
11670 MagickTrue,crop_info.x,crop_info.y,exception);
11671 roi_image=DestroyImage(roi_image);
11672 (void) SetImageProgressMonitor(*image,progress_monitor,
11673 (*image)->client_data);
11677 if (command_type != InfoCommand)
11679 XConfigureImageColormap(display,resource_info,windows,*image,
11681 (void) XConfigureImage(display,resource_info,windows,*image,
11684 XCheckRefreshWindows(display,windows);
11685 XInfoWidget(display,windows,text);
11686 (void) XSetFunction(display,windows->image.highlight_context,
11688 state&=(~UpdateRegionState);
11690 XHighlightRectangle(display,windows->image.id,
11691 windows->image.highlight_context,&highlight_info);
11692 XScreenEvent(display,windows,&event,exception);
11693 if (event.xany.window == windows->command.id)
11696 Select a command from the Command widget.
11698 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
11699 command_type=NullCommand;
11700 id=XCommandWidget(display,windows,ApplyMenu,&event);
11703 (void) CopyMagickString(command,ApplyMenu[id],MaxTextExtent);
11704 command_type=ApplyCommands[id];
11705 if (id < ApplyMenus)
11708 Select a command from a pop-up menu.
11710 entry=XMenuWidget(display,windows,ApplyMenu[id],
11711 (const char **) Menus[id],command);
11714 (void) CopyMagickString(command,Menus[id][entry],
11716 command_type=Commands[id][entry];
11720 (void) XSetFunction(display,windows->image.highlight_context,
11722 XHighlightRectangle(display,windows->image.id,
11723 windows->image.highlight_context,&highlight_info);
11724 if (command_type == HelpCommand)
11726 (void) XSetFunction(display,windows->image.highlight_context,
11728 XTextViewWidget(display,resource_info,windows,MagickFalse,
11729 "Help Viewer - Region of Interest",ImageROIHelp);
11730 (void) XSetFunction(display,windows->image.highlight_context,
11734 if (command_type == QuitCommand)
11739 state|=EscapeState;
11743 if (command_type != NullCommand)
11744 state|=UpdateRegionState;
11747 XHighlightRectangle(display,windows->image.id,
11748 windows->image.highlight_context,&highlight_info);
11749 switch (event.type)
11753 x=windows->image.x;
11754 y=windows->image.y;
11755 if (event.xbutton.button != Button1)
11757 if (event.xbutton.window != windows->image.id)
11759 x=windows->image.x+event.xbutton.x;
11760 y=windows->image.y+event.xbutton.y;
11761 if ((x < (int) (roi_info.x+RoiDelta)) &&
11762 (x > (int) (roi_info.x-RoiDelta)) &&
11763 (y < (int) (roi_info.y+RoiDelta)) &&
11764 (y > (int) (roi_info.y-RoiDelta)))
11766 roi_info.x=(ssize_t) (roi_info.x+roi_info.width);
11767 roi_info.y=(ssize_t) (roi_info.y+roi_info.height);
11768 state|=UpdateConfigurationState;
11771 if ((x < (int) (roi_info.x+RoiDelta)) &&
11772 (x > (int) (roi_info.x-RoiDelta)) &&
11773 (y < (int) (roi_info.y+roi_info.height+RoiDelta)) &&
11774 (y > (int) (roi_info.y+roi_info.height-RoiDelta)))
11776 roi_info.x=(ssize_t) (roi_info.x+roi_info.width);
11777 state|=UpdateConfigurationState;
11780 if ((x < (int) (roi_info.x+roi_info.width+RoiDelta)) &&
11781 (x > (int) (roi_info.x+roi_info.width-RoiDelta)) &&
11782 (y < (int) (roi_info.y+RoiDelta)) &&
11783 (y > (int) (roi_info.y-RoiDelta)))
11785 roi_info.y=(ssize_t) (roi_info.y+roi_info.height);
11786 state|=UpdateConfigurationState;
11789 if ((x < (int) (roi_info.x+roi_info.width+RoiDelta)) &&
11790 (x > (int) (roi_info.x+roi_info.width-RoiDelta)) &&
11791 (y < (int) (roi_info.y+roi_info.height+RoiDelta)) &&
11792 (y > (int) (roi_info.y+roi_info.height-RoiDelta)))
11794 state|=UpdateConfigurationState;
11798 case ButtonRelease:
11800 if (event.xbutton.window == windows->pan.id)
11801 if ((highlight_info.x != crop_info.x-windows->image.x) ||
11802 (highlight_info.y != crop_info.y-windows->image.y))
11803 XHighlightRectangle(display,windows->image.id,
11804 windows->image.highlight_context,&highlight_info);
11805 (void) XSetSelectionOwner(display,XA_PRIMARY,windows->image.id,
11806 event.xbutton.time);
11811 if (event.xexpose.window == windows->image.id)
11812 if (event.xexpose.count == 0)
11814 event.xexpose.x=(int) highlight_info.x;
11815 event.xexpose.y=(int) highlight_info.y;
11816 event.xexpose.width=(int) highlight_info.width;
11817 event.xexpose.height=(int) highlight_info.height;
11818 XRefreshWindow(display,&windows->image,&event);
11820 if (event.xexpose.window == windows->info.id)
11821 if (event.xexpose.count == 0)
11822 XInfoWidget(display,windows,text);
11830 if (event.xkey.window != windows->image.id)
11833 Respond to a user key press.
11835 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
11836 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
11837 switch ((int) key_symbol)
11844 state|=EscapeState;
11853 roi_info.x=(ssize_t) (windows->image.width/2L-roi_info.width/2L);
11854 roi_info.y=(ssize_t) (windows->image.height/2L-
11855 roi_info.height/2L);
11887 (void) XSetFunction(display,windows->image.highlight_context,
11889 XTextViewWidget(display,resource_info,windows,MagickFalse,
11890 "Help Viewer - Region of Interest",ImageROIHelp);
11891 (void) XSetFunction(display,windows->image.highlight_context,
11897 command_type=XImageWindowCommand(display,resource_info,windows,
11898 event.xkey.state,key_symbol,image,exception);
11899 if (command_type != NullCommand)
11900 state|=UpdateRegionState;
11904 (void) XSetSelectionOwner(display,XA_PRIMARY,windows->image.id,
11912 if (event.xbutton.window != windows->image.id)
11915 Map and unmap Info widget as text cursor crosses its boundaries.
11919 if (IfMagickTrue(windows->info.mapped) )
11921 if ((x < (int) (windows->info.x+windows->info.width)) &&
11922 (y < (int) (windows->info.y+windows->info.height)))
11923 (void) XWithdrawWindow(display,windows->info.id,
11924 windows->info.screen);
11927 if ((x > (int) (windows->info.x+windows->info.width)) ||
11928 (y > (int) (windows->info.y+windows->info.height)))
11929 (void) XMapWindow(display,windows->info.id);
11930 roi_info.x=(ssize_t) windows->image.x+event.xmotion.x;
11931 roi_info.y=(ssize_t) windows->image.y+event.xmotion.y;
11934 case SelectionRequest:
11939 XSelectionRequestEvent
11943 Set primary selection.
11945 (void) FormatLocaleString(text,MaxTextExtent,
11946 "%.20gx%.20g%+.20g%+.20g",(double) roi_info.width,(double)
11947 roi_info.height,(double) roi_info.x,(double) roi_info.y);
11948 request=(&(event.xselectionrequest));
11949 (void) XChangeProperty(request->display,request->requestor,
11950 request->property,request->target,8,PropModeReplace,
11951 (unsigned char *) text,(int) strlen(text));
11952 notify.type=SelectionNotify;
11953 notify.display=request->display;
11954 notify.requestor=request->requestor;
11955 notify.selection=request->selection;
11956 notify.target=request->target;
11957 notify.time=request->time;
11958 if (request->property == None)
11959 notify.property=request->target;
11961 notify.property=request->property;
11962 (void) XSendEvent(request->display,request->requestor,False,0,
11963 (XEvent *) ¬ify);
11968 if ((state & UpdateConfigurationState) != 0)
11970 (void) XPutBackEvent(display,&event);
11971 (void) XCheckDefineCursor(display,windows->image.id,cursor);
11974 } while ((state & ExitState) == 0);
11975 } while ((state & ExitState) == 0);
11976 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
11977 XSetCursorState(display,windows,MagickFalse);
11978 if ((state & EscapeState) != 0)
11979 return(MagickTrue);
11980 return(MagickTrue);
11984 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
11988 + X R o t a t e I m a g e %
11992 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
11994 % XRotateImage() rotates the X image. If the degrees parameter if zero, the
11995 % rotation angle is computed from the slope of a line drawn by the user.
11997 % The format of the XRotateImage method is:
11999 % MagickBooleanType XRotateImage(Display *display,
12000 % XResourceInfo *resource_info,XWindows *windows,double degrees,
12001 % Image **image,ExceptionInfo *exception)
12003 % A description of each parameter follows:
12005 % o display: Specifies a connection to an X server; returned from
12008 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
12010 % o windows: Specifies a pointer to a XWindows structure.
12012 % o degrees: Specifies the number of degrees to rotate the image.
12014 % o image: the image.
12016 % o exception: return any errors or warnings in this structure.
12019 static MagickBooleanType XRotateImage(Display *display,
12020 XResourceInfo *resource_info,XWindows *windows,double degrees,Image **image,
12021 ExceptionInfo *exception)
12034 direction = HorizontalRotateCommand;
12036 static const ModeType
12037 DirectionCommands[] =
12039 HorizontalRotateCommand,
12040 VerticalRotateCommand
12044 RotateColorCommand,
12045 RotateDirectionCommand,
12047 RotateDismissCommand
12050 static unsigned int
12054 command[MaxTextExtent],
12055 text[MaxTextExtent];
12066 normalized_degrees;
12076 if (degrees == 0.0)
12091 Map Command widget.
12093 (void) CloneString(&windows->command.name,"Rotate");
12094 windows->command.data=2;
12095 (void) XCommandWidget(display,windows,RotateMenu,(XEvent *) NULL);
12096 (void) XMapRaised(display,windows->command.id);
12097 XClientMessage(display,windows->image.id,windows->im_protocols,
12098 windows->im_update_widget,CurrentTime);
12100 Wait for first button press.
12102 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
12103 XQueryPosition(display,windows->image.id,&x,&y);
12108 state=DefaultState;
12111 XHighlightLine(display,windows->image.id,
12112 windows->image.highlight_context,&rotate_info);
12114 Wait for next event.
12116 XScreenEvent(display,windows,&event,exception);
12117 XHighlightLine(display,windows->image.id,
12118 windows->image.highlight_context,&rotate_info);
12119 if (event.xany.window == windows->command.id)
12122 Select a command from the Command widget.
12124 id=XCommandWidget(display,windows,RotateMenu,&event);
12127 (void) XSetFunction(display,windows->image.highlight_context,
12129 switch (RotateCommands[id])
12131 case RotateColorCommand:
12134 *ColorMenu[MaxNumberPens];
12143 Initialize menu selections.
12145 for (i=0; i < (int) (MaxNumberPens-2); i++)
12146 ColorMenu[i]=resource_info->pen_colors[i];
12147 ColorMenu[MaxNumberPens-2]="Browser...";
12148 ColorMenu[MaxNumberPens-1]=(const char *) NULL;
12150 Select a pen color from the pop-up menu.
12152 pen_number=XMenuWidget(display,windows,RotateMenu[id],
12153 (const char **) ColorMenu,command);
12154 if (pen_number < 0)
12156 if (pen_number == (MaxNumberPens-2))
12159 color_name[MaxTextExtent] = "gray";
12162 Select a pen color from a dialog.
12164 resource_info->pen_colors[pen_number]=color_name;
12165 XColorBrowserWidget(display,windows,"Select",color_name);
12166 if (*color_name == '\0')
12172 (void) XParseColor(display,windows->map_info->colormap,
12173 resource_info->pen_colors[pen_number],&color);
12174 XBestPixel(display,windows->map_info->colormap,(XColor *) NULL,
12175 (unsigned int) MaxColors,&color);
12176 windows->pixel_info->pen_colors[pen_number]=color;
12177 pen_id=(unsigned int) pen_number;
12180 case RotateDirectionCommand:
12191 Select a command from the pop-up menu.
12193 id=XMenuWidget(display,windows,RotateMenu[id],
12194 Directions,command);
12196 direction=DirectionCommands[id];
12199 case RotateHelpCommand:
12201 XTextViewWidget(display,resource_info,windows,MagickFalse,
12202 "Help Viewer - Image Rotation",ImageRotateHelp);
12205 case RotateDismissCommand:
12210 state|=EscapeState;
12217 (void) XSetFunction(display,windows->image.highlight_context,
12221 switch (event.type)
12225 if (event.xbutton.button != Button1)
12227 if (event.xbutton.window != windows->image.id)
12232 (void) XSetFunction(display,windows->image.highlight_context,
12234 rotate_info.x1=event.xbutton.x;
12235 rotate_info.y1=event.xbutton.y;
12239 case ButtonRelease:
12246 command[MaxTextExtent];
12251 if (event.xkey.window != windows->image.id)
12254 Respond to a user key press.
12256 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
12257 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
12258 switch ((int) key_symbol)
12266 state|=EscapeState;
12273 (void) XSetFunction(display,windows->image.highlight_context,
12275 XTextViewWidget(display,resource_info,windows,MagickFalse,
12276 "Help Viewer - Image Rotation",ImageRotateHelp);
12277 (void) XSetFunction(display,windows->image.highlight_context,
12283 (void) XBell(display,0);
12291 rotate_info.x1=event.xmotion.x;
12292 rotate_info.y1=event.xmotion.y;
12295 rotate_info.x2=rotate_info.x1;
12296 rotate_info.y2=rotate_info.y1;
12297 if (direction == HorizontalRotateCommand)
12298 rotate_info.x2+=32;
12300 rotate_info.y2-=32;
12301 } while ((state & ExitState) == 0);
12302 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
12303 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
12304 if ((state & EscapeState) != 0)
12305 return(MagickTrue);
12307 Draw line as pointer moves until the mouse button is released.
12310 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
12311 state=DefaultState;
12317 Display info and draw rotation line.
12319 if (IfMagickFalse(windows->info.mapped) )
12320 (void) XMapWindow(display,windows->info.id);
12321 (void) FormatLocaleString(text,MaxTextExtent," %g",
12322 direction == VerticalRotateCommand ? degrees-90.0 : degrees);
12323 XInfoWidget(display,windows,text);
12324 XHighlightLine(display,windows->image.id,
12325 windows->image.highlight_context,&rotate_info);
12328 if (IfMagickTrue(windows->info.mapped) )
12329 (void) XWithdrawWindow(display,windows->info.id,
12330 windows->info.screen);
12332 Wait for next event.
12334 XScreenEvent(display,windows,&event,exception);
12336 XHighlightLine(display,windows->image.id,
12337 windows->image.highlight_context,&rotate_info);
12338 switch (event.type)
12342 case ButtonRelease:
12345 User has committed to rotation line.
12347 rotate_info.x2=event.xbutton.x;
12348 rotate_info.y2=event.xbutton.y;
12356 rotate_info.x2=event.xmotion.x;
12357 rotate_info.y2=event.xmotion.y;
12363 Check boundary conditions.
12365 if (rotate_info.x2 < 0)
12368 if (rotate_info.x2 > (int) windows->image.width)
12369 rotate_info.x2=(short) windows->image.width;
12370 if (rotate_info.y2 < 0)
12373 if (rotate_info.y2 > (int) windows->image.height)
12374 rotate_info.y2=(short) windows->image.height;
12376 Compute rotation angle from the slope of the line.
12379 distance=(unsigned int)
12380 ((rotate_info.x2-rotate_info.x1+1)*(rotate_info.x2-rotate_info.x1+1))+
12381 ((rotate_info.y2-rotate_info.y1+1)*(rotate_info.y2-rotate_info.y1+1));
12383 degrees=RadiansToDegrees(-atan2((double) (rotate_info.y2-
12384 rotate_info.y1),(double) (rotate_info.x2-rotate_info.x1)));
12385 } while ((state & ExitState) == 0);
12386 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
12387 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
12389 return(MagickTrue);
12391 if (direction == VerticalRotateCommand)
12393 if (degrees == 0.0)
12394 return(MagickTrue);
12398 normalized_degrees=degrees;
12399 while (normalized_degrees < -45.0)
12400 normalized_degrees+=360.0;
12401 for (rotations=0; normalized_degrees > 45.0; rotations++)
12402 normalized_degrees-=90.0;
12403 if (normalized_degrees != 0.0)
12404 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image,
12406 XSetCursorState(display,windows,MagickTrue);
12407 XCheckRefreshWindows(display,windows);
12408 (*image)->background_color.red=(double) ScaleShortToQuantum(
12409 windows->pixel_info->pen_colors[pen_id].red);
12410 (*image)->background_color.green=(double) ScaleShortToQuantum(
12411 windows->pixel_info->pen_colors[pen_id].green);
12412 (*image)->background_color.blue=(double) ScaleShortToQuantum(
12413 windows->pixel_info->pen_colors[pen_id].blue);
12414 rotate_image=RotateImage(*image,degrees,exception);
12415 XSetCursorState(display,windows,MagickFalse);
12416 if (rotate_image == (Image *) NULL)
12417 return(MagickFalse);
12418 *image=DestroyImage(*image);
12419 *image=rotate_image;
12420 if (windows->image.crop_geometry != (char *) NULL)
12423 Rotate crop geometry.
12425 width=(unsigned int) (*image)->columns;
12426 height=(unsigned int) (*image)->rows;
12427 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
12428 switch (rotations % 4)
12438 (void) FormatLocaleString(windows->image.crop_geometry,MaxTextExtent,
12439 "%ux%u%+d%+d",height,width,(int) (*image)->columns-
12446 Rotate 180 degrees.
12448 (void) FormatLocaleString(windows->image.crop_geometry,MaxTextExtent,
12449 "%ux%u%+d%+d",width,height,(int) width-x,(int) height-y);
12455 Rotate 270 degrees.
12457 (void) FormatLocaleString(windows->image.crop_geometry,MaxTextExtent,
12458 "%ux%u%+d%+d",height,width,y,(int) (*image)->rows-(int) width-x);
12463 if (IfMagickTrue(windows->image.orphan) )
12464 return(MagickTrue);
12465 if (normalized_degrees != 0.0)
12468 Update image colormap.
12470 windows->image.window_changes.width=(int) (*image)->columns;
12471 windows->image.window_changes.height=(int) (*image)->rows;
12472 if (windows->image.crop_geometry != (char *) NULL)
12475 Obtain dimensions of image from crop geometry.
12477 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,
12479 windows->image.window_changes.width=(int) width;
12480 windows->image.window_changes.height=(int) height;
12482 XConfigureImageColormap(display,resource_info,windows,*image,exception);
12485 if (((rotations % 4) == 1) || ((rotations % 4) == 3))
12487 windows->image.window_changes.width=windows->image.ximage->height;
12488 windows->image.window_changes.height=windows->image.ximage->width;
12491 Update image configuration.
12493 (void) XConfigureImage(display,resource_info,windows,*image,exception);
12494 return(MagickTrue);
12498 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12502 + X S a v e I m a g e %
12506 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12508 % XSaveImage() saves an image to a file.
12510 % The format of the XSaveImage method is:
12512 % MagickBooleanType XSaveImage(Display *display,
12513 % XResourceInfo *resource_info,XWindows *windows,Image *image,
12514 % ExceptionInfo *exception)
12516 % A description of each parameter follows:
12518 % o display: Specifies a connection to an X server; returned from
12521 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
12523 % o windows: Specifies a pointer to a XWindows structure.
12525 % o image: the image.
12527 % o exception: return any errors or warnings in this structure.
12530 static MagickBooleanType XSaveImage(Display *display,
12531 XResourceInfo *resource_info,XWindows *windows,Image *image,
12532 ExceptionInfo *exception)
12535 filename[MaxTextExtent],
12536 geometry[MaxTextExtent];
12548 Request file name from user.
12550 if (resource_info->write_filename != (char *) NULL)
12551 (void) CopyMagickString(filename,resource_info->write_filename,
12556 path[MaxTextExtent];
12561 GetPathComponent(image->filename,HeadPath,path);
12562 GetPathComponent(image->filename,TailPath,filename);
12565 status=chdir(path);
12567 (void) ThrowMagickException(exception,GetMagickModule(),
12568 FileOpenError,"UnableToOpenFile","%s",path);
12571 XFileBrowserWidget(display,windows,"Save",filename);
12572 if (*filename == '\0')
12573 return(MagickTrue);
12574 if (IfMagickTrue(IsPathAccessible(filename)) )
12580 File exists-- seek user's permission before overwriting.
12582 status=XConfirmWidget(display,windows,"Overwrite",filename);
12584 return(MagickTrue);
12586 image_info=CloneImageInfo(resource_info->image_info);
12587 (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
12588 (void) SetImageInfo(image_info,1,exception);
12589 if ((LocaleCompare(image_info->magick,"JPEG") == 0) ||
12590 (LocaleCompare(image_info->magick,"JPG") == 0))
12593 quality[MaxTextExtent];
12599 Request JPEG quality from user.
12601 (void) FormatLocaleString(quality,MaxTextExtent,"%.20g",(double)
12603 status=XDialogWidget(display,windows,"Save","Enter JPEG quality:",
12605 if (*quality == '\0')
12606 return(MagickTrue);
12607 image->quality=StringToUnsignedLong(quality);
12608 image_info->interlace=status != 0 ? NoInterlace : PlaneInterlace;
12610 if ((LocaleCompare(image_info->magick,"EPS") == 0) ||
12611 (LocaleCompare(image_info->magick,"PDF") == 0) ||
12612 (LocaleCompare(image_info->magick,"PS") == 0) ||
12613 (LocaleCompare(image_info->magick,"PS2") == 0))
12616 geometry[MaxTextExtent];
12619 Request page geometry from user.
12621 (void) CopyMagickString(geometry,PSPageGeometry,MaxTextExtent);
12622 if (LocaleCompare(image_info->magick,"PDF") == 0)
12623 (void) CopyMagickString(geometry,PSPageGeometry,MaxTextExtent);
12624 if (image_info->page != (char *) NULL)
12625 (void) CopyMagickString(geometry,image_info->page,MaxTextExtent);
12626 XListBrowserWidget(display,windows,&windows->widget,PageSizes,"Select",
12627 "Select page geometry:",geometry);
12628 if (*geometry != '\0')
12629 image_info->page=GetPageGeometry(geometry);
12632 Apply image transforms.
12634 XSetCursorState(display,windows,MagickTrue);
12635 XCheckRefreshWindows(display,windows);
12636 save_image=CloneImage(image,0,0,MagickTrue,exception);
12637 if (save_image == (Image *) NULL)
12638 return(MagickFalse);
12639 (void) FormatLocaleString(geometry,MaxTextExtent,"%dx%d!",
12640 windows->image.ximage->width,windows->image.ximage->height);
12641 (void) TransformImage(&save_image,windows->image.crop_geometry,geometry,
12646 (void) CopyMagickString(save_image->filename,filename,MaxTextExtent);
12647 status=WriteImage(image_info,save_image,exception);
12648 if (IfMagickTrue(status) )
12649 image->taint=MagickFalse;
12650 save_image=DestroyImage(save_image);
12651 image_info=DestroyImageInfo(image_info);
12652 XSetCursorState(display,windows,MagickFalse);
12653 return(IsMagickTrue(status));
12657 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12661 + X S c r e e n E v e n t %
12665 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12667 % XScreenEvent() handles global events associated with the Pan and Magnify
12670 % The format of the XScreenEvent function is:
12672 % void XScreenEvent(Display *display,XWindows *windows,XEvent *event,
12673 % ExceptionInfo *exception)
12675 % A description of each parameter follows:
12677 % o display: Specifies a pointer to the Display structure; returned from
12680 % o windows: Specifies a pointer to a XWindows structure.
12682 % o event: Specifies a pointer to a X11 XEvent structure.
12684 % o exception: return any errors or warnings in this structure.
12688 #if defined(__cplusplus) || defined(c_plusplus)
12692 static int XPredicate(Display *magick_unused(display),XEvent *event,char *data)
12697 windows=(XWindows *) data;
12698 if ((event->type == ClientMessage) &&
12699 (event->xclient.window == windows->image.id))
12700 return(MagickFalse);
12701 return(MagickTrue);
12704 #if defined(__cplusplus) || defined(c_plusplus)
12708 static void XScreenEvent(Display *display,XWindows *windows,XEvent *event,
12709 ExceptionInfo *exception)
12715 (void) XIfEvent(display,event,XPredicate,(char *) windows);
12716 if (event->xany.window == windows->command.id)
12718 switch (event->type)
12721 case ButtonRelease:
12723 if ((event->xbutton.button == Button3) &&
12724 (event->xbutton.state & Mod1Mask))
12727 Convert Alt-Button3 to Button2.
12729 event->xbutton.button=Button2;
12730 event->xbutton.state&=(~Mod1Mask);
12732 if (event->xbutton.window == windows->backdrop.id)
12734 (void) XSetInputFocus(display,event->xbutton.window,RevertToParent,
12735 event->xbutton.time);
12738 if (event->xbutton.window == windows->pan.id)
12740 XPanImage(display,windows,event,exception);
12743 if (event->xbutton.window == windows->image.id)
12744 if (event->xbutton.button == Button2)
12747 Update magnified image.
12749 x=event->xbutton.x;
12750 y=event->xbutton.y;
12754 if (x >= (int) windows->image.width)
12755 x=(int) (windows->image.width-1);
12756 windows->magnify.x=(int) windows->image.x+x;
12760 if (y >= (int) windows->image.height)
12761 y=(int) (windows->image.height-1);
12762 windows->magnify.y=windows->image.y+y;
12763 if (IfMagickFalse(windows->magnify.mapped) )
12764 (void) XMapRaised(display,windows->magnify.id);
12765 XMakeMagnifyImage(display,windows,exception);
12766 if (event->type == ButtonRelease)
12767 (void) XWithdrawWindow(display,windows->info.id,
12768 windows->info.screen);
12773 case ClientMessage:
12776 If client window delete message, exit.
12778 if (event->xclient.message_type != windows->wm_protocols)
12780 if (*event->xclient.data.l != (long) windows->wm_delete_window)
12782 if (event->xclient.window == windows->magnify.id)
12784 (void) XWithdrawWindow(display,windows->magnify.id,
12785 windows->magnify.screen);
12790 case ConfigureNotify:
12792 if (event->xconfigure.window == windows->magnify.id)
12798 Magnify window has a new configuration.
12800 windows->magnify.width=(unsigned int) event->xconfigure.width;
12801 windows->magnify.height=(unsigned int) event->xconfigure.height;
12802 if (IfMagickFalse(windows->magnify.mapped) )
12805 while ((int) magnify <= event->xconfigure.width)
12807 while ((int) magnify <= event->xconfigure.height)
12810 if (((int) magnify != event->xconfigure.width) ||
12811 ((int) magnify != event->xconfigure.height))
12816 window_changes.width=(int) magnify;
12817 window_changes.height=(int) magnify;
12818 (void) XReconfigureWMWindow(display,windows->magnify.id,
12819 windows->magnify.screen,(unsigned int) (CWWidth | CWHeight),
12823 XMakeMagnifyImage(display,windows,exception);
12830 if (event->xexpose.window == windows->image.id)
12832 XRefreshWindow(display,&windows->image,event);
12835 if (event->xexpose.window == windows->pan.id)
12836 if (event->xexpose.count == 0)
12838 XDrawPanRectangle(display,windows);
12841 if (event->xexpose.window == windows->magnify.id)
12842 if (event->xexpose.count == 0)
12844 XMakeMagnifyImage(display,windows,exception);
12852 command[MaxTextExtent];
12857 if (event->xkey.window != windows->magnify.id)
12860 Respond to a user key press.
12862 (void) XLookupString((XKeyEvent *) &event->xkey,command,(int)
12863 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
12864 XMagnifyWindowCommand(display,windows,event->xkey.state,key_symbol,
12870 if (event->xmap.window == windows->magnify.id)
12872 windows->magnify.mapped=MagickTrue;
12873 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
12876 if (event->xmap.window == windows->info.id)
12878 windows->info.mapped=MagickTrue;
12885 while (XCheckMaskEvent(display,ButtonMotionMask,event)) ;
12886 if (event->xmotion.window == windows->image.id)
12887 if (IfMagickTrue(windows->magnify.mapped) )
12890 Update magnified image.
12892 x=event->xmotion.x;
12893 y=event->xmotion.y;
12897 if (x >= (int) windows->image.width)
12898 x=(int) (windows->image.width-1);
12899 windows->magnify.x=(int) windows->image.x+x;
12903 if (y >= (int) windows->image.height)
12904 y=(int) (windows->image.height-1);
12905 windows->magnify.y=windows->image.y+y;
12906 XMakeMagnifyImage(display,windows,exception);
12912 if (event->xunmap.window == windows->magnify.id)
12914 windows->magnify.mapped=MagickFalse;
12917 if (event->xunmap.window == windows->info.id)
12919 windows->info.mapped=MagickFalse;
12930 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12934 + X S e t C r o p G e o m e t r y %
12938 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12940 % XSetCropGeometry() accepts a cropping geometry relative to the Image window
12941 % and translates it to a cropping geometry relative to the image.
12943 % The format of the XSetCropGeometry method is:
12945 % void XSetCropGeometry(Display *display,XWindows *windows,
12946 % RectangleInfo *crop_info,Image *image)
12948 % A description of each parameter follows:
12950 % o display: Specifies a connection to an X server; returned from
12953 % o windows: Specifies a pointer to a XWindows structure.
12955 % o crop_info: A pointer to a RectangleInfo that defines a region of the
12956 % Image window to crop.
12958 % o image: the image.
12961 static void XSetCropGeometry(Display *display,XWindows *windows,
12962 RectangleInfo *crop_info,Image *image)
12965 text[MaxTextExtent];
12978 if (IfMagickTrue(windows->info.mapped) )
12981 Display info on cropping rectangle.
12983 (void) FormatLocaleString(text,MaxTextExtent," %.20gx%.20g%+.20g%+.20g",
12984 (double) crop_info->width,(double) crop_info->height,(double)
12985 crop_info->x,(double) crop_info->y);
12986 XInfoWidget(display,windows,text);
12989 Cropping geometry is relative to any previous crop geometry.
12993 width=(unsigned int) image->columns;
12994 height=(unsigned int) image->rows;
12995 if (windows->image.crop_geometry != (char *) NULL)
12996 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
12998 windows->image.crop_geometry=AcquireString((char *) NULL);
13000 Define the crop geometry string from the cropping rectangle.
13002 scale_factor=(double) width/windows->image.ximage->width;
13003 if (crop_info->x > 0)
13004 x+=(int) (scale_factor*crop_info->x+0.5);
13005 width=(unsigned int) (scale_factor*crop_info->width+0.5);
13008 scale_factor=(double) height/windows->image.ximage->height;
13009 if (crop_info->y > 0)
13010 y+=(int) (scale_factor*crop_info->y+0.5);
13011 height=(unsigned int) (scale_factor*crop_info->height+0.5);
13014 (void) FormatLocaleString(windows->image.crop_geometry,MaxTextExtent,
13015 "%ux%u%+d%+d",width,height,x,y);
13019 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13023 + X T i l e I m a g e %
13027 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13029 % XTileImage() loads or deletes a selected tile from a visual image directory.
13030 % The load or delete command is chosen from a menu.
13032 % The format of the XTileImage method is:
13034 % Image *XTileImage(Display *display,XResourceInfo *resource_info,
13035 % XWindows *windows,Image *image,XEvent *event,ExceptionInfo *exception)
13037 % A description of each parameter follows:
13039 % o tile_image: XTileImage reads or deletes the tile image
13040 % and returns it. A null image is returned if an error occurs.
13042 % o display: Specifies a connection to an X server; returned from
13045 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
13047 % o windows: Specifies a pointer to a XWindows structure.
13049 % o image: the image; returned from ReadImage.
13051 % o event: Specifies a pointer to a XEvent structure. If it is NULL,
13052 % the entire image is refreshed.
13054 % o exception: return any errors or warnings in this structure.
13057 static Image *XTileImage(Display *display,XResourceInfo *resource_info,
13058 XWindows *windows,Image *image,XEvent *event,ExceptionInfo *exception)
13071 static const ModeType
13082 command[MaxTextExtent],
13083 filename[MaxTextExtent];
13110 Tile image is relative to montage image configuration.
13114 width=(unsigned int) image->columns;
13115 height=(unsigned int) image->rows;
13116 if (windows->image.crop_geometry != (char *) NULL)
13117 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
13118 scale_factor=(double) width/windows->image.ximage->width;
13119 event->xbutton.x+=windows->image.x;
13120 event->xbutton.x=(int) (scale_factor*event->xbutton.x+x+0.5);
13121 scale_factor=(double) height/windows->image.ximage->height;
13122 event->xbutton.y+=windows->image.y;
13123 event->xbutton.y=(int) (scale_factor*event->xbutton.y+y+0.5);
13125 Determine size and location of each tile in the visual image directory.
13127 width=(unsigned int) image->columns;
13128 height=(unsigned int) image->rows;
13131 (void) XParseGeometry(image->montage,&x,&y,&width,&height);
13132 tile=((event->xbutton.y-y)/height)*(((int) image->columns-x)/width)+
13133 (event->xbutton.x-x)/width;
13137 Button press is outside any tile.
13139 (void) XBell(display,0);
13140 return((Image *) NULL);
13143 Determine file name from the tile directory.
13145 p=image->directory;
13146 for (i=tile; (i != 0) && (*p != '\0'); )
13155 Button press is outside any tile.
13157 (void) XBell(display,0);
13158 return((Image *) NULL);
13161 Select a command from the pop-up menu.
13163 id=XMenuWidget(display,windows,"Tile Verb",VerbMenu,command);
13165 return((Image *) NULL);
13167 while ((*q != '\n') && (*q != '\0'))
13169 (void) CopyMagickString(filename,p,(size_t) (q-p+1));
13171 Perform command for the selected tile.
13173 XSetCursorState(display,windows,MagickTrue);
13174 XCheckRefreshWindows(display,windows);
13175 tile_image=NewImageList();
13176 switch (TileCommands[id])
13178 case TileLoadCommand:
13183 XCheckRefreshWindows(display,windows);
13184 (void) CopyMagickString(resource_info->image_info->magick,"MIFF",
13186 (void) CopyMagickString(resource_info->image_info->filename,filename,
13188 tile_image=ReadImage(resource_info->image_info,exception);
13189 CatchException(exception);
13190 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
13193 case TileNextCommand:
13196 Display next image.
13198 XClientMessage(display,windows->image.id,windows->im_protocols,
13199 windows->im_next_image,CurrentTime);
13202 case TileFormerCommand:
13205 Display former image.
13207 XClientMessage(display,windows->image.id,windows->im_protocols,
13208 windows->im_former_image,CurrentTime);
13211 case TileDeleteCommand:
13216 if (IfMagickFalse(IsPathAccessible(filename)) )
13218 XNoticeWidget(display,windows,"Image file does not exist:",filename);
13221 status=XConfirmWidget(display,windows,"Really delete tile",filename);
13224 status=ShredFile(filename);
13225 if (IfMagickTrue(status) )
13227 XNoticeWidget(display,windows,"Unable to delete image file:",
13232 case TileUpdateCommand:
13248 Ensure all the images exist.
13251 GetPixelInfo(image,&pixel);
13252 for (p=image->directory; *p != '\0'; p++)
13258 while ((*q != '\n') && (*q != '\0'))
13260 (void) CopyMagickString(filename,p,(size_t) (q-p+1));
13262 if (IfMagickTrue(IsPathAccessible(filename)) )
13268 Overwrite tile with background color.
13270 x_offset=(int) (width*(tile % (((int) image->columns-x)/width))+x);
13271 y_offset=(int) (height*(tile/(((int) image->columns-x)/width))+y);
13272 image_view=AcquireAuthenticCacheView(image,exception);
13273 (void) GetOneCacheViewVirtualPixelInfo(image_view,0,0,&pixel,exception);
13274 for (i=0; i < (int) height; i++)
13276 s=GetCacheViewAuthenticPixels(image_view,(ssize_t) x_offset,(ssize_t)
13277 y_offset+i,width,1,exception);
13278 if (s == (Quantum *) NULL)
13280 for (j=0; j < (int) width; j++)
13282 SetPixelInfoPixel(image,&pixel,s);
13283 s+=GetPixelChannels(image);
13285 if (IfMagickFalse(SyncCacheViewAuthenticPixels(image_view,exception)) )
13288 image_view=DestroyCacheView(image_view);
13291 windows->image.window_changes.width=(int) image->columns;
13292 windows->image.window_changes.height=(int) image->rows;
13293 XConfigureImageColormap(display,resource_info,windows,image,exception);
13294 (void) XConfigureImage(display,resource_info,windows,image,exception);
13300 XSetCursorState(display,windows,MagickFalse);
13301 return(tile_image);
13305 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13309 + X T r a n s l a t e I m a g e %
13313 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13315 % XTranslateImage() translates the image within an Image window by one pixel
13316 % as specified by the key symbol. If the image has a montage string the
13317 % translation is respect to the width and height contained within the string.
13319 % The format of the XTranslateImage method is:
13321 % void XTranslateImage(Display *display,XWindows *windows,
13322 % Image *image,const KeySym key_symbol)
13324 % A description of each parameter follows:
13326 % o display: Specifies a connection to an X server; returned from
13329 % o windows: Specifies a pointer to a XWindows structure.
13331 % o image: the image.
13333 % o key_symbol: Specifies a KeySym which indicates which side of the image
13337 static void XTranslateImage(Display *display,XWindows *windows,
13338 Image *image,const KeySym key_symbol)
13341 text[MaxTextExtent];
13352 User specified a pan position offset.
13354 x_offset=windows->image.width;
13355 y_offset=windows->image.height;
13356 if (image->montage != (char *) NULL)
13357 (void) XParseGeometry(image->montage,&x,&y,&x_offset,&y_offset);
13358 switch ((int) key_symbol)
13363 windows->image.x=(int) windows->image.width/2;
13364 windows->image.y=(int) windows->image.height/2;
13370 windows->image.x-=x_offset;
13377 windows->image.y-=y_offset;
13383 windows->image.x+=x_offset;
13390 windows->image.y+=y_offset;
13397 Check boundary conditions.
13399 if (windows->image.x < 0)
13400 windows->image.x=0;
13402 if ((int) (windows->image.x+windows->image.width) >
13403 windows->image.ximage->width)
13404 windows->image.x=(int) windows->image.ximage->width-windows->image.width;
13405 if (windows->image.y < 0)
13406 windows->image.y=0;
13408 if ((int) (windows->image.y+windows->image.height) >
13409 windows->image.ximage->height)
13410 windows->image.y=(int) windows->image.ximage->height-windows->image.height;
13412 Refresh Image window.
13414 (void) FormatLocaleString(text,MaxTextExtent," %ux%u%+d%+d ",
13415 windows->image.width,windows->image.height,windows->image.x,
13417 XInfoWidget(display,windows,text);
13418 XCheckRefreshWindows(display,windows);
13419 XDrawPanRectangle(display,windows);
13420 XRefreshWindow(display,&windows->image,(XEvent *) NULL);
13421 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
13425 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13429 + X T r i m I m a g e %
13433 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13435 % XTrimImage() trims the edges from the Image window.
13437 % The format of the XTrimImage method is:
13439 % MagickBooleanType XTrimImage(Display *display,
13440 % XResourceInfo *resource_info,XWindows *windows,Image *image,
13441 % ExceptionInfo *exception)
13443 % A description of each parameter follows:
13445 % o display: Specifies a connection to an X server; returned from
13448 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
13450 % o windows: Specifies a pointer to a XWindows structure.
13452 % o image: the image.
13454 % o exception: return any errors or warnings in this structure.
13457 static MagickBooleanType XTrimImage(Display *display,
13458 XResourceInfo *resource_info,XWindows *windows,Image *image,
13459 ExceptionInfo *exception)
13473 Trim edges from image.
13475 XSetCursorState(display,windows,MagickTrue);
13476 XCheckRefreshWindows(display,windows);
13478 Crop the left edge.
13480 background=XGetPixel(windows->image.ximage,0,0);
13481 trim_info.width=(size_t) windows->image.ximage->width;
13482 for (x=0; x < windows->image.ximage->width; x++)
13484 for (y=0; y < windows->image.ximage->height; y++)
13486 pixel=XGetPixel(windows->image.ximage,x,y);
13487 if (pixel != background)
13490 if (y < windows->image.ximage->height)
13493 trim_info.x=(ssize_t) x;
13494 if (trim_info.x == (ssize_t) windows->image.ximage->width)
13496 XSetCursorState(display,windows,MagickFalse);
13497 return(MagickFalse);
13500 Crop the right edge.
13502 background=XGetPixel(windows->image.ximage,windows->image.ximage->width-1,0);
13503 for (x=windows->image.ximage->width-1; x != 0; x--)
13505 for (y=0; y < windows->image.ximage->height; y++)
13507 pixel=XGetPixel(windows->image.ximage,x,y);
13508 if (pixel != background)
13511 if (y < windows->image.ximage->height)
13514 trim_info.width=(size_t) (x-trim_info.x+1);
13518 background=XGetPixel(windows->image.ximage,0,0);
13519 trim_info.height=(size_t) windows->image.ximage->height;
13520 for (y=0; y < windows->image.ximage->height; y++)
13522 for (x=0; x < windows->image.ximage->width; x++)
13524 pixel=XGetPixel(windows->image.ximage,x,y);
13525 if (pixel != background)
13528 if (x < windows->image.ximage->width)
13531 trim_info.y=(ssize_t) y;
13533 Crop the bottom edge.
13535 background=XGetPixel(windows->image.ximage,0,windows->image.ximage->height-1);
13536 for (y=windows->image.ximage->height-1; y != 0; y--)
13538 for (x=0; x < windows->image.ximage->width; x++)
13540 pixel=XGetPixel(windows->image.ximage,x,y);
13541 if (pixel != background)
13544 if (x < windows->image.ximage->width)
13547 trim_info.height=(size_t) y-trim_info.y+1;
13548 if (((unsigned int) trim_info.width != windows->image.width) ||
13549 ((unsigned int) trim_info.height != windows->image.height))
13552 Reconfigure Image window as defined by the trimming rectangle.
13554 XSetCropGeometry(display,windows,&trim_info,image);
13555 windows->image.window_changes.width=(int) trim_info.width;
13556 windows->image.window_changes.height=(int) trim_info.height;
13557 (void) XConfigureImage(display,resource_info,windows,image,exception);
13559 XSetCursorState(display,windows,MagickFalse);
13560 return(MagickTrue);
13564 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13568 + X V i s u a l D i r e c t o r y I m a g e %
13572 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13574 % XVisualDirectoryImage() creates a Visual Image Directory.
13576 % The format of the XVisualDirectoryImage method is:
13578 % Image *XVisualDirectoryImage(Display *display,
13579 % XResourceInfo *resource_info,XWindows *windows,
13580 % ExceptionInfo *exception)
13582 % A description of each parameter follows:
13584 % o display: Specifies a connection to an X server; returned from
13587 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
13589 % o windows: Specifies a pointer to a XWindows structure.
13591 % o exception: return any errors or warnings in this structure.
13594 static Image *XVisualDirectoryImage(Display *display,
13595 XResourceInfo *resource_info,XWindows *windows,ExceptionInfo *exception)
13597 #define TileImageTag "Scale/Image"
13598 #define XClientName "montage"
13631 filename[MaxTextExtent] = "\0",
13632 filenames[MaxTextExtent] = "*";
13635 background_resources;
13638 Request file name from user.
13640 XFileBrowserWidget(display,windows,"Directory",filenames);
13641 if (*filenames == '\0')
13642 return((Image *) NULL);
13644 Expand the filenames.
13646 filelist=(char **) AcquireMagickMemory(sizeof(*filelist));
13647 if (filelist == (char **) NULL)
13649 ThrowXWindowException(ResourceLimitError,"MemoryAllocationFailed",
13651 return((Image *) NULL);
13654 filelist[0]=filenames;
13655 status=ExpandFilenames(&number_files,&filelist);
13656 if (IfMagickFalse(status) || (number_files == 0))
13658 if (number_files == 0)
13659 ThrowXWindowException(ImageError,"NoImagesWereFound",filenames)
13661 ThrowXWindowException(ResourceLimitError,"MemoryAllocationFailed",
13663 return((Image *) NULL);
13666 Set image background resources.
13668 background_resources=(*resource_info);
13669 background_resources.window_id=AcquireString("");
13670 (void) FormatLocaleString(background_resources.window_id,MaxTextExtent,
13671 "0x%lx",windows->image.id);
13672 background_resources.backdrop=MagickTrue;
13674 Read each image and convert them to a tile.
13676 backdrop=IsMagickTrue( (windows->visual_info->klass == TrueColor) ||
13677 (windows->visual_info->klass == DirectColor) );
13678 read_info=CloneImageInfo(resource_info->image_info);
13679 (void) SetImageOption(read_info,"jpeg:size","120x120");
13680 (void) CloneString(&read_info->size,DefaultTileGeometry);
13681 (void) SetImageInfoProgressMonitor(read_info,(MagickProgressMonitor) NULL,
13683 images=NewImageList();
13684 XSetCursorState(display,windows,MagickTrue);
13685 XCheckRefreshWindows(display,windows);
13686 for (i=0; i < (int) number_files; i++)
13688 (void) CopyMagickString(read_info->filename,filelist[i],MaxTextExtent);
13689 filelist[i]=DestroyString(filelist[i]);
13690 *read_info->magick='\0';
13691 next_image=ReadImage(read_info,exception);
13692 CatchException(exception);
13693 if (next_image != (Image *) NULL)
13695 (void) DeleteImageProperty(next_image,"label");
13696 (void) SetImageProperty(next_image,"label",InterpretImageProperties(
13697 read_info,next_image,DefaultTileLabel,exception),exception);
13698 (void) ParseRegionGeometry(next_image,read_info->size,&geometry,
13700 thumbnail_image=ThumbnailImage(next_image,geometry.width,
13701 geometry.height,exception);
13702 if (thumbnail_image != (Image *) NULL)
13704 next_image=DestroyImage(next_image);
13705 next_image=thumbnail_image;
13709 (void) XDisplayBackgroundImage(display,&background_resources,
13710 next_image,exception);
13711 XSetCursorState(display,windows,MagickTrue);
13713 AppendImageToList(&images,next_image);
13714 if (images->progress_monitor != (MagickProgressMonitor) NULL)
13719 proceed=SetImageProgress(images,LoadImageTag,(MagickOffsetType) i,
13720 (MagickSizeType) number_files);
13721 if (IfMagickFalse(proceed) )
13726 filelist=(char **) RelinquishMagickMemory(filelist);
13727 if (images == (Image *) NULL)
13729 read_info=DestroyImageInfo(read_info);
13730 XSetCursorState(display,windows,MagickFalse);
13731 ThrowXWindowException(ImageError,"NoImagesWereLoaded",filenames);
13732 return((Image *) NULL);
13735 Create the Visual Image Directory.
13737 montage_info=CloneMontageInfo(read_info,(MontageInfo *) NULL);
13738 montage_info->pointsize=10;
13739 if (resource_info->font != (char *) NULL)
13740 (void) CloneString(&montage_info->font,resource_info->font);
13741 (void) CopyMagickString(montage_info->filename,filename,MaxTextExtent);
13742 montage_image=MontageImageList(read_info,montage_info,GetFirstImageInList(
13743 images),exception);
13744 images=DestroyImageList(images);
13745 montage_info=DestroyMontageInfo(montage_info);
13746 read_info=DestroyImageInfo(read_info);
13747 XSetCursorState(display,windows,MagickFalse);
13748 if (montage_image == (Image *) NULL)
13749 return(montage_image);
13750 XClientMessage(display,windows->image.id,windows->im_protocols,
13751 windows->im_next_image,CurrentTime);
13752 return(montage_image);
13756 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13760 % X D i s p l a y B a c k g r o u n d I m a g e %
13764 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13766 % XDisplayBackgroundImage() displays an image in the background of a window.
13768 % The format of the XDisplayBackgroundImage method is:
13770 % MagickBooleanType XDisplayBackgroundImage(Display *display,
13771 % XResourceInfo *resource_info,Image *image,ExceptionInfo *exception)
13773 % A description of each parameter follows:
13775 % o display: Specifies a connection to an X server; returned from
13778 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
13780 % o image: the image.
13782 % o exception: return any errors or warnings in this structure.
13785 MagickExport MagickBooleanType XDisplayBackgroundImage(Display *display,
13786 XResourceInfo *resource_info,Image *image,ExceptionInfo *exception)
13789 geometry[MaxTextExtent],
13790 visual_type[MaxTextExtent];
13803 static XStandardColormap
13807 *visual_info = (XVisualInfo *) NULL;
13828 Determine target window.
13830 assert(image != (Image *) NULL);
13831 assert(image->signature == MagickSignature);
13832 if (IfMagickTrue(image->debug) )
13833 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
13834 resources=(*resource_info);
13835 window_info.id=(Window) NULL;
13836 root_window=XRootWindow(display,XDefaultScreen(display));
13837 if (LocaleCompare(resources.window_id,"root") == 0)
13838 window_info.id=root_window;
13841 if (isdigit((int) ((unsigned char) *resources.window_id)) != 0)
13842 window_info.id=XWindowByID(display,root_window,
13843 (Window) strtol((char *) resources.window_id,(char **) NULL,0));
13844 if (window_info.id == (Window) NULL)
13845 window_info.id=XWindowByName(display,root_window,resources.window_id);
13847 if (window_info.id == (Window) NULL)
13849 ThrowXWindowException(XServerError,"NoWindowWithSpecifiedIDExists",
13850 resources.window_id);
13851 return(MagickFalse);
13854 Determine window visual id.
13856 window_attributes.width=XDisplayWidth(display,XDefaultScreen(display));
13857 window_attributes.height=XDisplayHeight(display,XDefaultScreen(display));
13858 (void) CopyMagickString(visual_type,"default",MaxTextExtent);
13859 status=XGetWindowAttributes(display,window_info.id,&window_attributes);
13861 (void) FormatLocaleString(visual_type,MaxTextExtent,"0x%lx",
13862 XVisualIDFromVisual(window_attributes.visual));
13863 if (visual_info == (XVisualInfo *) NULL)
13866 Allocate standard colormap.
13868 map_info=XAllocStandardColormap();
13869 if (map_info == (XStandardColormap *) NULL)
13870 ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
13872 map_info->colormap=(Colormap) NULL;
13873 pixel.pixels=(unsigned long *) NULL;
13875 Initialize visual info.
13877 resources.map_type=(char *) NULL;
13878 resources.visual_type=visual_type;
13879 visual_info=XBestVisualInfo(display,map_info,&resources);
13880 if (visual_info == (XVisualInfo *) NULL)
13881 ThrowXWindowFatalException(XServerFatalError,"UnableToGetVisual",
13882 resources.visual_type);
13884 Initialize window info.
13886 window_info.ximage=(XImage *) NULL;
13887 window_info.matte_image=(XImage *) NULL;
13888 window_info.pixmap=(Pixmap) NULL;
13889 window_info.matte_pixmap=(Pixmap) NULL;
13892 Free previous root colors.
13894 if (window_info.id == root_window)
13895 (void) XDestroyWindowColors(display,root_window);
13897 Initialize Standard Colormap.
13899 resources.colormap=SharedColormap;
13900 XMakeStandardColormap(display,visual_info,&resources,image,map_info,&pixel,
13903 Graphic context superclass.
13905 context_values.background=pixel.background_color.pixel;
13906 context_values.foreground=pixel.foreground_color.pixel;
13907 pixel.annotate_context=XCreateGC(display,window_info.id,
13908 (size_t) (GCBackground | GCForeground),&context_values);
13909 if (pixel.annotate_context == (GC) NULL)
13910 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
13913 Initialize Image window attributes.
13915 window_info.name=AcquireString("\0");
13916 window_info.icon_name=AcquireString("\0");
13917 XGetWindowInfo(display,visual_info,map_info,&pixel,(XFontStruct *) NULL,
13918 &resources,&window_info);
13920 Create the X image.
13922 window_info.width=(unsigned int) image->columns;
13923 window_info.height=(unsigned int) image->rows;
13924 if ((image->columns != window_info.width) ||
13925 (image->rows != window_info.height))
13926 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
13928 (void) FormatLocaleString(geometry,MaxTextExtent,"%ux%u+0+0>",
13929 window_attributes.width,window_attributes.height);
13930 geometry_info.width=window_info.width;
13931 geometry_info.height=window_info.height;
13932 geometry_info.x=(ssize_t) window_info.x;
13933 geometry_info.y=(ssize_t) window_info.y;
13934 (void) ParseMetaGeometry(geometry,&geometry_info.x,&geometry_info.y,
13935 &geometry_info.width,&geometry_info.height);
13936 window_info.width=(unsigned int) geometry_info.width;
13937 window_info.height=(unsigned int) geometry_info.height;
13938 window_info.x=(int) geometry_info.x;
13939 window_info.y=(int) geometry_info.y;
13940 status=XMakeImage(display,&resources,&window_info,image,window_info.width,
13941 window_info.height,exception);
13942 if (IfMagickFalse(status) )
13943 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
13947 if (IfMagickTrue(image->debug) )
13949 (void) LogMagickEvent(X11Event,GetMagickModule(),
13950 "Image: %s[%.20g] %.20gx%.20g ",image->filename,(double) image->scene,
13951 (double) image->columns,(double) image->rows);
13952 if (image->colors != 0)
13953 (void) LogMagickEvent(X11Event,GetMagickModule(),"%.20gc ",(double)
13955 (void) LogMagickEvent(X11Event,GetMagickModule(),"%s",image->magick);
13958 Adjust image dimensions as specified by backdrop or geometry options.
13960 width=(int) window_info.width;
13961 height=(int) window_info.height;
13962 if (IfMagickTrue(resources.backdrop) )
13965 Center image on window.
13967 window_info.x=(window_attributes.width/2)-
13968 (window_info.ximage->width/2);
13969 window_info.y=(window_attributes.height/2)-
13970 (window_info.ximage->height/2);
13971 width=window_attributes.width;
13972 height=window_attributes.height;
13974 if ((resources.image_geometry != (char *) NULL) &&
13975 (*resources.image_geometry != '\0'))
13978 default_geometry[MaxTextExtent];
13988 User specified geometry.
13990 size_hints=XAllocSizeHints();
13991 if (size_hints == (XSizeHints *) NULL)
13992 ThrowXWindowFatalException(ResourceLimitFatalError,
13993 "MemoryAllocationFailed",image->filename);
13994 size_hints->flags=0L;
13995 (void) FormatLocaleString(default_geometry,MaxTextExtent,"%dx%d",
13997 flags=XWMGeometry(display,visual_info->screen,resources.image_geometry,
13998 default_geometry,window_info.border_width,size_hints,&window_info.x,
13999 &window_info.y,&width,&height,&gravity);
14000 if (flags & (XValue | YValue))
14002 width=window_attributes.width;
14003 height=window_attributes.height;
14005 (void) XFree((void *) size_hints);
14008 Create the X pixmap.
14010 window_info.pixmap=XCreatePixmap(display,window_info.id,(unsigned int) width,
14011 (unsigned int) height,window_info.depth);
14012 if (window_info.pixmap == (Pixmap) NULL)
14013 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXPixmap",
14016 Display pixmap on the window.
14018 if (((unsigned int) width > window_info.width) ||
14019 ((unsigned int) height > window_info.height))
14020 (void) XFillRectangle(display,window_info.pixmap,
14021 window_info.annotate_context,0,0,(unsigned int) width,
14022 (unsigned int) height);
14023 (void) XPutImage(display,window_info.pixmap,window_info.annotate_context,
14024 window_info.ximage,0,0,window_info.x,window_info.y,(unsigned int)
14025 window_info.width,(unsigned int) window_info.height);
14026 (void) XSetWindowBackgroundPixmap(display,window_info.id,window_info.pixmap);
14027 (void) XClearWindow(display,window_info.id);
14028 delay=1000*image->delay/MagickMax(image->ticks_per_second,1L);
14029 XDelay(display,delay == 0UL ? 10UL : delay);
14030 (void) XSync(display,MagickFalse);
14031 return(IsMagickTrue(window_info.id == root_window));
14035 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
14039 + X D i s p l a y I m a g e %
14043 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
14045 % XDisplayImage() displays an image via X11. A new image is created and
14046 % returned if the user interactively transforms the displayed image.
14048 % The format of the XDisplayImage method is:
14050 % Image *XDisplayImage(Display *display,XResourceInfo *resource_info,
14051 % char **argv,int argc,Image **image,size_t *state,
14052 % ExceptionInfo *exception)
14054 % A description of each parameter follows:
14056 % o nexus: Method XDisplayImage returns an image when the
14057 % user chooses 'Open Image' from the command menu or picks a tile
14058 % from the image directory. Otherwise a null image is returned.
14060 % o display: Specifies a connection to an X server; returned from
14063 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
14065 % o argv: Specifies the application's argument list.
14067 % o argc: Specifies the number of arguments.
14069 % o image: Specifies an address to an address of an Image structure;
14071 % o exception: return any errors or warnings in this structure.
14074 MagickExport Image *XDisplayImage(Display *display,XResourceInfo *resource_info,
14075 char **argv,int argc,Image **image,size_t *state,ExceptionInfo *exception)
14077 #define MagnifySize 256 /* must be a power of 2 */
14078 #define MagickMenus 10
14079 #define MagickTitle "Commands"
14106 "Visual Directory...",
14152 "Contrast Stretch...",
14153 "Sigmoidal Contrast...",
14187 "Charcoal Draw...",
14201 "Region of Interest...",
14204 *MiscellanyMenu[] =
14219 "Browse Documentation",
14246 **Menus[MagickMenus] =
14284 VisualDirectoryCommand,
14298 OriginalSizeCommand,
14305 TransformCommands[] =
14311 RotateRightCommand,
14318 EnhanceCommands[] =
14326 ContrastStretchCommand,
14327 SigmoidalContrastCommand,
14335 EffectsCommands[] =
14339 ReduceNoiseCommand,
14359 CharcoalDrawCommand
14361 ImageEditCommands[] =
14372 RegionofInterestCommand
14374 MiscellanyCommands[] =
14378 ShowPreviewCommand,
14379 ShowHistogramCommand,
14388 BrowseDocumentationCommand,
14391 ShortCutsCommands[] =
14403 VirtualCommands[] =
14412 *Commands[MagickMenus] =
14422 MiscellanyCommands,
14427 command[MaxTextExtent],
14429 geometry[MaxTextExtent],
14430 resource_name[MaxTextExtent];
14457 working_directory[MaxTextExtent];
14463 *magick_windows[MaxXWindows];
14465 static unsigned int
14525 assert(image != (Image **) NULL);
14526 assert((*image)->signature == MagickSignature);
14527 if (IfMagickTrue((*image)->debug) )
14528 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",(*image)->filename);
14529 display_image=(*image);
14530 warning_handler=(WarningHandler) NULL;
14531 windows=XSetWindows((XWindows *) ~0);
14532 if (windows != (XWindows *) NULL)
14537 if (*working_directory == '\0')
14538 (void) CopyMagickString(working_directory,".",MaxTextExtent);
14539 status=chdir(working_directory);
14541 (void) ThrowMagickException(exception,GetMagickModule(),FileOpenError,
14542 "UnableToOpenFile","%s",working_directory);
14543 warning_handler=resource_info->display_warnings ?
14544 SetErrorHandler(XWarning) : SetErrorHandler((ErrorHandler) NULL);
14545 warning_handler=resource_info->display_warnings ?
14546 SetWarningHandler(XWarning) : SetWarningHandler((WarningHandler) NULL);
14551 Allocate windows structure.
14553 resource_info->colors=display_image->colors;
14554 windows=XSetWindows(XInitializeWindows(display,resource_info));
14555 if (windows == (XWindows *) NULL)
14556 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateWindow",
14557 (*image)->filename);
14559 Initialize window id's.
14562 magick_windows[number_windows++]=(&windows->icon);
14563 magick_windows[number_windows++]=(&windows->backdrop);
14564 magick_windows[number_windows++]=(&windows->image);
14565 magick_windows[number_windows++]=(&windows->info);
14566 magick_windows[number_windows++]=(&windows->command);
14567 magick_windows[number_windows++]=(&windows->widget);
14568 magick_windows[number_windows++]=(&windows->popup);
14569 magick_windows[number_windows++]=(&windows->magnify);
14570 magick_windows[number_windows++]=(&windows->pan);
14571 for (i=0; i < (int) number_windows; i++)
14572 magick_windows[i]->id=(Window) NULL;
14577 Initialize font info.
14579 if (windows->font_info != (XFontStruct *) NULL)
14580 (void) XFreeFont(display,windows->font_info);
14581 windows->font_info=XBestFont(display,resource_info,MagickFalse);
14582 if (windows->font_info == (XFontStruct *) NULL)
14583 ThrowXWindowFatalException(XServerFatalError,"UnableToLoadFont",
14584 resource_info->font);
14586 Initialize Standard Colormap.
14588 map_info=windows->map_info;
14589 icon_map=windows->icon_map;
14590 visual_info=windows->visual_info;
14591 icon_visual=windows->icon_visual;
14592 pixel=windows->pixel_info;
14593 icon_pixel=windows->icon_pixel;
14594 font_info=windows->font_info;
14595 icon_resources=windows->icon_resources;
14596 class_hints=windows->class_hints;
14597 manager_hints=windows->manager_hints;
14598 root_window=XRootWindow(display,visual_info->screen);
14599 nexus=NewImageList();
14600 if (IfMagickTrue(display_image->debug) )
14602 (void) LogMagickEvent(X11Event,GetMagickModule(),
14603 "Image: %s[%.20g] %.20gx%.20g ",display_image->filename,
14604 (double) display_image->scene,(double) display_image->columns,
14605 (double) display_image->rows);
14606 if (display_image->colors != 0)
14607 (void) LogMagickEvent(X11Event,GetMagickModule(),"%.20gc ",(double)
14608 display_image->colors);
14609 (void) LogMagickEvent(X11Event,GetMagickModule(),"%s",
14610 display_image->magick);
14612 XMakeStandardColormap(display,visual_info,resource_info,display_image,
14613 map_info,pixel,exception);
14614 display_image->taint=MagickFalse;
14616 Initialize graphic context.
14618 windows->context.id=(Window) NULL;
14619 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
14620 resource_info,&windows->context);
14621 (void) CloneString(&class_hints->res_name,resource_info->client_name);
14622 (void) CloneString(&class_hints->res_class,resource_info->client_name);
14623 class_hints->res_class[0]=(char) toupper((int) class_hints->res_class[0]);
14624 manager_hints->flags=InputHint | StateHint;
14625 manager_hints->input=MagickFalse;
14626 manager_hints->initial_state=WithdrawnState;
14627 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14628 &windows->context);
14629 if (IfMagickTrue(display_image->debug) )
14630 (void) LogMagickEvent(X11Event,GetMagickModule(),
14631 "Window id: 0x%lx (context)",windows->context.id);
14632 context_values.background=pixel->background_color.pixel;
14633 context_values.font=font_info->fid;
14634 context_values.foreground=pixel->foreground_color.pixel;
14635 context_values.graphics_exposures=MagickFalse;
14636 context_mask=(MagickStatusType)
14637 (GCBackground | GCFont | GCForeground | GCGraphicsExposures);
14638 if (pixel->annotate_context != (GC) NULL)
14639 (void) XFreeGC(display,pixel->annotate_context);
14640 pixel->annotate_context=XCreateGC(display,windows->context.id,
14641 context_mask,&context_values);
14642 if (pixel->annotate_context == (GC) NULL)
14643 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
14644 display_image->filename);
14645 context_values.background=pixel->depth_color.pixel;
14646 if (pixel->widget_context != (GC) NULL)
14647 (void) XFreeGC(display,pixel->widget_context);
14648 pixel->widget_context=XCreateGC(display,windows->context.id,context_mask,
14650 if (pixel->widget_context == (GC) NULL)
14651 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
14652 display_image->filename);
14653 context_values.background=pixel->foreground_color.pixel;
14654 context_values.foreground=pixel->background_color.pixel;
14655 context_values.plane_mask=context_values.background ^
14656 context_values.foreground;
14657 if (pixel->highlight_context != (GC) NULL)
14658 (void) XFreeGC(display,pixel->highlight_context);
14659 pixel->highlight_context=XCreateGC(display,windows->context.id,
14660 (size_t) (context_mask | GCPlaneMask),&context_values);
14661 if (pixel->highlight_context == (GC) NULL)
14662 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
14663 display_image->filename);
14664 (void) XDestroyWindow(display,windows->context.id);
14666 Initialize icon window.
14668 XGetWindowInfo(display,icon_visual,icon_map,icon_pixel,(XFontStruct *) NULL,
14669 icon_resources,&windows->icon);
14670 windows->icon.geometry=resource_info->icon_geometry;
14671 XBestIconSize(display,&windows->icon,display_image);
14672 windows->icon.attributes.colormap=XDefaultColormap(display,
14673 icon_visual->screen);
14674 windows->icon.attributes.event_mask=ExposureMask | StructureNotifyMask;
14675 manager_hints->flags=InputHint | StateHint;
14676 manager_hints->input=MagickFalse;
14677 manager_hints->initial_state=IconicState;
14678 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14680 if (IfMagickTrue(display_image->debug) )
14681 (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (icon)",
14684 Initialize graphic context for icon window.
14686 if (icon_pixel->annotate_context != (GC) NULL)
14687 (void) XFreeGC(display,icon_pixel->annotate_context);
14688 context_values.background=icon_pixel->background_color.pixel;
14689 context_values.foreground=icon_pixel->foreground_color.pixel;
14690 icon_pixel->annotate_context=XCreateGC(display,windows->icon.id,
14691 (size_t) (GCBackground | GCForeground),&context_values);
14692 if (icon_pixel->annotate_context == (GC) NULL)
14693 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
14694 display_image->filename);
14695 windows->icon.annotate_context=icon_pixel->annotate_context;
14697 Initialize Image window.
14699 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,resource_info,
14701 windows->image.shape=MagickTrue; /* non-rectangular shape hint */
14702 if (IfMagickFalse(resource_info->use_shared_memory) )
14703 windows->image.shared_memory=MagickFalse;
14704 if ((resource_info->title != (char *) NULL) && !(*state & MontageImageState))
14709 title=InterpretImageProperties(resource_info->image_info,display_image,
14710 resource_info->title,exception);
14711 (void) CopyMagickString(windows->image.name,title,MaxTextExtent);
14712 (void) CopyMagickString(windows->image.icon_name,title,MaxTextExtent);
14713 title=DestroyString(title);
14718 filename[MaxTextExtent];
14721 Window name is the base of the filename.
14723 GetPathComponent(display_image->magick_filename,TailPath,filename);
14724 if (display_image->scene == 0)
14725 (void) FormatLocaleString(windows->image.name,MaxTextExtent,
14726 "%s: %s",MagickPackageName,filename);
14728 (void) FormatLocaleString(windows->image.name,MaxTextExtent,
14729 "%s: %s[scene: %.20g frames: %.20g]",MagickPackageName,filename,
14730 (double) display_image->scene,(double) GetImageListLength(
14732 (void) CopyMagickString(windows->image.icon_name,filename,MaxTextExtent);
14734 if (resource_info->immutable)
14735 windows->image.immutable=MagickTrue;
14736 windows->image.use_pixmap=resource_info->use_pixmap;
14737 windows->image.geometry=resource_info->image_geometry;
14738 (void) FormatLocaleString(geometry,MaxTextExtent,"%ux%u+0+0>!",
14739 XDisplayWidth(display,visual_info->screen),
14740 XDisplayHeight(display,visual_info->screen));
14741 geometry_info.width=display_image->columns;
14742 geometry_info.height=display_image->rows;
14745 (void) ParseMetaGeometry(geometry,&geometry_info.x,&geometry_info.y,
14746 &geometry_info.width,&geometry_info.height);
14747 windows->image.width=(unsigned int) geometry_info.width;
14748 windows->image.height=(unsigned int) geometry_info.height;
14749 windows->image.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
14750 ButtonReleaseMask | EnterWindowMask | ExposureMask | KeyPressMask |
14751 KeyReleaseMask | LeaveWindowMask | OwnerGrabButtonMask |
14752 PropertyChangeMask | StructureNotifyMask | SubstructureNotifyMask;
14753 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
14754 resource_info,&windows->backdrop);
14755 if ((resource_info->backdrop) || (windows->backdrop.id != (Window) NULL))
14758 Initialize backdrop window.
14760 windows->backdrop.x=0;
14761 windows->backdrop.y=0;
14762 (void) CloneString(&windows->backdrop.name,"Backdrop");
14763 windows->backdrop.flags=(size_t) (USSize | USPosition);
14764 windows->backdrop.width=(unsigned int)
14765 XDisplayWidth(display,visual_info->screen);
14766 windows->backdrop.height=(unsigned int)
14767 XDisplayHeight(display,visual_info->screen);
14768 windows->backdrop.border_width=0;
14769 windows->backdrop.immutable=MagickTrue;
14770 windows->backdrop.attributes.do_not_propagate_mask=ButtonPressMask |
14772 windows->backdrop.attributes.event_mask=ButtonPressMask | KeyPressMask |
14773 StructureNotifyMask;
14774 manager_hints->flags=IconWindowHint | InputHint | StateHint;
14775 manager_hints->icon_window=windows->icon.id;
14776 manager_hints->input=MagickTrue;
14777 manager_hints->initial_state=resource_info->iconic ? IconicState :
14779 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14780 &windows->backdrop);
14781 if (IfMagickTrue(display_image->debug) )
14782 (void) LogMagickEvent(X11Event,GetMagickModule(),
14783 "Window id: 0x%lx (backdrop)",windows->backdrop.id);
14784 (void) XMapWindow(display,windows->backdrop.id);
14785 (void) XClearWindow(display,windows->backdrop.id);
14786 if (windows->image.id != (Window) NULL)
14788 (void) XDestroyWindow(display,windows->image.id);
14789 windows->image.id=(Window) NULL;
14792 Position image in the center the backdrop.
14794 windows->image.flags|=USPosition;
14795 windows->image.x=(XDisplayWidth(display,visual_info->screen)/2)-
14796 (windows->image.width/2);
14797 windows->image.y=(XDisplayHeight(display,visual_info->screen)/2)-
14798 (windows->image.height/2);
14800 manager_hints->flags=IconWindowHint | InputHint | StateHint;
14801 manager_hints->icon_window=windows->icon.id;
14802 manager_hints->input=MagickTrue;
14803 manager_hints->initial_state=resource_info->iconic ? IconicState :
14805 if (windows->group_leader.id != (Window) NULL)
14810 manager_hints->flags|=WindowGroupHint;
14811 manager_hints->window_group=windows->group_leader.id;
14812 (void) XSelectInput(display,windows->group_leader.id,StructureNotifyMask);
14813 if (IfMagickTrue(display_image->debug) )
14814 (void) LogMagickEvent(X11Event,GetMagickModule(),
14815 "Window id: 0x%lx (group leader)",windows->group_leader.id);
14817 XMakeWindow(display,
14818 (Window) (resource_info->backdrop ? windows->backdrop.id : root_window),
14819 argv,argc,class_hints,manager_hints,&windows->image);
14820 (void) XChangeProperty(display,windows->image.id,windows->im_protocols,
14821 XA_STRING,8,PropModeReplace,(unsigned char *) NULL,0);
14822 if (windows->group_leader.id != (Window) NULL)
14823 (void) XSetTransientForHint(display,windows->image.id,
14824 windows->group_leader.id);
14825 if (IfMagickTrue(display_image->debug) )
14826 (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (image)",
14827 windows->image.id);
14829 Initialize Info widget.
14831 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,resource_info,
14833 (void) CloneString(&windows->info.name,"Info");
14834 (void) CloneString(&windows->info.icon_name,"Info");
14835 windows->info.border_width=1;
14838 windows->info.flags|=PPosition;
14839 windows->info.attributes.win_gravity=UnmapGravity;
14840 windows->info.attributes.event_mask=ButtonPressMask | ExposureMask |
14841 StructureNotifyMask;
14842 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
14843 manager_hints->input=MagickFalse;
14844 manager_hints->initial_state=NormalState;
14845 manager_hints->window_group=windows->image.id;
14846 XMakeWindow(display,windows->image.id,argv,argc,class_hints,manager_hints,
14848 windows->info.highlight_stipple=XCreateBitmapFromData(display,
14849 windows->info.id,(char *) HighlightBitmap,HighlightWidth,HighlightHeight);
14850 windows->info.shadow_stipple=XCreateBitmapFromData(display,
14851 windows->info.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
14852 (void) XSetTransientForHint(display,windows->info.id,windows->image.id);
14853 if (IfMagickTrue(windows->image.mapped) )
14854 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
14855 if (IfMagickTrue(display_image->debug) )
14856 (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (info)",
14859 Initialize Command widget.
14861 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
14862 resource_info,&windows->command);
14863 windows->command.data=MagickMenus;
14864 (void) XCommandWidget(display,windows,CommandMenu,(XEvent *) NULL);
14865 (void) FormatLocaleString(resource_name,MaxTextExtent,"%s.command",
14866 resource_info->client_name);
14867 windows->command.geometry=XGetResourceClass(resource_info->resource_database,
14868 resource_name,"geometry",(char *) NULL);
14869 (void) CloneString(&windows->command.name,MagickTitle);
14870 windows->command.border_width=0;
14871 windows->command.flags|=PPosition;
14872 windows->command.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
14873 ButtonReleaseMask | EnterWindowMask | ExposureMask | LeaveWindowMask |
14874 OwnerGrabButtonMask | StructureNotifyMask;
14875 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
14876 manager_hints->input=MagickTrue;
14877 manager_hints->initial_state=NormalState;
14878 manager_hints->window_group=windows->image.id;
14879 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14880 &windows->command);
14881 windows->command.highlight_stipple=XCreateBitmapFromData(display,
14882 windows->command.id,(char *) HighlightBitmap,HighlightWidth,
14884 windows->command.shadow_stipple=XCreateBitmapFromData(display,
14885 windows->command.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
14886 (void) XSetTransientForHint(display,windows->command.id,windows->image.id);
14887 if (IfMagickTrue(windows->command.mapped) )
14888 (void) XMapRaised(display,windows->command.id);
14889 if (IfMagickTrue(display_image->debug) )
14890 (void) LogMagickEvent(X11Event,GetMagickModule(),
14891 "Window id: 0x%lx (command)",windows->command.id);
14893 Initialize Widget window.
14895 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
14896 resource_info,&windows->widget);
14897 (void) FormatLocaleString(resource_name,MaxTextExtent,"%s.widget",
14898 resource_info->client_name);
14899 windows->widget.geometry=XGetResourceClass(resource_info->resource_database,
14900 resource_name,"geometry",(char *) NULL);
14901 windows->widget.border_width=0;
14902 windows->widget.flags|=PPosition;
14903 windows->widget.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
14904 ButtonReleaseMask | EnterWindowMask | ExposureMask | KeyPressMask |
14905 KeyReleaseMask | LeaveWindowMask | OwnerGrabButtonMask |
14906 StructureNotifyMask;
14907 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
14908 manager_hints->input=MagickTrue;
14909 manager_hints->initial_state=NormalState;
14910 manager_hints->window_group=windows->image.id;
14911 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14913 windows->widget.highlight_stipple=XCreateBitmapFromData(display,
14914 windows->widget.id,(char *) HighlightBitmap,HighlightWidth,HighlightHeight);
14915 windows->widget.shadow_stipple=XCreateBitmapFromData(display,
14916 windows->widget.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
14917 (void) XSetTransientForHint(display,windows->widget.id,windows->image.id);
14918 if (IfMagickTrue(display_image->debug) )
14919 (void) LogMagickEvent(X11Event,GetMagickModule(),
14920 "Window id: 0x%lx (widget)",windows->widget.id);
14922 Initialize popup window.
14924 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
14925 resource_info,&windows->popup);
14926 windows->popup.border_width=0;
14927 windows->popup.flags|=PPosition;
14928 windows->popup.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
14929 ButtonReleaseMask | EnterWindowMask | ExposureMask | KeyPressMask |
14930 KeyReleaseMask | LeaveWindowMask | StructureNotifyMask;
14931 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
14932 manager_hints->input=MagickTrue;
14933 manager_hints->initial_state=NormalState;
14934 manager_hints->window_group=windows->image.id;
14935 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14937 windows->popup.highlight_stipple=XCreateBitmapFromData(display,
14938 windows->popup.id,(char *) HighlightBitmap,HighlightWidth,HighlightHeight);
14939 windows->popup.shadow_stipple=XCreateBitmapFromData(display,
14940 windows->popup.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
14941 (void) XSetTransientForHint(display,windows->popup.id,windows->image.id);
14942 if (IfMagickTrue(display_image->debug) )
14943 (void) LogMagickEvent(X11Event,GetMagickModule(),
14944 "Window id: 0x%lx (pop up)",windows->popup.id);
14946 Initialize Magnify window and cursor.
14948 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
14949 resource_info,&windows->magnify);
14950 if (IfMagickFalse(resource_info->use_shared_memory) )
14951 windows->magnify.shared_memory=MagickFalse;
14952 (void) FormatLocaleString(resource_name,MaxTextExtent,"%s.magnify",
14953 resource_info->client_name);
14954 windows->magnify.geometry=XGetResourceClass(resource_info->resource_database,
14955 resource_name,"geometry",(char *) NULL);
14956 (void) FormatLocaleString(windows->magnify.name,MaxTextExtent,"Magnify %uX",
14957 resource_info->magnify);
14958 if (windows->magnify.cursor != (Cursor) NULL)
14959 (void) XFreeCursor(display,windows->magnify.cursor);
14960 windows->magnify.cursor=XMakeCursor(display,windows->image.id,
14961 map_info->colormap,resource_info->background_color,
14962 resource_info->foreground_color);
14963 if (windows->magnify.cursor == (Cursor) NULL)
14964 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateCursor",
14965 display_image->filename);
14966 windows->magnify.width=MagnifySize;
14967 windows->magnify.height=MagnifySize;
14968 windows->magnify.flags|=PPosition;
14969 windows->magnify.min_width=MagnifySize;
14970 windows->magnify.min_height=MagnifySize;
14971 windows->magnify.width_inc=MagnifySize;
14972 windows->magnify.height_inc=MagnifySize;
14973 windows->magnify.data=resource_info->magnify;
14974 windows->magnify.attributes.cursor=windows->magnify.cursor;
14975 windows->magnify.attributes.event_mask=ButtonPressMask | ButtonReleaseMask |
14976 ExposureMask | KeyPressMask | KeyReleaseMask | OwnerGrabButtonMask |
14977 StructureNotifyMask;
14978 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
14979 manager_hints->input=MagickTrue;
14980 manager_hints->initial_state=NormalState;
14981 manager_hints->window_group=windows->image.id;
14982 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14983 &windows->magnify);
14984 if (IfMagickTrue(display_image->debug) )
14985 (void) LogMagickEvent(X11Event,GetMagickModule(),
14986 "Window id: 0x%lx (magnify)",windows->magnify.id);
14987 (void) XSetTransientForHint(display,windows->magnify.id,windows->image.id);
14989 Initialize panning window.
14991 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
14992 resource_info,&windows->pan);
14993 (void) CloneString(&windows->pan.name,"Pan Icon");
14994 windows->pan.width=windows->icon.width;
14995 windows->pan.height=windows->icon.height;
14996 (void) FormatLocaleString(resource_name,MaxTextExtent,"%s.pan",
14997 resource_info->client_name);
14998 windows->pan.geometry=XGetResourceClass(resource_info->resource_database,
14999 resource_name,"geometry",(char *) NULL);
15000 (void) XParseGeometry(windows->pan.geometry,&windows->pan.x,&windows->pan.y,
15001 &windows->pan.width,&windows->pan.height);
15002 windows->pan.flags|=PPosition;
15003 windows->pan.immutable=MagickTrue;
15004 windows->pan.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
15005 ButtonReleaseMask | ExposureMask | KeyPressMask | KeyReleaseMask |
15006 StructureNotifyMask;
15007 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
15008 manager_hints->input=MagickFalse;
15009 manager_hints->initial_state=NormalState;
15010 manager_hints->window_group=windows->image.id;
15011 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
15013 if (IfMagickTrue(display_image->debug) )
15014 (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (pan)",
15016 (void) XSetTransientForHint(display,windows->pan.id,windows->image.id);
15017 if (IfMagickTrue(windows->info.mapped) )
15018 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
15019 if (IfMagickFalse(windows->image.mapped) ||
15020 (windows->backdrop.id != (Window) NULL))
15021 (void) XMapWindow(display,windows->image.id);
15023 Set our progress monitor and warning handlers.
15025 if (warning_handler == (WarningHandler) NULL)
15027 warning_handler=resource_info->display_warnings ?
15028 SetErrorHandler(XWarning) : SetErrorHandler((ErrorHandler) NULL);
15029 warning_handler=resource_info->display_warnings ?
15030 SetWarningHandler(XWarning) : SetWarningHandler((WarningHandler) NULL);
15033 Initialize Image and Magnify X images.
15035 windows->image.x=0;
15036 windows->image.y=0;
15037 windows->magnify.shape=MagickFalse;
15038 width=(unsigned int) display_image->columns;
15039 height=(unsigned int) display_image->rows;
15040 if ((display_image->columns != width) || (display_image->rows != height))
15041 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
15042 display_image->filename);
15043 status=XMakeImage(display,resource_info,&windows->image,display_image,
15044 width,height,exception);
15045 if (IfMagickFalse(status) )
15046 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
15047 display_image->filename);
15048 status=XMakeImage(display,resource_info,&windows->magnify,(Image *) NULL,
15049 windows->magnify.width,windows->magnify.height,exception);
15050 if (IfMagickFalse(status))
15051 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
15052 display_image->filename);
15053 if (IfMagickTrue(windows->magnify.mapped) )
15054 (void) XMapRaised(display,windows->magnify.id);
15055 if (IfMagickTrue(windows->pan.mapped) )
15056 (void) XMapRaised(display,windows->pan.id);
15057 windows->image.window_changes.width=(int) display_image->columns;
15058 windows->image.window_changes.height=(int) display_image->rows;
15059 (void) XConfigureImage(display,resource_info,windows,display_image,exception);
15060 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
15061 (void) XSync(display,MagickFalse);
15065 delay=display_image->delay/MagickMax(display_image->ticks_per_second,1L);
15066 timer=time((time_t *) NULL)+(delay == 0 ? 1 : delay)+1;
15068 if (IfMagickTrue(resource_info->update) )
15074 Determine when file data was last modified.
15076 status=GetPathAttributes(display_image->filename,&attributes);
15077 if (IfMagickTrue(status) )
15078 update_time=attributes.st_mtime;
15080 *state&=(~FormerImageState);
15081 *state&=(~MontageImageState);
15082 *state&=(~NextImageState);
15086 Handle a window event.
15088 if (IfMagickTrue(windows->image.mapped) )
15089 if ((display_image->delay != 0) || (resource_info->update != 0))
15091 if (timer < time((time_t *) NULL))
15093 if (IfMagickFalse(resource_info->update) )
15094 *state|=NextImageState | ExitState;
15101 Determine if image file was modified.
15103 status=GetPathAttributes(display_image->filename,&attributes);
15104 if (IfMagickTrue(status) )
15105 if (update_time != attributes.st_mtime)
15110 (void) FormatLocaleString(
15111 resource_info->image_info->filename,MaxTextExtent,
15112 "%s:%s",display_image->magick,
15113 display_image->filename);
15114 nexus=ReadImage(resource_info->image_info,exception);
15115 if (nexus != (Image *) NULL)
15117 nexus=DestroyImage(nexus);
15118 *state|=NextImageState | ExitState;
15121 delay=display_image->delay/MagickMax(
15122 display_image->ticks_per_second,1L);
15123 timer=time((time_t *) NULL)+(delay == 0 ? 1 : delay)+1;
15126 if (XEventsQueued(display,QueuedAfterFlush) == 0)
15129 Do not block if delay > 0.
15131 XDelay(display,SuspendTime << 2);
15135 timestamp=time((time_t *) NULL);
15136 (void) XNextEvent(display,&event);
15137 if (IfMagickFalse(windows->image.stasis) )
15138 windows->image.stasis=IsMagickTrue((time((time_t *) NULL)-timestamp) > 0);
15139 if (IfMagickFalse(windows->magnify.stasis) )
15140 windows->magnify.stasis=IsMagickTrue((time((time_t *) NULL)-timestamp) > 0);
15141 if (event.xany.window == windows->command.id)
15144 Select a command from the Command widget.
15146 id=XCommandWidget(display,windows,CommandMenu,&event);
15149 (void) CopyMagickString(command,CommandMenu[id],MaxTextExtent);
15150 command_type=CommandMenus[id];
15151 if (id < MagickMenus)
15154 Select a command from a pop-up menu.
15156 entry=XMenuWidget(display,windows,CommandMenu[id],Menus[id],
15160 (void) CopyMagickString(command,Menus[id][entry],MaxTextExtent);
15161 command_type=Commands[id][entry];
15163 if (command_type != NullCommand)
15164 nexus=XMagickCommand(display,resource_info,windows,command_type,
15165 &display_image,exception);
15168 switch (event.type)
15172 if (IfMagickTrue(display_image->debug) )
15173 (void) LogMagickEvent(X11Event,GetMagickModule(),
15174 "Button Press: 0x%lx %u +%d+%d",event.xbutton.window,
15175 event.xbutton.button,event.xbutton.x,event.xbutton.y);
15176 if ((event.xbutton.button == Button3) &&
15177 (event.xbutton.state & Mod1Mask))
15180 Convert Alt-Button3 to Button2.
15182 event.xbutton.button=Button2;
15183 event.xbutton.state&=(~Mod1Mask);
15185 if (event.xbutton.window == windows->backdrop.id)
15187 (void) XSetInputFocus(display,event.xbutton.window,RevertToParent,
15188 event.xbutton.time);
15191 if (event.xbutton.window == windows->image.id)
15193 switch (event.xbutton.button)
15197 if (resource_info->immutable)
15200 Select a command from the Virtual menu.
15202 entry=XMenuWidget(display,windows,"Commands",VirtualMenu,
15205 nexus=XMagickCommand(display,resource_info,windows,
15206 VirtualCommands[entry],&display_image,exception);
15210 Map/unmap Command widget.
15212 if (IfMagickTrue(windows->command.mapped) )
15213 (void) XWithdrawWindow(display,windows->command.id,
15214 windows->command.screen);
15217 (void) XCommandWidget(display,windows,CommandMenu,
15219 (void) XMapRaised(display,windows->command.id);
15226 User pressed the image magnify button.
15228 (void) XMagickCommand(display,resource_info,windows,ZoomCommand,
15229 &display_image,exception);
15230 XMagnifyImage(display,windows,&event,exception);
15235 if (resource_info->immutable)
15238 Select a command from the Virtual menu.
15240 entry=XMenuWidget(display,windows,"Commands",VirtualMenu,
15243 nexus=XMagickCommand(display,resource_info,windows,
15244 VirtualCommands[entry],&display_image,exception);
15247 if (display_image->montage != (char *) NULL)
15250 Open or delete a tile from a visual image directory.
15252 nexus=XTileImage(display,resource_info,windows,
15253 display_image,&event,exception);
15254 if (nexus != (Image *) NULL)
15255 *state|=MontageImageState | NextImageState | ExitState;
15256 vid_info.x=(short int) windows->image.x;
15257 vid_info.y=(short int) windows->image.y;
15261 Select a command from the Short Cuts menu.
15263 entry=XMenuWidget(display,windows,"Short Cuts",ShortCutsMenu,
15266 nexus=XMagickCommand(display,resource_info,windows,
15267 ShortCutsCommands[entry],&display_image,exception);
15275 XTranslateImage(display,windows,*image,XK_Up);
15283 XTranslateImage(display,windows,*image,XK_Down);
15291 if (event.xbutton.window == windows->magnify.id)
15311 MagnifyCommands[] =
15324 Select a magnify factor from the pop-up menu.
15326 factor=XMenuWidget(display,windows,"Magnify",MagnifyMenu,command);
15328 XMagnifyWindowCommand(display,windows,0,MagnifyCommands[factor],
15332 if (event.xbutton.window == windows->pan.id)
15334 switch (event.xbutton.button)
15341 XTranslateImage(display,windows,*image,XK_Up);
15349 XTranslateImage(display,windows,*image,XK_Down);
15354 XPanImage(display,windows,&event,exception);
15360 delay=display_image->delay/MagickMax(display_image->ticks_per_second,
15362 timer=time((time_t *) NULL)+(delay == 0 ? 1 : delay)+1;
15365 case ButtonRelease:
15367 if (IfMagickTrue(display_image->debug) )
15368 (void) LogMagickEvent(X11Event,GetMagickModule(),
15369 "Button Release: 0x%lx %u +%d+%d",event.xbutton.window,
15370 event.xbutton.button,event.xbutton.x,event.xbutton.y);
15373 case ClientMessage:
15375 if (IfMagickTrue(display_image->debug) )
15376 (void) LogMagickEvent(X11Event,GetMagickModule(),
15377 "Client Message: 0x%lx 0x%lx %d 0x%lx",event.xclient.window,
15378 event.xclient.message_type,event.xclient.format,(unsigned long)
15379 event.xclient.data.l[0]);
15380 if (event.xclient.message_type == windows->im_protocols)
15382 if (*event.xclient.data.l == (long) windows->im_update_widget)
15384 (void) CloneString(&windows->command.name,MagickTitle);
15385 windows->command.data=MagickMenus;
15386 (void) XCommandWidget(display,windows,CommandMenu,
15390 if (*event.xclient.data.l == (long) windows->im_update_colormap)
15393 Update graphic context and window colormap.
15395 for (i=0; i < (int) number_windows; i++)
15397 if (magick_windows[i]->id == windows->icon.id)
15399 context_values.background=pixel->background_color.pixel;
15400 context_values.foreground=pixel->foreground_color.pixel;
15401 (void) XChangeGC(display,magick_windows[i]->annotate_context,
15402 context_mask,&context_values);
15403 (void) XChangeGC(display,magick_windows[i]->widget_context,
15404 context_mask,&context_values);
15405 context_values.background=pixel->foreground_color.pixel;
15406 context_values.foreground=pixel->background_color.pixel;
15407 context_values.plane_mask=context_values.background ^
15408 context_values.foreground;
15409 (void) XChangeGC(display,magick_windows[i]->highlight_context,
15410 (size_t) (context_mask | GCPlaneMask),
15412 magick_windows[i]->attributes.background_pixel=
15413 pixel->background_color.pixel;
15414 magick_windows[i]->attributes.border_pixel=
15415 pixel->border_color.pixel;
15416 magick_windows[i]->attributes.colormap=map_info->colormap;
15417 (void) XChangeWindowAttributes(display,magick_windows[i]->id,
15418 (unsigned long) magick_windows[i]->mask,
15419 &magick_windows[i]->attributes);
15421 if (IfMagickTrue(windows->pan.mapped) )
15423 (void) XSetWindowBackgroundPixmap(display,windows->pan.id,
15424 windows->pan.pixmap);
15425 (void) XClearWindow(display,windows->pan.id);
15426 XDrawPanRectangle(display,windows);
15428 if (windows->backdrop.id != (Window) NULL)
15429 (void) XInstallColormap(display,map_info->colormap);
15432 if (*event.xclient.data.l == (long) windows->im_former_image)
15434 *state|=FormerImageState | ExitState;
15437 if (*event.xclient.data.l == (long) windows->im_next_image)
15439 *state|=NextImageState | ExitState;
15442 if (*event.xclient.data.l == (long) windows->im_retain_colors)
15444 *state|=RetainColorsState;
15447 if (*event.xclient.data.l == (long) windows->im_exit)
15454 if (event.xclient.message_type == windows->dnd_protocols)
15472 Display image named by the Drag-and-Drop selection.
15474 if ((*event.xclient.data.l != 2) && (*event.xclient.data.l != 128))
15476 selection=XInternAtom(display,"DndSelection",MagickFalse);
15477 status=XGetWindowProperty(display,root_window,selection,0L,(long)
15478 MaxTextExtent,MagickFalse,(Atom) AnyPropertyType,&type,&format,
15479 &length,&after,&data);
15480 if ((status != Success) || (length == 0))
15482 if (*event.xclient.data.l == 2)
15487 (void) CopyMagickString(resource_info->image_info->filename,
15488 (char *) data,MaxTextExtent);
15495 if (strncmp((char *) data, "file:", 5) != 0)
15497 (void) XFree((void *) data);
15500 (void) CopyMagickString(resource_info->image_info->filename,
15501 ((char *) data)+5,MaxTextExtent);
15503 nexus=ReadImage(resource_info->image_info,exception);
15504 CatchException(exception);
15505 if (nexus != (Image *) NULL)
15506 *state|=NextImageState | ExitState;
15507 (void) XFree((void *) data);
15511 If client window delete message, exit.
15513 if (event.xclient.message_type != windows->wm_protocols)
15515 if (*event.xclient.data.l != (long) windows->wm_delete_window)
15517 (void) XWithdrawWindow(display,event.xclient.window,
15518 visual_info->screen);
15519 if (event.xclient.window == windows->image.id)
15524 if (event.xclient.window == windows->pan.id)
15527 Restore original image size when pan window is deleted.
15529 windows->image.window_changes.width=windows->image.ximage->width;
15530 windows->image.window_changes.height=windows->image.ximage->height;
15531 (void) XConfigureImage(display,resource_info,windows,
15532 display_image,exception);
15536 case ConfigureNotify:
15538 if (IfMagickTrue(display_image->debug) )
15539 (void) LogMagickEvent(X11Event,GetMagickModule(),
15540 "Configure Notify: 0x%lx %dx%d+%d+%d %d",event.xconfigure.window,
15541 event.xconfigure.width,event.xconfigure.height,event.xconfigure.x,
15542 event.xconfigure.y,event.xconfigure.send_event);
15543 if (event.xconfigure.window == windows->image.id)
15546 Image window has a new configuration.
15548 if (event.xconfigure.send_event != 0)
15554 Position the transient windows relative of the Image window.
15556 if (windows->command.geometry == (char *) NULL)
15557 if (IfMagickFalse(windows->command.mapped) )
15559 windows->command.x=event.xconfigure.x-
15560 windows->command.width-25;
15561 windows->command.y=event.xconfigure.y;
15562 XConstrainWindowPosition(display,&windows->command);
15563 window_changes.x=windows->command.x;
15564 window_changes.y=windows->command.y;
15565 (void) XReconfigureWMWindow(display,windows->command.id,
15566 windows->command.screen,(unsigned int) (CWX | CWY),
15569 if (windows->widget.geometry == (char *) NULL)
15570 if (IfMagickFalse(windows->widget.mapped) )
15572 windows->widget.x=event.xconfigure.x+
15573 event.xconfigure.width/10;
15574 windows->widget.y=event.xconfigure.y+
15575 event.xconfigure.height/10;
15576 XConstrainWindowPosition(display,&windows->widget);
15577 window_changes.x=windows->widget.x;
15578 window_changes.y=windows->widget.y;
15579 (void) XReconfigureWMWindow(display,windows->widget.id,
15580 windows->widget.screen,(unsigned int) (CWX | CWY),
15583 if (windows->magnify.geometry == (char *) NULL)
15584 if (IfMagickFalse(windows->magnify.mapped) )
15586 windows->magnify.x=event.xconfigure.x+
15587 event.xconfigure.width+25;
15588 windows->magnify.y=event.xconfigure.y;
15589 XConstrainWindowPosition(display,&windows->magnify);
15590 window_changes.x=windows->magnify.x;
15591 window_changes.y=windows->magnify.y;
15592 (void) XReconfigureWMWindow(display,windows->magnify.id,
15593 windows->magnify.screen,(unsigned int) (CWX | CWY),
15596 if (windows->pan.geometry == (char *) NULL)
15597 if (IfMagickFalse(windows->pan.mapped) )
15599 windows->pan.x=event.xconfigure.x+
15600 event.xconfigure.width+25;
15601 windows->pan.y=event.xconfigure.y+
15602 windows->magnify.height+50;
15603 XConstrainWindowPosition(display,&windows->pan);
15604 window_changes.x=windows->pan.x;
15605 window_changes.y=windows->pan.y;
15606 (void) XReconfigureWMWindow(display,windows->pan.id,
15607 windows->pan.screen,(unsigned int) (CWX | CWY),
15611 if ((event.xconfigure.width == (int) windows->image.width) &&
15612 (event.xconfigure.height == (int) windows->image.height))
15614 windows->image.width=(unsigned int) event.xconfigure.width;
15615 windows->image.height=(unsigned int) event.xconfigure.height;
15616 windows->image.x=0;
15617 windows->image.y=0;
15618 if (display_image->montage != (char *) NULL)
15620 windows->image.x=vid_info.x;
15621 windows->image.y=vid_info.y;
15623 if (IfMagickTrue(windows->image.mapped) &&
15624 IfMagickTrue(windows->image.stasis) )
15627 Update image window configuration.
15629 windows->image.window_changes.width=event.xconfigure.width;
15630 windows->image.window_changes.height=event.xconfigure.height;
15631 (void) XConfigureImage(display,resource_info,windows,
15632 display_image,exception);
15635 Update pan window configuration.
15637 if ((event.xconfigure.width < windows->image.ximage->width) ||
15638 (event.xconfigure.height < windows->image.ximage->height))
15640 (void) XMapRaised(display,windows->pan.id);
15641 XDrawPanRectangle(display,windows);
15644 if (IfMagickTrue(windows->pan.mapped) )
15645 (void) XWithdrawWindow(display,windows->pan.id,
15646 windows->pan.screen);
15649 if (event.xconfigure.window == windows->magnify.id)
15655 Magnify window has a new configuration.
15657 windows->magnify.width=(unsigned int) event.xconfigure.width;
15658 windows->magnify.height=(unsigned int) event.xconfigure.height;
15659 if (IfMagickFalse(windows->magnify.mapped) )
15662 while ((int) magnify <= event.xconfigure.width)
15664 while ((int) magnify <= event.xconfigure.height)
15667 if (((int) magnify != event.xconfigure.width) ||
15668 ((int) magnify != event.xconfigure.height))
15670 window_changes.width=(int) magnify;
15671 window_changes.height=(int) magnify;
15672 (void) XReconfigureWMWindow(display,windows->magnify.id,
15673 windows->magnify.screen,(unsigned int) (CWWidth | CWHeight),
15677 if (IfMagickTrue(windows->magnify.mapped) &&
15678 IfMagickTrue(windows->magnify.stasis) )
15680 status=XMakeImage(display,resource_info,&windows->magnify,
15681 display_image,windows->magnify.width,windows->magnify.height,
15683 XMakeMagnifyImage(display,windows,exception);
15687 if (IfMagickTrue(windows->magnify.mapped) &&
15688 (event.xconfigure.window == windows->pan.id))
15691 Pan icon window has a new configuration.
15693 if (event.xconfigure.send_event != 0)
15695 windows->pan.x=event.xconfigure.x;
15696 windows->pan.y=event.xconfigure.y;
15698 windows->pan.width=(unsigned int) event.xconfigure.width;
15699 windows->pan.height=(unsigned int) event.xconfigure.height;
15702 if (event.xconfigure.window == windows->icon.id)
15705 Icon window has a new configuration.
15707 windows->icon.width=(unsigned int) event.xconfigure.width;
15708 windows->icon.height=(unsigned int) event.xconfigure.height;
15713 case DestroyNotify:
15716 Group leader has exited.
15718 if (IfMagickTrue(display_image->debug) )
15719 (void) LogMagickEvent(X11Event,GetMagickModule(),
15720 "Destroy Notify: 0x%lx",event.xdestroywindow.window);
15721 if (event.xdestroywindow.window == windows->group_leader.id)
15731 Selectively install colormap.
15733 if (map_info->colormap != XDefaultColormap(display,visual_info->screen))
15734 if (event.xcrossing.mode != NotifyUngrab)
15735 XInstallColormap(display,map_info->colormap);
15740 if (IfMagickTrue(display_image->debug) )
15741 (void) LogMagickEvent(X11Event,GetMagickModule(),
15742 "Expose: 0x%lx %dx%d+%d+%d",event.xexpose.window,
15743 event.xexpose.width,event.xexpose.height,event.xexpose.x,
15746 Refresh windows that are now exposed.
15748 if ((event.xexpose.window == windows->image.id) &&
15749 IfMagickTrue(windows->image.mapped) )
15751 XRefreshWindow(display,&windows->image,&event);
15752 delay=display_image->delay/MagickMax(
15753 display_image->ticks_per_second,1L);
15754 timer=time((time_t *) NULL)+(delay == 0 ? 1 : delay)+1;
15757 if ((event.xexpose.window == windows->magnify.id) &&
15758 IfMagickTrue(windows->magnify.mapped))
15760 XMakeMagnifyImage(display,windows,exception);
15763 if (event.xexpose.window == windows->pan.id)
15765 XDrawPanRectangle(display,windows);
15768 if (event.xexpose.window == windows->icon.id)
15770 XRefreshWindow(display,&windows->icon,&event);
15781 Respond to a user key press.
15783 length=XLookupString((XKeyEvent *) &event.xkey,command,(int)
15784 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
15785 *(command+length)='\0';
15786 if (IfMagickTrue(display_image->debug) )
15787 (void) LogMagickEvent(X11Event,GetMagickModule(),
15788 "Key press: %d 0x%lx (%s)",event.xkey.state,(unsigned long)
15789 key_symbol,command);
15790 if (event.xkey.window == windows->image.id)
15792 command_type=XImageWindowCommand(display,resource_info,windows,
15793 event.xkey.state,key_symbol,&display_image,exception);
15794 if (command_type != NullCommand)
15795 nexus=XMagickCommand(display,resource_info,windows,command_type,
15796 &display_image,exception);
15798 if (event.xkey.window == windows->magnify.id)
15799 XMagnifyWindowCommand(display,windows,event.xkey.state,key_symbol,
15801 if (event.xkey.window == windows->pan.id)
15803 if ((key_symbol == XK_q) || (key_symbol == XK_Escape))
15804 (void) XWithdrawWindow(display,windows->pan.id,
15805 windows->pan.screen);
15807 if ((key_symbol == XK_F1) || (key_symbol == XK_Help))
15808 XTextViewWidget(display,resource_info,windows,MagickFalse,
15809 "Help Viewer - Image Pan",ImagePanHelp);
15811 XTranslateImage(display,windows,*image,key_symbol);
15813 delay=display_image->delay/MagickMax(
15814 display_image->ticks_per_second,1L);
15815 timer=time((time_t *) NULL)+(delay == 0 ? 1 : delay)+1;
15821 Respond to a user key release.
15823 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
15824 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
15825 if (IfMagickTrue(display_image->debug) )
15826 (void) LogMagickEvent(X11Event,GetMagickModule(),
15827 "Key release: 0x%lx (%c)",(unsigned long) key_symbol,*command);
15833 Selectively uninstall colormap.
15835 if (map_info->colormap != XDefaultColormap(display,visual_info->screen))
15836 if (event.xcrossing.mode != NotifyUngrab)
15837 XUninstallColormap(display,map_info->colormap);
15842 if (IfMagickTrue(display_image->debug) )
15843 (void) LogMagickEvent(X11Event,GetMagickModule(),"Map Notify: 0x%lx",
15844 event.xmap.window);
15845 if (event.xmap.window == windows->backdrop.id)
15847 (void) XSetInputFocus(display,event.xmap.window,RevertToParent,
15849 windows->backdrop.mapped=MagickTrue;
15852 if (event.xmap.window == windows->image.id)
15854 if (windows->backdrop.id != (Window) NULL)
15855 (void) XInstallColormap(display,map_info->colormap);
15856 if (LocaleCompare(display_image->magick,"LOGO") == 0)
15858 if (LocaleCompare(display_image->filename,"LOGO") == 0)
15859 nexus=XOpenImage(display,resource_info,windows,MagickFalse);
15861 if (((int) windows->image.width < windows->image.ximage->width) ||
15862 ((int) windows->image.height < windows->image.ximage->height))
15863 (void) XMapRaised(display,windows->pan.id);
15864 windows->image.mapped=MagickTrue;
15867 if (event.xmap.window == windows->magnify.id)
15869 XMakeMagnifyImage(display,windows,exception);
15870 windows->magnify.mapped=MagickTrue;
15871 (void) XWithdrawWindow(display,windows->info.id,
15872 windows->info.screen);
15875 if (event.xmap.window == windows->pan.id)
15877 XMakePanImage(display,resource_info,windows,display_image,
15879 windows->pan.mapped=MagickTrue;
15882 if (event.xmap.window == windows->info.id)
15884 windows->info.mapped=MagickTrue;
15887 if (event.xmap.window == windows->icon.id)
15893 Create an icon image.
15895 taint=display_image->taint;
15896 XMakeStandardColormap(display,icon_visual,icon_resources,
15897 display_image,icon_map,icon_pixel,exception);
15898 (void) XMakeImage(display,icon_resources,&windows->icon,
15899 display_image,windows->icon.width,windows->icon.height,
15901 display_image->taint=taint;
15902 (void) XSetWindowBackgroundPixmap(display,windows->icon.id,
15903 windows->icon.pixmap);
15904 (void) XClearWindow(display,windows->icon.id);
15905 (void) XWithdrawWindow(display,windows->info.id,
15906 windows->info.screen);
15907 windows->icon.mapped=MagickTrue;
15910 if (event.xmap.window == windows->command.id)
15912 windows->command.mapped=MagickTrue;
15915 if (event.xmap.window == windows->popup.id)
15917 windows->popup.mapped=MagickTrue;
15920 if (event.xmap.window == windows->widget.id)
15922 windows->widget.mapped=MagickTrue;
15927 case MappingNotify:
15929 (void) XRefreshKeyboardMapping(&event.xmapping);
15934 case PropertyNotify:
15950 if (IfMagickTrue(display_image->debug) )
15951 (void) LogMagickEvent(X11Event,GetMagickModule(),
15952 "Property Notify: 0x%lx 0x%lx %d",event.xproperty.window,
15953 event.xproperty.atom,event.xproperty.state);
15954 if (event.xproperty.atom != windows->im_remote_command)
15957 Display image named by the remote command protocol.
15959 status=XGetWindowProperty(display,event.xproperty.window,
15960 event.xproperty.atom,0L,(long) MaxTextExtent,MagickFalse,(Atom)
15961 AnyPropertyType,&type,&format,&length,&after,&data);
15962 if ((status != Success) || (length == 0))
15964 if (LocaleCompare((char *) data,"-quit") == 0)
15966 XClientMessage(display,windows->image.id,windows->im_protocols,
15967 windows->im_exit,CurrentTime);
15968 (void) XFree((void *) data);
15971 (void) CopyMagickString(resource_info->image_info->filename,
15972 (char *) data,MaxTextExtent);
15973 (void) XFree((void *) data);
15974 nexus=ReadImage(resource_info->image_info,exception);
15975 CatchException(exception);
15976 if (nexus != (Image *) NULL)
15977 *state|=NextImageState | ExitState;
15980 case ReparentNotify:
15982 if (IfMagickTrue(display_image->debug) )
15983 (void) LogMagickEvent(X11Event,GetMagickModule(),
15984 "Reparent Notify: 0x%lx=>0x%lx",event.xreparent.parent,
15985 event.xreparent.window);
15990 if (IfMagickTrue(display_image->debug) )
15991 (void) LogMagickEvent(X11Event,GetMagickModule(),
15992 "Unmap Notify: 0x%lx",event.xunmap.window);
15993 if (event.xunmap.window == windows->backdrop.id)
15995 windows->backdrop.mapped=MagickFalse;
15998 if (event.xunmap.window == windows->image.id)
16000 windows->image.mapped=MagickFalse;
16003 if (event.xunmap.window == windows->magnify.id)
16005 windows->magnify.mapped=MagickFalse;
16008 if (event.xunmap.window == windows->pan.id)
16010 windows->pan.mapped=MagickFalse;
16013 if (event.xunmap.window == windows->info.id)
16015 windows->info.mapped=MagickFalse;
16018 if (event.xunmap.window == windows->icon.id)
16020 if (map_info->colormap == icon_map->colormap)
16021 XConfigureImageColormap(display,resource_info,windows,
16022 display_image,exception);
16023 (void) XFreeStandardColormap(display,icon_visual,icon_map,
16025 windows->icon.mapped=MagickFalse;
16028 if (event.xunmap.window == windows->command.id)
16030 windows->command.mapped=MagickFalse;
16033 if (event.xunmap.window == windows->popup.id)
16035 if (windows->backdrop.id != (Window) NULL)
16036 (void) XSetInputFocus(display,windows->image.id,RevertToParent,
16038 windows->popup.mapped=MagickFalse;
16041 if (event.xunmap.window == windows->widget.id)
16043 if (windows->backdrop.id != (Window) NULL)
16044 (void) XSetInputFocus(display,windows->image.id,RevertToParent,
16046 windows->widget.mapped=MagickFalse;
16053 if (IfMagickTrue(display_image->debug) )
16054 (void) LogMagickEvent(X11Event,GetMagickModule(),"Event type: %d",
16059 } while (!(*state & ExitState));
16060 if ((*state & ExitState) == 0)
16061 (void) XMagickCommand(display,resource_info,windows,FreeBuffersCommand,
16062 &display_image,exception);
16064 if (IfMagickTrue(resource_info->confirm_edit) )
16067 Query user if image has changed.
16069 if (IfMagickFalse(resource_info->immutable) &&
16070 IfMagickTrue(display_image->taint))
16075 status=XConfirmWidget(display,windows,"Your image changed.",
16076 "Do you want to save it");
16078 *state&=(~ExitState);
16081 (void) XMagickCommand(display,resource_info,windows,SaveCommand,
16082 &display_image,exception);
16085 if ((windows->visual_info->klass == GrayScale) ||
16086 (windows->visual_info->klass == PseudoColor) ||
16087 (windows->visual_info->klass == DirectColor))
16090 Withdraw pan and Magnify window.
16092 if (IfMagickTrue(windows->info.mapped) )
16093 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
16094 if (IfMagickTrue(windows->magnify.mapped) )
16095 (void) XWithdrawWindow(display,windows->magnify.id,
16096 windows->magnify.screen);
16097 if (IfMagickTrue(windows->command.mapped) )
16098 (void) XWithdrawWindow(display,windows->command.id,
16099 windows->command.screen);
16101 if (IfMagickTrue(windows->pan.mapped) )
16102 (void) XWithdrawWindow(display,windows->pan.id,windows->pan.screen);
16103 if (IfMagickFalse(resource_info->backdrop) )
16104 if (windows->backdrop.mapped)
16106 (void) XWithdrawWindow(display,windows->backdrop.id,
16107 windows->backdrop.screen);
16108 (void) XDestroyWindow(display,windows->backdrop.id);
16109 windows->backdrop.id=(Window) NULL;
16110 (void) XWithdrawWindow(display,windows->image.id,
16111 windows->image.screen);
16112 (void) XDestroyWindow(display,windows->image.id);
16113 windows->image.id=(Window) NULL;
16115 XSetCursorState(display,windows,MagickTrue);
16116 XCheckRefreshWindows(display,windows);
16117 if (((*state & FormerImageState) != 0) || ((*state & NextImageState) != 0))
16118 *state&=(~ExitState);
16119 if (*state & ExitState)
16122 Free Standard Colormap.
16124 (void) XFreeStandardColormap(display,icon_visual,icon_map,icon_pixel);
16125 if (resource_info->map_type == (char *) NULL)
16126 (void) XFreeStandardColormap(display,visual_info,map_info,pixel);
16130 if (resource_info->copy_image != (Image *) NULL)
16132 resource_info->copy_image=DestroyImage(resource_info->copy_image);
16133 resource_info->copy_image=NewImageList();
16135 DestroyXResources();
16137 (void) XSync(display,MagickFalse);
16139 Restore our progress monitor and warning handlers.
16141 (void) SetErrorHandler(warning_handler);
16142 (void) SetWarningHandler(warning_handler);
16144 Change to home directory.
16146 directory=getcwd(working_directory,MaxTextExtent);
16152 if (*resource_info->home_directory == '\0')
16153 (void) CopyMagickString(resource_info->home_directory,".",MaxTextExtent);
16154 status=chdir(resource_info->home_directory);
16156 (void) ThrowMagickException(exception,GetMagickModule(),FileOpenError,
16157 "UnableToOpenFile","%s",resource_info->home_directory);
16159 *image=display_image;
16165 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
16169 + D i s p l a y I m a g e s %
16173 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
16175 % DisplayImages() displays an image sequence to any X window screen. It
16176 % returns a value other than 0 if successful. Check the exception member
16177 % of image to determine the reason for any failure.
16179 % The format of the DisplayImages method is:
16181 % MagickBooleanType DisplayImages(const ImageInfo *image_info,
16182 % Image *images,ExceptionInfo *exception)
16184 % A description of each parameter follows:
16186 % o image_info: the image info.
16188 % o image: the image.
16190 % o exception: return any errors or warnings in this structure.
16193 MagickExport MagickBooleanType DisplayImages(const ImageInfo *image_info,
16194 Image *image,ExceptionInfo *exception)
16196 assert(image_info != (const ImageInfo *) NULL);
16197 assert(image_info->signature == MagickSignature);
16198 assert(image != (Image *) NULL);
16199 assert(image->signature == MagickSignature);
16200 if (IfMagickTrue(image->debug) )
16201 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
16202 (void) ThrowMagickException(exception,GetMagickModule(),MissingDelegateError,
16203 "DelegateLibrarySupportNotBuiltIn","'%s' (X11)",image->filename);
16204 return(MagickFalse);
16208 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
16212 + R e m o t e D i s p l a y C o m m a n d %
16216 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
16218 % RemoteDisplayCommand() encourages a remote display program to display the
16219 % specified image filename.
16221 % The format of the RemoteDisplayCommand method is:
16223 % MagickBooleanType RemoteDisplayCommand(const ImageInfo *image,
16224 % const char *window,const char *filename,ExceptionInfo *exception)
16226 % A description of each parameter follows:
16228 % o image_info: the image info.
16230 % o window: Specifies the name or id of an X window.
16232 % o filename: the name of the image filename to display.
16234 % o exception: return any errors or warnings in this structure.
16237 MagickExport MagickBooleanType RemoteDisplayCommand(const ImageInfo *image_info,
16238 const char *window,const char *filename,ExceptionInfo *exception)
16240 assert(image_info != (const ImageInfo *) NULL);
16241 assert(image_info->signature == MagickSignature);
16242 assert(filename != (char *) NULL);
16244 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
16245 (void) ThrowMagickException(exception,GetMagickModule(),MissingDelegateError,
16246 "DelegateLibrarySupportNotBuiltIn","'%s' (X11)",image_info->filename);
16247 return(MagickFalse);