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/client.h"
49 #include "MagickCore/color.h"
50 #include "MagickCore/colorspace.h"
51 #include "MagickCore/composite.h"
52 #include "MagickCore/constitute.h"
53 #include "MagickCore/decorate.h"
54 #include "MagickCore/delegate.h"
55 #include "MagickCore/display.h"
56 #include "MagickCore/display-private.h"
57 #include "MagickCore/distort.h"
58 #include "MagickCore/draw.h"
59 #include "MagickCore/effect.h"
60 #include "MagickCore/enhance.h"
61 #include "MagickCore/exception.h"
62 #include "MagickCore/exception-private.h"
63 #include "MagickCore/fx.h"
64 #include "MagickCore/geometry.h"
65 #include "MagickCore/image.h"
66 #include "MagickCore/image-private.h"
67 #include "MagickCore/list.h"
68 #include "MagickCore/log.h"
69 #include "MagickCore/magick.h"
70 #include "MagickCore/memory_.h"
71 #include "MagickCore/monitor.h"
72 #include "MagickCore/monitor-private.h"
73 #include "MagickCore/montage.h"
74 #include "MagickCore/option.h"
75 #include "MagickCore/paint.h"
76 #include "MagickCore/pixel.h"
77 #include "MagickCore/pixel-accessor.h"
78 #include "MagickCore/PreRvIcccm.h"
79 #include "MagickCore/property.h"
80 #include "MagickCore/quantum.h"
81 #include "MagickCore/quantum-private.h"
82 #include "MagickCore/resize.h"
83 #include "MagickCore/resource_.h"
84 #include "MagickCore/shear.h"
85 #include "MagickCore/segment.h"
86 #include "MagickCore/statistic.h"
87 #include "MagickCore/string_.h"
88 #include "MagickCore/string-private.h"
89 #include "MagickCore/transform.h"
90 #include "MagickCore/threshold.h"
91 #include "MagickCore/utility.h"
92 #include "MagickCore/utility-private.h"
93 #include "MagickCore/version.h"
94 #include "MagickCore/widget.h"
95 #include "MagickCore/widget-private.h"
96 #include "MagickCore/xwindow.h"
97 #include "MagickCore/xwindow-private.h"
99 #if defined(MAGICKCORE_X11_DELEGATE)
103 #define MaxColors MagickMin((ssize_t) windows->visual_info->colormap_size,256L)
106 Constant declarations.
108 static const unsigned char
111 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55
115 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
119 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
143 Help widget declarations.
146 *ImageAnnotateHelp[] =
148 "In annotate mode, the Command widget has these options:",
198 "Choose a font name from the Font Name sub-menu. Additional",
199 "font names can be specified with the font browser. You can",
200 "change the menu names by setting the X resources font1",
203 "Choose a font color from the Font Color sub-menu.",
204 "Additional font colors can be specified with the color",
205 "browser. You can change the menu colors by setting the X",
206 "resources pen1 through pen9.",
208 "If you select the color browser and press Grab, you can",
209 "choose the font color by moving the pointer to the desired",
210 "color on the screen and press any button.",
212 "If you choose to rotate the text, choose Rotate Text from the",
213 "menu and select an angle. Typically you will only want to",
214 "rotate one line of text at a time. Depending on the angle you",
215 "choose, subsequent lines may end up overwriting each other.",
217 "Choosing a font and its color is optional. The default font",
218 "is fixed and the default color is black. However, you must",
219 "choose a location to begin entering text and press button 1.",
220 "An underscore character will appear at the location of the",
221 "pointer. The cursor changes to a pencil to indicate you are",
222 "in text mode. To exit immediately, press Dismiss.",
224 "In text mode, any key presses will display the character at",
225 "the location of the underscore and advance the underscore",
226 "cursor. Enter your text and once completed press Apply to",
227 "finish your image annotation. To correct errors press BACK",
228 "SPACE. To delete an entire line of text, press DELETE. Any",
229 "text that exceeds the boundaries of the image window is",
230 "automagically continued onto the next line.",
232 "The actual color you request for the font is saved in the",
233 "image. However, the color that appears in your image window",
234 "may be different. For example, on a monochrome screen the",
235 "text will appear black or white even if you choose the color",
236 "red as the font color. However, the image saved to a file",
237 "with -write is written with red lettering. To assure the",
238 "correct color text in the final image, any PseudoClass image",
239 "is promoted to DirectClass (see miff(5)). To force a",
240 "PseudoClass image to remain PseudoClass, use -colors.",
245 "In chop mode, the Command widget has these options:",
253 "If the you choose the horizontal direction (this the",
254 "default), the area of the image between the two horizontal",
255 "endpoints of the chop line is removed. Otherwise, the area",
256 "of the image between the two vertical endpoints of the chop",
259 "Select a location within the image window to begin your chop,",
260 "press and hold any button. Next, move the pointer to",
261 "another location in the image. As you move a line will",
262 "connect the initial location and the pointer. When you",
263 "release the button, the area within the image to chop is",
264 "determined by which direction you choose from the Command",
267 "To cancel the image chopping, move the pointer back to the",
268 "starting point of the line and release the button.",
271 *ImageColorEditHelp[] =
273 "In color edit mode, the Command widget has these options:",
314 "Choose a color editing method from the Method sub-menu",
315 "of the Command widget. The point method recolors any pixel",
316 "selected with the pointer until the button is released. The",
317 "replace method recolors any pixel that matches the color of",
318 "the pixel you select with a button press. Floodfill recolors",
319 "any pixel that matches the color of the pixel you select with",
320 "a button press and is a neighbor. Whereas filltoborder recolors",
321 "any neighbor pixel that is not the border color. Finally reset",
322 "changes the entire image to the designated color.",
324 "Next, choose a pixel color from the Pixel Color sub-menu.",
325 "Additional pixel colors can be specified with the color",
326 "browser. You can change the menu colors by setting the X",
327 "resources pen1 through pen9.",
329 "Now press button 1 to select a pixel within the image window",
330 "to change its color. Additional pixels may be recolored as",
331 "prescribed by the method you choose.",
333 "If the Magnify widget is mapped, it can be helpful in positioning",
334 "your pointer within the image (refer to button 2).",
336 "The actual color you request for the pixels is saved in the",
337 "image. However, the color that appears in your image window",
338 "may be different. For example, on a monochrome screen the",
339 "pixel will appear black or white even if you choose the",
340 "color red as the pixel color. However, the image saved to a",
341 "file with -write is written with red pixels. To assure the",
342 "correct color text in the final image, any PseudoClass image",
343 "is promoted to DirectClass (see miff(5)). To force a",
344 "PseudoClass image to remain PseudoClass, use -colors.",
347 *ImageCompositeHelp[] =
349 "First a widget window is displayed requesting you to enter an",
350 "image name. Press Composite, Grab or type a file name.",
351 "Press Cancel if you choose not to create a composite image.",
352 "When you choose Grab, move the pointer to the desired window",
353 "and press any button.",
355 "If the Composite image does not have any matte information,",
356 "you are informed and the file browser is displayed again.",
357 "Enter the name of a mask image. The image is typically",
358 "grayscale and the same size as the composite image. If the",
359 "image is not grayscale, it is converted to grayscale and the",
360 "resulting intensities are used as matte information.",
362 "A small window appears showing the location of the cursor in",
363 "the image window. You are now in composite mode. To exit",
364 "immediately, press Dismiss. In composite mode, the Command",
365 "widget has these options:",
391 "Choose a composite operation from the Operators sub-menu of",
392 "the Command widget. How each operator behaves is described",
393 "below. Image window is the image currently displayed on",
394 "your X server and image is the image obtained with the File",
397 "Over The result is the union of the two image shapes,",
398 " with image obscuring image window in the region of",
401 "In The result is simply image cut by the shape of",
402 " image window. None of the image data of image",
403 " window is in the result.",
405 "Out The resulting image is image with the shape of",
406 " image window cut out.",
408 "Atop The result is the same shape as image image window,",
409 " with image obscuring image window where the image",
410 " shapes overlap. Note this differs from over",
411 " because the portion of image outside image window's",
412 " shape does not appear in the result.",
414 "Xor The result is the image data from both image and",
415 " image window that is outside the overlap region.",
416 " The overlap region is blank.",
418 "Plus The result is just the sum of the image data.",
419 " Output values are cropped to QuantumRange (no overflow).",
421 "Minus The result of image - image window, with underflow",
424 "Add The result of image + image window, with overflow",
425 " wrapping around (mod 256).",
427 "Subtract The result of image - image window, with underflow",
428 " wrapping around (mod 256). The add and subtract",
429 " operators can be used to perform reversible",
433 " The result of abs(image - image window). This",
434 " useful for comparing two very similar images.",
437 " The result of image * image window. This",
438 " useful for the creation of drop-shadows.",
440 "Bumpmap The result of surface normals from image * image",
443 "Copy The resulting image is image window replaced with",
444 " image. Here the matte information is ignored.",
446 "CopyRed The red layer of the image window is replace with",
447 " the red layer of the image. The other layers are",
451 " The green layer of the image window is replace with",
452 " the green layer of the image. The other layers are",
455 "CopyBlue The blue layer of the image window is replace with",
456 " the blue layer of the image. The other layers are",
460 " The matte layer of the image window is replace with",
461 " the matte layer of the image. The other layers are",
464 "The image compositor requires a matte, or alpha channel in",
465 "the image for some operations. This extra channel usually",
466 "defines a mask which represents a sort of a cookie-cutter",
467 "for the image. This the case when matte is opaque (full",
468 "coverage) for pixels inside the shape, zero outside, and",
469 "between 0 and QuantumRange on the boundary. If image does not",
470 "have a matte channel, it is initialized with 0 for any pixel",
471 "matching in color to pixel location (0,0), otherwise QuantumRange.",
473 "If you choose Dissolve, the composite operator becomes Over. The",
474 "image matte channel percent transparency is initialized to factor.",
475 "The image window is initialized to (100-factor). Where factor is the",
476 "value you specify in the Dialog widget.",
478 "Displace shifts the image pixels as defined by a displacement",
479 "map. With this option, image is used as a displacement map.",
480 "Black, within the displacement map, is a maximum positive",
481 "displacement. White is a maximum negative displacement and",
482 "middle gray is neutral. The displacement is scaled to determine",
483 "the pixel shift. By default, the displacement applies in both the",
484 "horizontal and vertical directions. However, if you specify a mask,",
485 "image is the horizontal X displacement and mask the vertical Y",
488 "Note that matte information for image window is not retained",
489 "for colormapped X server visuals (e.g. StaticColor,",
490 "StaticColor, GrayScale, PseudoColor). Correct compositing",
491 "behavior may require a TrueColor or DirectColor visual or a",
492 "Standard Colormap.",
494 "Choosing a composite operator is optional. The default",
495 "operator is replace. However, you must choose a location to",
496 "composite your image and press button 1. Press and hold the",
497 "button before releasing and an outline of the image will",
498 "appear to help you identify your location.",
500 "The actual colors of the composite image is saved. However,",
501 "the color that appears in image window may be different.",
502 "For example, on a monochrome screen image window will appear",
503 "black or white even though your composited image may have",
504 "many colors. If the image is saved to a file it is written",
505 "with the correct colors. To assure the correct colors are",
506 "saved in the final image, any PseudoClass image is promoted",
507 "to DirectClass (see miff(5)). To force a PseudoClass image",
508 "to remain PseudoClass, use -colors.",
513 "In cut mode, the Command widget has these options:",
518 "To define a cut region, press button 1 and drag. The",
519 "cut region is defined by a highlighted rectangle that",
520 "expands or contracts as it follows the pointer. Once you",
521 "are satisfied with the cut region, release the button.",
522 "You are now in rectify mode. In rectify mode, the Command",
523 "widget has these options:",
529 "You can make adjustments by moving the pointer to one of the",
530 "cut rectangle corners, pressing a button, and dragging.",
531 "Finally, press Cut to commit your copy region. To",
532 "exit without cutting the image, press Dismiss.",
537 "In copy mode, the Command widget has these options:",
542 "To define a copy region, press button 1 and drag. The",
543 "copy region is defined by a highlighted rectangle that",
544 "expands or contracts as it follows the pointer. Once you",
545 "are satisfied with the copy region, release the button.",
546 "You are now in rectify mode. In rectify mode, the Command",
547 "widget has these options:",
553 "You can make adjustments by moving the pointer to one of the",
554 "copy rectangle corners, pressing a button, and dragging.",
555 "Finally, press Copy to commit your copy region. To",
556 "exit without copying the image, press Dismiss.",
561 "In crop mode, the Command widget has these options:",
566 "To define a cropping region, press button 1 and drag. The",
567 "cropping region is defined by a highlighted rectangle that",
568 "expands or contracts as it follows the pointer. Once you",
569 "are satisfied with the cropping region, release the button.",
570 "You are now in rectify mode. In rectify mode, the Command",
571 "widget has these options:",
577 "You can make adjustments by moving the pointer to one of the",
578 "cropping rectangle corners, pressing a button, and dragging.",
579 "Finally, press Crop to commit your cropping region. To",
580 "exit without cropping the image, press Dismiss.",
585 "The cursor changes to a crosshair to indicate you are in",
586 "draw mode. To exit immediately, press Dismiss. In draw mode,",
587 "the Command widget has these options:",
632 "Choose a drawing primitive from the Element sub-menu.",
634 "Choose a color from the Color sub-menu. Additional",
635 "colors can be specified with the color browser.",
637 "If you choose the color browser and press Grab, you can",
638 "select the color by moving the pointer to the desired",
639 "color on the screen and press any button. The transparent",
640 "color updates the image matte channel and is useful for",
641 "image compositing.",
643 "Choose a stipple, if appropriate, from the Stipple sub-menu.",
644 "Additional stipples can be specified with the file browser.",
645 "Stipples obtained from the file browser must be on disk in the",
646 "X11 bitmap format.",
648 "Choose a width, if appropriate, from the Width sub-menu. To",
649 "choose a specific width select the Dialog widget.",
651 "Choose a point in the Image window and press button 1 and",
652 "hold. Next, move the pointer to another location in the",
653 "image. As you move, a line connects the initial location and",
654 "the pointer. When you release the button, the image is",
655 "updated with the primitive you just drew. For polygons, the",
656 "image is updated when you press and release the button without",
657 "moving the pointer.",
659 "To cancel image drawing, move the pointer back to the",
660 "starting point of the line and release the button.",
666 " The effects of each button press is described below. Three",
667 " buttons are required. If you have a two button mouse,",
668 " button 1 and 3 are returned. Press ALT and button 3 to",
669 " simulate button 2.",
671 " 1 Press this button to map or unmap the Command widget.",
673 " 2 Press and drag to define a region of the image to",
676 " 3 Press and drag to choose from a select set of commands.",
677 " This button behaves differently if the image being",
678 " displayed is a visual image directory. Here, choose a",
679 " particular tile of the directory and press this button and",
680 " drag to select a command from a pop-up menu. Choose from",
681 " these menu items:",
689 " If you choose Open, the image represented by the tile is",
690 " displayed. To return to the visual image directory, choose",
691 " Next from the Command widget. Next and Former moves to the",
692 " next or former image respectively. Choose Delete to delete",
693 " a particular image tile. Finally, choose Update to",
694 " synchronize all the image tiles with their respective",
698 " The Command widget lists a number of sub-menus and commands.",
710 " Visual Directory...",
744 " Contrast Stretch...",
745 " Sigmoidal Contrast...",
773 " Charcoal Drawing...",
784 " Region of Interest...",
796 " Browse Documentation",
799 " Menu items with a indented triangle have a sub-menu. They",
800 " are represented above as the indented items. To access a",
801 " sub-menu item, move the pointer to the appropriate menu and",
802 " press a button and drag. When you find the desired sub-menu",
803 " item, release the button and the command is executed. Move",
804 " the pointer away from the sub-menu if you decide not to",
805 " execute a particular command.",
807 "KEYBOARD ACCELERATORS",
808 " Accelerators are one or two key presses that effect a",
809 " particular command. The keyboard accelerators that",
810 " display(1) understands is:",
812 " Ctl+O Press to open an image from a file.",
814 " space Press to display the next image.",
816 " If the image is a multi-paged document such as a Postscript",
817 " document, you can skip ahead several pages by preceding",
818 " this command with a number. For example to display the",
819 " third page beyond the current page, press 3<space>.",
821 " backspace Press to display the former image.",
823 " If the image is a multi-paged document such as a Postscript",
824 " document, you can skip behind several pages by preceding",
825 " this command with a number. For example to display the",
826 " third page preceding the current page, press 3<backspace>.",
828 " Ctl+S Press to write the image to a file.",
830 " Ctl+P Press to print the image to a Postscript printer.",
832 " Ctl+D Press to delete an image file.",
834 " Ctl+N Press to create a blank canvas.",
836 " Ctl+Q Press to discard all images and exit program.",
838 " Ctl+Z Press to undo last image transformation.",
840 " Ctl+R Press to redo last image transformation.",
842 " Ctl+X Press to cut a region of the image.",
844 " Ctl+C Press to copy a region of the image.",
846 " Ctl+V Press to paste a region to the image.",
848 " < Press to half the image size.",
850 " - Press to return to the original image size.",
852 " > Press to double the image size.",
854 " % Press to resize the image to a width and height you",
857 "Cmd-A Press to make any image transformations permanent."
859 " By default, any image size transformations are applied",
860 " to the original image to create the image displayed on",
861 " the X server. However, the transformations are not",
862 " permanent (i.e. the original image does not change",
863 " size only the X image does). For example, if you",
864 " press > the X image will appear to double in size,",
865 " but the original image will in fact remain the same size.",
866 " To force the original image to double in size, press >",
867 " followed by Cmd-A.",
869 " @ Press to refresh the image window.",
871 " C Press to cut out a rectangular region of the image.",
873 " [ Press to chop the image.",
875 " H Press to flop image in the horizontal direction.",
877 " V Press to flip image in the vertical direction.",
879 " / Press to rotate the image 90 degrees clockwise.",
881 " \\ Press to rotate the image 90 degrees counter-clockwise.",
883 " * Press to rotate the image the number of degrees you",
886 " S Press to shear the image the number of degrees you",
889 " R Press to roll the image.",
891 " T Press to trim the image edges.",
893 " Shft-H Press to vary the image hue.",
895 " Shft-S Press to vary the color saturation.",
897 " Shft-L Press to vary the color brightness.",
899 " Shft-G Press to gamma correct the image.",
901 " Shft-C Press to sharpen the image contrast.",
903 " Shft-Z Press to dull the image contrast.",
905 " = Press to perform histogram equalization on the image.",
907 " Shft-N Press to perform histogram normalization on the image.",
909 " Shft-~ Press to negate the colors of the image.",
911 " . Press to convert the image colors to gray.",
913 " Shft-# Press to set the maximum number of unique colors in the",
916 " F2 Press to reduce the speckles in an image.",
918 " F3 Press to eliminate peak noise from an image.",
920 " F4 Press to add noise to an image.",
922 " F5 Press to sharpen an image.",
924 " F6 Press to delete an image file.",
926 " F7 Press to threshold the image.",
928 " F8 Press to detect edges within an image.",
930 " F9 Press to emboss an image.",
932 " F10 Press to displace pixels by a random amount.",
934 " F11 Press to negate all pixels above the threshold level.",
936 " F12 Press to shade the image using a distant light source.",
938 " F13 Press to lighten or darken image edges to create a 3-D effect.",
940 " F14 Press to segment the image by color.",
942 " Meta-S Press to swirl image pixels about the center.",
944 " Meta-I Press to implode image pixels about the center.",
946 " Meta-W Press to alter an image along a sine wave.",
948 " Meta-P Press to simulate an oil painting.",
950 " Meta-C Press to simulate a charcoal drawing.",
952 " Alt-A Press to annotate the image with text.",
954 " Alt-D Press to draw on an image.",
956 " Alt-P Press to edit an image pixel color.",
958 " Alt-M Press to edit the image matte information.",
960 " Alt-V Press to composite the image with another.",
962 " Alt-B Press to add a border to the image.",
964 " Alt-F Press to add an ornamental border to the image.",
967 " Press to add an image comment.",
969 " Ctl-A Press to apply image processing techniques to a region",
972 " Shft-? Press to display information about the image.",
974 " Shft-+ Press to map the zoom image window.",
976 " Shft-P Press to preview an image enhancement, effect, or f/x.",
978 " F1 Press to display helpful information about display(1).",
980 " Find Press to browse documentation about ImageMagick.",
982 " 1-9 Press to change the level of magnification.",
984 " Use the arrow keys to move the image one pixel up, down,",
985 " left, or right within the magnify window. Be sure to first",
986 " map the magnify window by pressing button 2.",
988 " Press ALT and one of the arrow keys to trim off one pixel",
989 " from any side of the image.",
992 *ImageMatteEditHelp[] =
994 "Matte information within an image is useful for some",
995 "operations such as image compositing (See IMAGE",
996 "COMPOSITING). This extra channel usually defines a mask",
997 "which represents a sort of a cookie-cutter for the image.",
998 "This the case when matte is opaque (full coverage) for",
999 "pixels inside the shape, zero outside, and between 0 and",
1000 "QuantumRange on the boundary.",
1002 "A small window appears showing the location of the cursor in",
1003 "the image window. You are now in matte edit mode. To exit",
1004 "immediately, press Dismiss. In matte edit mode, the Command",
1005 "widget has these options:",
1039 "Choose a matte editing method from the Method sub-menu of",
1040 "the Command widget. The point method changes the matte value",
1041 "of any pixel selected with the pointer until the button is",
1042 "is released. The replace method changes the matte value of",
1043 "any pixel that matches the color of the pixel you select with",
1044 "a button press. Floodfill changes the matte value of any pixel",
1045 "that matches the color of the pixel you select with a button",
1046 "press and is a neighbor. Whereas filltoborder changes the matte",
1047 "value any neighbor pixel that is not the border color. Finally",
1048 "reset changes the entire image to the designated matte value.",
1050 "Choose Matte Value and pick Opaque or Transarent. For other values",
1051 "select the Dialog entry. Here a dialog appears requesting a matte",
1052 "value. The value you select is assigned as the opacity value of the",
1053 "selected pixel or pixels.",
1055 "Now, press any button to select a pixel within the image",
1056 "window to change its matte value.",
1058 "If the Magnify widget is mapped, it can be helpful in positioning",
1059 "your pointer within the image (refer to button 2).",
1061 "Matte information is only valid in a DirectClass image.",
1062 "Therefore, any PseudoClass image is promoted to DirectClass",
1063 "(see miff(5)). Note that matte information for PseudoClass",
1064 "is not retained for colormapped X server visuals (e.g.",
1065 "StaticColor, StaticColor, GrayScale, PseudoColor) unless you",
1066 "immediately save your image to a file (refer to Write).",
1067 "Correct matte editing behavior may require a TrueColor or",
1068 "DirectColor visual or a Standard Colormap.",
1073 "When an image exceeds the width or height of the X server",
1074 "screen, display maps a small panning icon. The rectangle",
1075 "within the panning icon shows the area that is currently",
1076 "displayed in the image window. To pan about the image,",
1077 "press any button and drag the pointer within the panning",
1078 "icon. The pan rectangle moves with the pointer and the",
1079 "image window is updated to reflect the location of the",
1080 "rectangle within the panning icon. When you have selected",
1081 "the area of the image you wish to view, release the button.",
1083 "Use the arrow keys to pan the image one pixel up, down,",
1084 "left, or right within the image window.",
1086 "The panning icon is withdrawn if the image becomes smaller",
1087 "than the dimensions of the X server screen.",
1092 "A small window appears showing the location of the cursor in",
1093 "the image window. You are now in paste mode. To exit",
1094 "immediately, press Dismiss. In paste mode, the Command",
1095 "widget has these options:",
1112 "Choose a composite operation from the Operators sub-menu of",
1113 "the Command widget. How each operator behaves is described",
1114 "below. Image window is the image currently displayed on",
1115 "your X server and image is the image obtained with the File",
1118 "Over The result is the union of the two image shapes,",
1119 " with image obscuring image window in the region of",
1122 "In The result is simply image cut by the shape of",
1123 " image window. None of the image data of image",
1124 " window is in the result.",
1126 "Out The resulting image is image with the shape of",
1127 " image window cut out.",
1129 "Atop The result is the same shape as image image window,",
1130 " with image obscuring image window where the image",
1131 " shapes overlap. Note this differs from over",
1132 " because the portion of image outside image window's",
1133 " shape does not appear in the result.",
1135 "Xor The result is the image data from both image and",
1136 " image window that is outside the overlap region.",
1137 " The overlap region is blank.",
1139 "Plus The result is just the sum of the image data.",
1140 " Output values are cropped to QuantumRange (no overflow).",
1141 " This operation is independent of the matte",
1144 "Minus The result of image - image window, with underflow",
1145 " cropped to zero.",
1147 "Add The result of image + image window, with overflow",
1148 " wrapping around (mod 256).",
1150 "Subtract The result of image - image window, with underflow",
1151 " wrapping around (mod 256). The add and subtract",
1152 " operators can be used to perform reversible",
1153 " transformations.",
1156 " The result of abs(image - image window). This",
1157 " useful for comparing two very similar images.",
1159 "Copy The resulting image is image window replaced with",
1160 " image. Here the matte information is ignored.",
1162 "CopyRed The red layer of the image window is replace with",
1163 " the red layer of the image. The other layers are",
1167 " The green layer of the image window is replace with",
1168 " the green layer of the image. The other layers are",
1171 "CopyBlue The blue layer of the image window is replace with",
1172 " the blue layer of the image. The other layers are",
1176 " The matte layer of the image window is replace with",
1177 " the matte layer of the image. The other layers are",
1180 "The image compositor requires a matte, or alpha channel in",
1181 "the image for some operations. This extra channel usually",
1182 "defines a mask which represents a sort of a cookie-cutter",
1183 "for the image. This the case when matte is opaque (full",
1184 "coverage) for pixels inside the shape, zero outside, and",
1185 "between 0 and QuantumRange on the boundary. If image does not",
1186 "have a matte channel, it is initialized with 0 for any pixel",
1187 "matching in color to pixel location (0,0), otherwise QuantumRange.",
1189 "Note that matte information for image window is not retained",
1190 "for colormapped X server visuals (e.g. StaticColor,",
1191 "StaticColor, GrayScale, PseudoColor). Correct compositing",
1192 "behavior may require a TrueColor or DirectColor visual or a",
1193 "Standard Colormap.",
1195 "Choosing a composite operator is optional. The default",
1196 "operator is replace. However, you must choose a location to",
1197 "paste your image and press button 1. Press and hold the",
1198 "button before releasing and an outline of the image will",
1199 "appear to help you identify your location.",
1201 "The actual colors of the pasted image is saved. However,",
1202 "the color that appears in image window may be different.",
1203 "For example, on a monochrome screen image window will appear",
1204 "black or white even though your pasted image may have",
1205 "many colors. If the image is saved to a file it is written",
1206 "with the correct colors. To assure the correct colors are",
1207 "saved in the final image, any PseudoClass image is promoted",
1208 "to DirectClass (see miff(5)). To force a PseudoClass image",
1209 "to remain PseudoClass, use -colors.",
1214 "In region of interest mode, the Command widget has these",
1220 "To define a region of interest, press button 1 and drag.",
1221 "The region of interest is defined by a highlighted rectangle",
1222 "that expands or contracts as it follows the pointer. Once",
1223 "you are satisfied with the region of interest, release the",
1224 "button. You are now in apply mode. In apply mode the",
1225 "Command widget has these options:",
1245 " Contrast Stretch",
1246 " Sigmoidal Contrast...",
1273 " Charcoal Drawing...",
1283 "You can make adjustments to the region of interest by moving",
1284 "the pointer to one of the rectangle corners, pressing a",
1285 "button, and dragging. Finally, choose an image processing",
1286 "technique from the Command widget. You can choose more than",
1287 "one image processing technique to apply to an area.",
1288 "Alternatively, you can move the region of interest before",
1289 "applying another image processing technique. To exit, press",
1293 *ImageRotateHelp[] =
1295 "In rotate mode, the Command widget has these options:",
1314 "Choose a background color from the Pixel Color sub-menu.",
1315 "Additional background colors can be specified with the color",
1316 "browser. You can change the menu colors by setting the X",
1317 "resources pen1 through pen9.",
1319 "If you choose the color browser and press Grab, you can",
1320 "select the background color by moving the pointer to the",
1321 "desired color on the screen and press any button.",
1323 "Choose a point in the image window and press this button and",
1324 "hold. Next, move the pointer to another location in the",
1325 "image. As you move a line connects the initial location and",
1326 "the pointer. When you release the button, the degree of",
1327 "image rotation is determined by the slope of the line you",
1328 "just drew. The slope is relative to the direction you",
1329 "choose from the Direction sub-menu of the Command widget.",
1331 "To cancel the image rotation, move the pointer back to the",
1332 "starting point of the line and release the button.",
1337 Enumeration declarations.
1356 VisualDirectoryCommand,
1364 OriginalSizeCommand,
1386 ContrastStretchCommand,
1387 SigmoidalContrastCommand,
1413 CharcoalDrawCommand,
1423 RegionofInterestCommand,
1429 ShowHistogramCommand,
1435 BrowseDocumentationCommand,
1437 SaveToUndoBufferCommand,
1444 AnnotateNameCommand,
1445 AnnotateFontColorCommand,
1446 AnnotateBackgroundColorCommand,
1447 AnnotateRotateCommand,
1448 AnnotateHelpCommand,
1449 AnnotateDismissCommand,
1452 ChopDirectionCommand,
1455 HorizontalChopCommand,
1456 VerticalChopCommand,
1457 ColorEditMethodCommand,
1458 ColorEditColorCommand,
1459 ColorEditBorderCommand,
1460 ColorEditFuzzCommand,
1461 ColorEditUndoCommand,
1462 ColorEditHelpCommand,
1463 ColorEditDismissCommand,
1464 CompositeOperatorsCommand,
1465 CompositeDissolveCommand,
1466 CompositeDisplaceCommand,
1467 CompositeHelpCommand,
1468 CompositeDismissCommand,
1473 RectifyDismissCommand,
1482 MatteEditBorderCommand,
1483 MatteEditFuzzCommand,
1484 MatteEditValueCommand,
1485 MatteEditUndoCommand,
1486 MatteEditHelpCommand,
1487 MatteEditDismissCommand,
1488 PasteOperatorsCommand,
1490 PasteDismissCommand,
1492 RotateDirectionCommand,
1494 RotateSharpenCommand,
1496 RotateDismissCommand,
1497 HorizontalRotateCommand,
1498 VerticalRotateCommand,
1509 #define BricksWidth 20
1510 #define BricksHeight 20
1511 #define DiagonalWidth 16
1512 #define DiagonalHeight 16
1513 #define HighlightWidth 8
1514 #define HighlightHeight 8
1515 #define OpaqueWidth 8
1516 #define OpaqueHeight 8
1517 #define ScalesWidth 16
1518 #define ScalesHeight 16
1519 #define ShadowWidth 8
1520 #define ShadowHeight 8
1521 #define VerticalWidth 16
1522 #define VerticalHeight 16
1523 #define WavyWidth 16
1524 #define WavyHeight 16
1527 Constant declaration.
1532 static const unsigned char
1535 0xff, 0xff, 0x0f, 0x03, 0x0c, 0x00, 0x03, 0x0c, 0x00, 0x03, 0x0c, 0x00,
1536 0x03, 0x0c, 0x00, 0xff, 0xff, 0x0f, 0x60, 0x80, 0x01, 0x60, 0x80, 0x01,
1537 0x60, 0x80, 0x01, 0x60, 0x80, 0x01, 0xff, 0xff, 0x0f, 0x03, 0x0c, 0x00,
1538 0x03, 0x0c, 0x00, 0x03, 0x0c, 0x00, 0x03, 0x0c, 0x00, 0xff, 0xff, 0x0f,
1539 0x60, 0x80, 0x01, 0x60, 0x80, 0x01, 0x60, 0x80, 0x01, 0x60, 0x80, 0x01
1543 0x44, 0x44, 0x88, 0x88, 0x11, 0x11, 0x22, 0x22, 0x44, 0x44, 0x88, 0x88,
1544 0x11, 0x11, 0x22, 0x22, 0x44, 0x44, 0x88, 0x88, 0x11, 0x11, 0x22, 0x22,
1545 0x44, 0x44, 0x88, 0x88, 0x11, 0x11, 0x22, 0x22
1549 0x08, 0x08, 0x08, 0x08, 0x14, 0x14, 0xe3, 0xe3, 0x80, 0x80, 0x80, 0x80,
1550 0x41, 0x41, 0x3e, 0x3e, 0x08, 0x08, 0x08, 0x08, 0x14, 0x14, 0xe3, 0xe3,
1551 0x80, 0x80, 0x80, 0x80, 0x41, 0x41, 0x3e, 0x3e
1555 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
1556 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
1557 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
1561 0xfe, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfd, 0xff, 0xfd, 0xff, 0xfb, 0xff,
1562 0xe7, 0xff, 0x1f, 0xff, 0xff, 0xf8, 0xff, 0xe7, 0xff, 0xdf, 0xff, 0xbf,
1563 0xff, 0xbf, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f
1567 Function prototypes.
1570 XImageWindowCommand(Display *,XResourceInfo *,XWindows *,
1571 const MagickStatusType,KeySym,Image **,ExceptionInfo *);
1574 *XMagickCommand(Display *,XResourceInfo *,XWindows *,const CommandType,
1575 Image **,ExceptionInfo *),
1576 *XOpenImage(Display *,XResourceInfo *,XWindows *,const MagickBooleanType),
1577 *XTileImage(Display *,XResourceInfo *,XWindows *,Image *,XEvent *,
1579 *XVisualDirectoryImage(Display *,XResourceInfo *,XWindows *,
1582 static MagickBooleanType
1583 XAnnotateEditImage(Display *,XResourceInfo *,XWindows *,Image *,
1585 XBackgroundImage(Display *,XResourceInfo *,XWindows *,Image **,
1587 XChopImage(Display *,XResourceInfo *,XWindows *,Image **,
1589 XCropImage(Display *,XResourceInfo *,XWindows *,Image *,const ClipboardMode,
1591 XColorEditImage(Display *,XResourceInfo *,XWindows *,Image **,
1593 XCompositeImage(Display *,XResourceInfo *,XWindows *,Image *,
1595 XConfigureImage(Display *,XResourceInfo *,XWindows *,Image *,ExceptionInfo *),
1596 XDrawEditImage(Display *,XResourceInfo *,XWindows *,Image **,
1598 XMatteEditImage(Display *,XResourceInfo *,XWindows *,Image **,
1600 XPasteImage(Display *,XResourceInfo *,XWindows *,Image *,ExceptionInfo *),
1601 XPrintImage(Display *,XResourceInfo *,XWindows *,Image *,ExceptionInfo *),
1602 XRotateImage(Display *,XResourceInfo *,XWindows *,double,Image **,
1604 XROIImage(Display *,XResourceInfo *,XWindows *,Image **,ExceptionInfo *),
1605 XSaveImage(Display *,XResourceInfo *,XWindows *,Image *,ExceptionInfo *),
1606 XTrimImage(Display *,XResourceInfo *,XWindows *,Image *,ExceptionInfo *);
1609 XDrawPanRectangle(Display *,XWindows *),
1610 XImageCache(Display *,XResourceInfo *,XWindows *,const CommandType,Image **,
1612 XMagnifyImage(Display *,XWindows *,XEvent *,ExceptionInfo *),
1613 XMakePanImage(Display *,XResourceInfo *,XWindows *,Image *,ExceptionInfo *),
1614 XPanImage(Display *,XWindows *,XEvent *,ExceptionInfo *),
1615 XMagnifyWindowCommand(Display *,XWindows *,const MagickStatusType,
1616 const KeySym,ExceptionInfo *),
1617 XSetCropGeometry(Display *,XWindows *,RectangleInfo *,Image *),
1618 XScreenEvent(Display *,XWindows *,XEvent *,ExceptionInfo *),
1619 XTranslateImage(Display *,XWindows *,Image *,const KeySym);
1622 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1626 % D i s p l a y I m a g e s %
1630 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1632 % DisplayImages() displays an image sequence to any X window screen. It
1633 % returns a value other than 0 if successful. Check the exception member
1634 % of image to determine the reason for any failure.
1636 % The format of the DisplayImages method is:
1638 % MagickBooleanType DisplayImages(const ImageInfo *image_info,
1639 % Image *images,ExceptionInfo *exception)
1641 % A description of each parameter follows:
1643 % o image_info: the image info.
1645 % o image: the image.
1647 % o exception: return any errors or warnings in this structure.
1650 MagickExport MagickBooleanType DisplayImages(const ImageInfo *image_info,
1651 Image *images,ExceptionInfo *exception)
1674 assert(image_info != (const ImageInfo *) NULL);
1675 assert(image_info->signature == MagickSignature);
1676 assert(images != (Image *) NULL);
1677 assert(images->signature == MagickSignature);
1678 if( IfMagickTrue(images->debug) )
1679 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",images->filename);
1680 display=XOpenDisplay(image_info->server_name);
1681 if (display == (Display *) NULL)
1683 (void) ThrowMagickException(exception,GetMagickModule(),XServerError,
1684 "UnableToOpenXServer","`%s'",XDisplayName(image_info->server_name));
1685 return(MagickFalse);
1687 if (exception->severity != UndefinedException)
1688 CatchException(exception);
1689 (void) XSetErrorHandler(XError);
1690 resource_database=XGetResourceDatabase(display,GetClientName());
1691 (void) ResetMagickMemory(&resource_info,0,sizeof(resource_info));
1692 XGetResourceInfo(image_info,resource_database,GetClientName(),&resource_info);
1693 if (image_info->page != (char *) NULL)
1694 resource_info.image_geometry=AcquireString(image_info->page);
1695 resource_info.immutable=MagickTrue;
1696 argv[0]=AcquireString(GetClientName());
1698 for (i=0; (state & ExitState) == 0; i++)
1700 if ((images->iterations != 0) && (i >= (ssize_t) images->iterations))
1702 image=GetImageFromList(images,i % GetImageListLength(images));
1703 (void) XDisplayImage(display,&resource_info,argv,1,&image,&state,exception);
1705 (void) SetErrorHandler((ErrorHandler) NULL);
1706 (void) SetWarningHandler((WarningHandler) NULL);
1707 argv[0]=DestroyString(argv[0]);
1708 (void) XCloseDisplay(display);
1709 XDestroyResourceInfo(&resource_info);
1710 if (exception->severity != UndefinedException)
1711 return(MagickFalse);
1716 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1720 % R e m o t e D i s p l a y C o m m a n d %
1724 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1726 % RemoteDisplayCommand() encourages a remote display program to display the
1727 % specified image filename.
1729 % The format of the RemoteDisplayCommand method is:
1731 % MagickBooleanType RemoteDisplayCommand(const ImageInfo *image_info,
1732 % const char *window,const char *filename,ExceptionInfo *exception)
1734 % A description of each parameter follows:
1736 % o image_info: the image info.
1738 % o window: Specifies the name or id of an X window.
1740 % o filename: the name of the image filename to display.
1742 % o exception: return any errors or warnings in this structure.
1745 MagickExport MagickBooleanType RemoteDisplayCommand(const ImageInfo *image_info,
1746 const char *window,const char *filename,ExceptionInfo *exception)
1754 assert(image_info != (const ImageInfo *) NULL);
1755 assert(image_info->signature == MagickSignature);
1756 assert(filename != (char *) NULL);
1757 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
1758 display=XOpenDisplay(image_info->server_name);
1759 if (display == (Display *) NULL)
1761 (void) ThrowMagickException(exception,GetMagickModule(),XServerError,
1762 "UnableToOpenXServer","`%s'",XDisplayName(image_info->server_name));
1763 return(MagickFalse);
1765 (void) XSetErrorHandler(XError);
1766 status=XRemoteCommand(display,window,filename);
1767 (void) XCloseDisplay(display);
1768 return(IsMagickTrue(status));
1772 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1776 + X A n n o t a t e E d i t I m a g e %
1780 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1782 % XAnnotateEditImage() annotates the image with text.
1784 % The format of the XAnnotateEditImage method is:
1786 % MagickBooleanType XAnnotateEditImage(Display *display,
1787 % XResourceInfo *resource_info,XWindows *windows,Image *image,
1788 % ExceptionInfo *exception)
1790 % A description of each parameter follows:
1792 % o display: Specifies a connection to an X server; returned from
1795 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
1797 % o windows: Specifies a pointer to a XWindows structure.
1799 % o image: the image; returned from ReadImage.
1803 static inline ssize_t MagickMax(const ssize_t x,const ssize_t y)
1810 static inline ssize_t MagickMin(const ssize_t x,const ssize_t y)
1817 static MagickBooleanType XAnnotateEditImage(Display *display,
1818 XResourceInfo *resource_info,XWindows *windows,Image *image,
1819 ExceptionInfo *exception)
1839 static const ModeType
1840 AnnotateCommands[] =
1842 AnnotateNameCommand,
1843 AnnotateFontColorCommand,
1844 AnnotateBackgroundColorCommand,
1845 AnnotateRotateCommand,
1846 AnnotateHelpCommand,
1847 AnnotateDismissCommand
1855 static MagickBooleanType
1856 transparent_box = MagickTrue,
1857 transparent_pen = MagickFalse;
1863 box_id = MaxNumberPens-2,
1868 command[MaxTextExtent],
1869 text[MaxTextExtent];
1872 *ColorMenu[MaxNumberPens+1];
1920 (void) CloneString(&windows->command.name,"Annotate");
1921 windows->command.data=4;
1922 (void) XCommandWidget(display,windows,AnnotateMenu,(XEvent *) NULL);
1923 (void) XMapRaised(display,windows->command.id);
1924 XClientMessage(display,windows->image.id,windows->im_protocols,
1925 windows->im_update_widget,CurrentTime);
1927 Track pointer until button 1 is pressed.
1929 XQueryPosition(display,windows->image.id,&x,&y);
1930 (void) XSelectInput(display,windows->image.id,
1931 windows->image.attributes.event_mask | PointerMotionMask);
1932 cursor=XCreateFontCursor(display,XC_left_side);
1933 (void) XCheckDefineCursor(display,windows->image.id,cursor);
1937 if( IfMagickTrue(windows->info.mapped) )
1940 Display pointer position.
1942 (void) FormatLocaleString(text,MaxTextExtent," %+d%+d ",
1943 x+windows->image.x,y+windows->image.y);
1944 XInfoWidget(display,windows,text);
1947 Wait for next event.
1949 XScreenEvent(display,windows,&event,exception);
1950 if (event.xany.window == windows->command.id)
1953 Select a command from the Command widget.
1955 id=XCommandWidget(display,windows,AnnotateMenu,&event);
1956 (void) XCheckDefineCursor(display,windows->image.id,cursor);
1959 switch (AnnotateCommands[id])
1961 case AnnotateNameCommand:
1964 *FontMenu[MaxNumberFonts];
1970 Initialize menu selections.
1972 for (i=0; i < MaxNumberFonts; i++)
1973 FontMenu[i]=resource_info->font_name[i];
1974 FontMenu[MaxNumberFonts-2]="Browser...";
1975 FontMenu[MaxNumberFonts-1]=(const char *) NULL;
1977 Select a font name from the pop-up menu.
1979 font_number=XMenuWidget(display,windows,AnnotateMenu[id],
1980 (const char **) FontMenu,command);
1981 if (font_number < 0)
1983 if (font_number == (MaxNumberFonts-2))
1986 font_name[MaxTextExtent] = "fixed";
1989 Select a font name from a browser.
1991 resource_info->font_name[font_number]=font_name;
1992 XFontBrowserWidget(display,windows,"Select",font_name);
1993 if (*font_name == '\0')
1997 Initialize font info.
1999 font_info=XLoadQueryFont(display,resource_info->font_name[
2001 if (font_info == (XFontStruct *) NULL)
2003 XNoticeWidget(display,windows,"Unable to load font:",
2004 resource_info->font_name[font_number]);
2007 font_id=(unsigned int) font_number;
2008 (void) XFreeFont(display,font_info);
2011 case AnnotateFontColorCommand:
2014 Initialize menu selections.
2016 for (i=0; i < (int) (MaxNumberPens-2); i++)
2017 ColorMenu[i]=resource_info->pen_colors[i];
2018 ColorMenu[MaxNumberPens-2]="transparent";
2019 ColorMenu[MaxNumberPens-1]="Browser...";
2020 ColorMenu[MaxNumberPens]=(const char *) NULL;
2022 Select a pen color from the pop-up menu.
2024 pen_number=XMenuWidget(display,windows,AnnotateMenu[id],
2025 (const char **) ColorMenu,command);
2028 transparent_pen=pen_number == (MaxNumberPens-2) ? MagickTrue :
2030 if( IfMagickTrue(transparent_pen) )
2032 if (pen_number == (MaxNumberPens-1))
2035 color_name[MaxTextExtent] = "gray";
2038 Select a pen color from a dialog.
2040 resource_info->pen_colors[pen_number]=color_name;
2041 XColorBrowserWidget(display,windows,"Select",color_name);
2042 if (*color_name == '\0')
2048 (void) XParseColor(display,windows->map_info->colormap,
2049 resource_info->pen_colors[pen_number],&color);
2050 XBestPixel(display,windows->map_info->colormap,(XColor *) NULL,
2051 (unsigned int) MaxColors,&color);
2052 windows->pixel_info->pen_colors[pen_number]=color;
2053 pen_id=(unsigned int) pen_number;
2056 case AnnotateBackgroundColorCommand:
2059 Initialize menu selections.
2061 for (i=0; i < (int) (MaxNumberPens-2); i++)
2062 ColorMenu[i]=resource_info->pen_colors[i];
2063 ColorMenu[MaxNumberPens-2]="transparent";
2064 ColorMenu[MaxNumberPens-1]="Browser...";
2065 ColorMenu[MaxNumberPens]=(const char *) NULL;
2067 Select a pen color from the pop-up menu.
2069 pen_number=XMenuWidget(display,windows,AnnotateMenu[id],
2070 (const char **) ColorMenu,command);
2073 transparent_box=pen_number == (MaxNumberPens-2) ? MagickTrue :
2075 if( IfMagickTrue(transparent_box) )
2077 if (pen_number == (MaxNumberPens-1))
2080 color_name[MaxTextExtent] = "gray";
2083 Select a pen color from a dialog.
2085 resource_info->pen_colors[pen_number]=color_name;
2086 XColorBrowserWidget(display,windows,"Select",color_name);
2087 if (*color_name == '\0')
2093 (void) XParseColor(display,windows->map_info->colormap,
2094 resource_info->pen_colors[pen_number],&color);
2095 XBestPixel(display,windows->map_info->colormap,(XColor *) NULL,
2096 (unsigned int) MaxColors,&color);
2097 windows->pixel_info->pen_colors[pen_number]=color;
2098 box_id=(unsigned int) pen_number;
2101 case AnnotateRotateCommand:
2107 angle[MaxTextExtent] = "30.0";
2125 Select a command from the pop-up menu.
2127 entry=XMenuWidget(display,windows,AnnotateMenu[id],RotateMenu,
2133 degrees=StringToDouble(RotateMenu[entry],(char **) NULL);
2136 (void) XDialogWidget(display,windows,"OK","Enter rotation angle:",
2140 degrees=StringToDouble(angle,(char **) NULL);
2143 case AnnotateHelpCommand:
2145 XTextViewWidget(display,resource_info,windows,MagickFalse,
2146 "Help Viewer - Image Annotation",ImageAnnotateHelp);
2149 case AnnotateDismissCommand:
2167 if (event.xbutton.button != Button1)
2169 if (event.xbutton.window != windows->image.id)
2172 Change to text entering mode.
2185 if (event.xkey.window != windows->image.id)
2188 Respond to a user key press.
2190 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
2191 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
2192 switch ((int) key_symbol)
2207 XTextViewWidget(display,resource_info,windows,MagickFalse,
2208 "Help Viewer - Image Annotation",ImageAnnotateHelp);
2213 (void) XBell(display,0);
2222 Map and unmap Info widget as cursor crosses its boundaries.
2226 if( IfMagickTrue(windows->info.mapped) )
2228 if ((x < (int) (windows->info.x+windows->info.width)) &&
2229 (y < (int) (windows->info.y+windows->info.height)))
2230 (void) XWithdrawWindow(display,windows->info.id,
2231 windows->info.screen);
2234 if ((x > (int) (windows->info.x+windows->info.width)) ||
2235 (y > (int) (windows->info.y+windows->info.height)))
2236 (void) XMapWindow(display,windows->info.id);
2242 } while ((state & ExitState) == 0);
2243 (void) XSelectInput(display,windows->image.id,
2244 windows->image.attributes.event_mask);
2245 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
2246 if ((state & EscapeState) != 0)
2249 Set font info and check boundary conditions.
2251 font_info=XLoadQueryFont(display,resource_info->font_name[font_id]);
2252 if (font_info == (XFontStruct *) NULL)
2254 XNoticeWidget(display,windows,"Unable to load font:",
2255 resource_info->font_name[font_id]);
2256 font_info=windows->font_info;
2258 if ((x+font_info->max_bounds.width) >= (int) windows->image.width)
2259 x=(int) windows->image.width-font_info->max_bounds.width;
2260 if (y < (int) (font_info->ascent+font_info->descent))
2261 y=(int) font_info->ascent+font_info->descent;
2262 if (((int) font_info->max_bounds.width > (int) windows->image.width) ||
2263 ((font_info->ascent+font_info->descent) >= (int) windows->image.height))
2264 return(MagickFalse);
2266 Initialize annotate structure.
2268 annotate_info=(XAnnotateInfo *) AcquireMagickMemory(sizeof(*annotate_info));
2269 if (annotate_info == (XAnnotateInfo *) NULL)
2270 return(MagickFalse);
2271 XGetAnnotateInfo(annotate_info);
2274 if( IfMagickFalse(transparent_box) && IfMagickFalse(transparent_pen))
2275 annotate_info->stencil=OpaqueStencil;
2277 if( IfMagickFalse(transparent_box) )
2278 annotate_info->stencil=BackgroundStencil;
2280 annotate_info->stencil=ForegroundStencil;
2281 annotate_info->height=(unsigned int) font_info->ascent+font_info->descent;
2282 annotate_info->degrees=degrees;
2283 annotate_info->font_info=font_info;
2284 annotate_info->text=(char *) AcquireQuantumMemory((size_t)
2285 windows->image.width/MagickMax((ssize_t) font_info->min_bounds.width,1)+2UL,
2286 sizeof(*annotate_info->text));
2287 if (annotate_info->text == (char *) NULL)
2288 return(MagickFalse);
2290 Create cursor and set graphic context.
2292 cursor=XCreateFontCursor(display,XC_pencil);
2293 (void) XCheckDefineCursor(display,windows->image.id,cursor);
2294 annotate_context=windows->image.annotate_context;
2295 (void) XSetFont(display,annotate_context,font_info->fid);
2296 (void) XSetBackground(display,annotate_context,
2297 windows->pixel_info->pen_colors[box_id].pixel);
2298 (void) XSetForeground(display,annotate_context,
2299 windows->pixel_info->pen_colors[pen_id].pixel);
2301 Begin annotating the image with text.
2303 (void) CloneString(&windows->command.name,"Text");
2304 windows->command.data=0;
2305 (void) XCommandWidget(display,windows,TextMenu,(XEvent *) NULL);
2307 (void) XDrawString(display,windows->image.id,annotate_context,x,y,"_",1);
2308 text_event.xexpose.width=(int) font_info->max_bounds.width;
2309 text_event.xexpose.height=font_info->max_bounds.ascent+
2310 font_info->max_bounds.descent;
2311 p=annotate_info->text;
2315 Display text cursor.
2318 (void) XDrawString(display,windows->image.id,annotate_context,x,y,"_",1);
2320 Wait for next event.
2322 XScreenEvent(display,windows,&event,exception);
2323 if (event.xany.window == windows->command.id)
2326 Select a command from the Command widget.
2328 (void) XSetBackground(display,annotate_context,
2329 windows->pixel_info->background_color.pixel);
2330 (void) XSetForeground(display,annotate_context,
2331 windows->pixel_info->foreground_color.pixel);
2332 id=XCommandWidget(display,windows,AnnotateMenu,&event);
2333 (void) XSetBackground(display,annotate_context,
2334 windows->pixel_info->pen_colors[box_id].pixel);
2335 (void) XSetForeground(display,annotate_context,
2336 windows->pixel_info->pen_colors[pen_id].pixel);
2339 switch (TextCommands[id])
2341 case TextHelpCommand:
2343 XTextViewWidget(display,resource_info,windows,MagickFalse,
2344 "Help Viewer - Image Annotation",ImageAnnotateHelp);
2345 (void) XCheckDefineCursor(display,windows->image.id,cursor);
2348 case TextApplyCommand:
2351 Finished annotating.
2353 annotate_info->width=(unsigned int) XTextWidth(font_info,
2354 annotate_info->text,(int) strlen(annotate_info->text));
2355 XRefreshWindow(display,&windows->image,&text_event);
2367 text_event.xexpose.x=x;
2368 text_event.xexpose.y=y-font_info->max_bounds.ascent;
2369 (void) XClearArea(display,windows->image.id,x,text_event.xexpose.y,
2370 (unsigned int) text_event.xexpose.width,(unsigned int)
2371 text_event.xexpose.height,MagickFalse);
2372 XRefreshWindow(display,&windows->image,&text_event);
2377 if (event.xbutton.window != windows->image.id)
2379 if (event.xbutton.button == Button2)
2382 Request primary selection.
2384 (void) XConvertSelection(display,XA_PRIMARY,XA_STRING,XA_STRING,
2385 windows->image.id,CurrentTime);
2392 if (event.xexpose.count == 0)
2398 Refresh Image window.
2400 XRefreshWindow(display,&windows->image,(XEvent *) NULL);
2401 text_info=annotate_info;
2402 while (text_info != (XAnnotateInfo *) NULL)
2404 if (annotate_info->stencil == ForegroundStencil)
2405 (void) XDrawString(display,windows->image.id,annotate_context,
2406 text_info->x,text_info->y,text_info->text,
2407 (int) strlen(text_info->text));
2409 (void) XDrawImageString(display,windows->image.id,
2410 annotate_context,text_info->x,text_info->y,text_info->text,
2411 (int) strlen(text_info->text));
2412 text_info=text_info->previous;
2414 (void) XDrawString(display,windows->image.id,annotate_context,
2424 if (event.xkey.window != windows->image.id)
2427 Respond to a user key press.
2429 length=XLookupString((XKeyEvent *) &event.xkey,command,(int)
2430 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
2431 *(command+length)='\0';
2432 if (((event.xkey.state & ControlMask) != 0) ||
2433 ((event.xkey.state & Mod1Mask) != 0))
2434 state|=ModifierState;
2435 if ((state & ModifierState) != 0)
2436 switch ((int) key_symbol)
2441 key_symbol=DeleteCommand;
2447 switch ((int) key_symbol)
2452 Erase one character.
2454 if (p == annotate_info->text)
2456 if (annotate_info->previous == (XAnnotateInfo *) NULL)
2461 Go to end of the previous line of text.
2463 annotate_info=annotate_info->previous;
2464 p=annotate_info->text;
2465 x=annotate_info->x+annotate_info->width;
2467 if (annotate_info->width != 0)
2468 p+=strlen(annotate_info->text);
2473 x-=XTextWidth(font_info,p,1);
2474 text_event.xexpose.x=x;
2475 text_event.xexpose.y=y-font_info->max_bounds.ascent;
2476 XRefreshWindow(display,&windows->image,&text_event);
2479 case XK_bracketleft:
2481 key_symbol=XK_Escape;
2487 Erase the entire line of text.
2489 while (p != annotate_info->text)
2492 x-=XTextWidth(font_info,p,1);
2493 text_event.xexpose.x=x;
2494 XRefreshWindow(display,&windows->image,&text_event);
2502 Finished annotating.
2504 annotate_info->width=(unsigned int) XTextWidth(font_info,
2505 annotate_info->text,(int) strlen(annotate_info->text));
2506 XRefreshWindow(display,&windows->image,&text_event);
2513 Draw a single character on the Image window.
2515 if ((state & ModifierState) != 0)
2517 if (*command == '\0')
2520 if (annotate_info->stencil == ForegroundStencil)
2521 (void) XDrawString(display,windows->image.id,annotate_context,
2524 (void) XDrawImageString(display,windows->image.id,
2525 annotate_context,x,y,p,1);
2526 x+=XTextWidth(font_info,p,1);
2528 if ((x+font_info->max_bounds.width) < (int) windows->image.width)
2535 Advance to the next line of text.
2538 annotate_info->width=(unsigned int) XTextWidth(font_info,
2539 annotate_info->text,(int) strlen(annotate_info->text));
2540 if (annotate_info->next != (XAnnotateInfo *) NULL)
2543 Line of text already exists.
2545 annotate_info=annotate_info->next;
2548 p=annotate_info->text;
2551 annotate_info->next=(XAnnotateInfo *) AcquireMagickMemory(
2552 sizeof(*annotate_info->next));
2553 if (annotate_info->next == (XAnnotateInfo *) NULL)
2554 return(MagickFalse);
2555 *annotate_info->next=(*annotate_info);
2556 annotate_info->next->previous=annotate_info;
2557 annotate_info=annotate_info->next;
2558 annotate_info->text=(char *) AcquireQuantumMemory((size_t)
2559 windows->image.width/MagickMax((ssize_t)
2560 font_info->min_bounds.width,1)+2UL,sizeof(*annotate_info->text));
2561 if (annotate_info->text == (char *) NULL)
2562 return(MagickFalse);
2563 annotate_info->y+=annotate_info->height;
2564 if (annotate_info->y > (int) windows->image.height)
2565 annotate_info->y=(int) annotate_info->height;
2566 annotate_info->next=(XAnnotateInfo *) NULL;
2569 p=annotate_info->text;
2578 Respond to a user key release.
2580 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
2581 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
2582 state&=(~ModifierState);
2585 case SelectionNotify:
2601 Obtain response from primary selection.
2603 if (event.xselection.property == (Atom) None)
2605 status=XGetWindowProperty(display,event.xselection.requestor,
2606 event.xselection.property,0L,(long) MaxTextExtent,True,XA_STRING,
2607 &type,&format,&length,&after,&data);
2608 if ((status != Success) || (type != XA_STRING) || (format == 32) ||
2612 Annotate Image window with primary selection.
2614 for (i=0; i < (ssize_t) length; i++)
2616 if ((char) data[i] != '\n')
2619 Draw a single character on the Image window.
2622 (void) XDrawString(display,windows->image.id,annotate_context,
2624 x+=XTextWidth(font_info,p,1);
2626 if ((x+font_info->max_bounds.width) < (int) windows->image.width)
2630 Advance to the next line of text.
2633 annotate_info->width=(unsigned int) XTextWidth(font_info,
2634 annotate_info->text,(int) strlen(annotate_info->text));
2635 if (annotate_info->next != (XAnnotateInfo *) NULL)
2638 Line of text already exists.
2640 annotate_info=annotate_info->next;
2643 p=annotate_info->text;
2646 annotate_info->next=(XAnnotateInfo *) AcquireMagickMemory(
2647 sizeof(*annotate_info->next));
2648 if (annotate_info->next == (XAnnotateInfo *) NULL)
2649 return(MagickFalse);
2650 *annotate_info->next=(*annotate_info);
2651 annotate_info->next->previous=annotate_info;
2652 annotate_info=annotate_info->next;
2653 annotate_info->text=(char *) AcquireQuantumMemory((size_t)
2654 windows->image.width/MagickMax((ssize_t)
2655 font_info->min_bounds.width,1)+2UL,sizeof(*annotate_info->text));
2656 if (annotate_info->text == (char *) NULL)
2657 return(MagickFalse);
2658 annotate_info->y+=annotate_info->height;
2659 if (annotate_info->y > (int) windows->image.height)
2660 annotate_info->y=(int) annotate_info->height;
2661 annotate_info->next=(XAnnotateInfo *) NULL;
2664 p=annotate_info->text;
2666 (void) XFree((void *) data);
2672 } while ((state & ExitState) == 0);
2673 (void) XFreeCursor(display,cursor);
2675 Annotation is relative to image configuration.
2677 width=(unsigned int) image->columns;
2678 height=(unsigned int) image->rows;
2681 if (windows->image.crop_geometry != (char *) NULL)
2682 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
2684 Initialize annotated image.
2686 XSetCursorState(display,windows,MagickTrue);
2687 XCheckRefreshWindows(display,windows);
2688 while (annotate_info != (XAnnotateInfo *) NULL)
2690 if (annotate_info->width == 0)
2693 No text on this line-- go to the next line of text.
2695 previous_info=annotate_info->previous;
2696 annotate_info->text=(char *)
2697 RelinquishMagickMemory(annotate_info->text);
2698 annotate_info=(XAnnotateInfo *) RelinquishMagickMemory(annotate_info);
2699 annotate_info=previous_info;
2703 Determine pixel index for box and pen color.
2705 windows->pixel_info->box_color=windows->pixel_info->pen_colors[box_id];
2706 if (windows->pixel_info->colors != 0)
2707 for (i=0; i < (ssize_t) windows->pixel_info->colors; i++)
2708 if (windows->pixel_info->pixels[i] ==
2709 windows->pixel_info->pen_colors[box_id].pixel)
2711 windows->pixel_info->box_index=(unsigned short) i;
2714 windows->pixel_info->pen_color=windows->pixel_info->pen_colors[pen_id];
2715 if (windows->pixel_info->colors != 0)
2716 for (i=0; i < (ssize_t) windows->pixel_info->colors; i++)
2717 if (windows->pixel_info->pixels[i] ==
2718 windows->pixel_info->pen_colors[pen_id].pixel)
2720 windows->pixel_info->pen_index=(unsigned short) i;
2724 Define the annotate geometry string.
2726 annotate_info->x=(int)
2727 width*(annotate_info->x+windows->image.x)/windows->image.ximage->width;
2728 annotate_info->y=(int) height*(annotate_info->y-font_info->ascent+
2729 windows->image.y)/windows->image.ximage->height;
2730 (void) FormatLocaleString(annotate_info->geometry,MaxTextExtent,
2731 "%ux%u%+d%+d",width*annotate_info->width/windows->image.ximage->width,
2732 height*annotate_info->height/windows->image.ximage->height,
2733 annotate_info->x+x,annotate_info->y+y);
2735 Annotate image with text.
2737 status=XAnnotateImage(display,windows->pixel_info,annotate_info,image,
2740 return(MagickFalse);
2744 previous_info=annotate_info->previous;
2745 annotate_info->text=DestroyString(annotate_info->text);
2746 annotate_info=(XAnnotateInfo *) RelinquishMagickMemory(annotate_info);
2747 annotate_info=previous_info;
2749 (void) XSetForeground(display,annotate_context,
2750 windows->pixel_info->foreground_color.pixel);
2751 (void) XSetBackground(display,annotate_context,
2752 windows->pixel_info->background_color.pixel);
2753 (void) XSetFont(display,annotate_context,windows->font_info->fid);
2754 XSetCursorState(display,windows,MagickFalse);
2755 (void) XFreeFont(display,font_info);
2757 Update image configuration.
2759 XConfigureImageColormap(display,resource_info,windows,image,exception);
2760 (void) XConfigureImage(display,resource_info,windows,image,exception);
2765 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2769 + X B a c k g r o u n d I m a g e %
2773 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2775 % XBackgroundImage() displays the image in the background of a window.
2777 % The format of the XBackgroundImage method is:
2779 % MagickBooleanType XBackgroundImage(Display *display,
2780 % XResourceInfo *resource_info,XWindows *windows,Image **image,
2781 % ExceptionInfo *exception)
2783 % A description of each parameter follows:
2785 % o display: Specifies a connection to an X server; returned from
2788 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
2790 % o windows: Specifies a pointer to a XWindows structure.
2792 % o image: the image.
2794 % o exception: return any errors or warnings in this structure.
2797 static MagickBooleanType XBackgroundImage(Display *display,
2798 XResourceInfo *resource_info,XWindows *windows,Image **image,
2799 ExceptionInfo *exception)
2801 #define BackgroundImageTag "Background/Image"
2807 window_id[MaxTextExtent] = "root";
2810 background_resources;
2813 Put image in background.
2815 status=XDialogWidget(display,windows,"Background",
2816 "Enter window id (id 0x00 selects window with pointer):",window_id);
2817 if (*window_id == '\0')
2818 return(MagickFalse);
2819 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image,
2821 XInfoWidget(display,windows,BackgroundImageTag);
2822 XSetCursorState(display,windows,MagickTrue);
2823 XCheckRefreshWindows(display,windows);
2824 background_resources=(*resource_info);
2825 background_resources.window_id=window_id;
2826 background_resources.backdrop=IsMagickTrue(status);
2827 status=XDisplayBackgroundImage(display,&background_resources,*image,
2829 if (IfMagickTrue(status))
2830 XClientMessage(display,windows->image.id,windows->im_protocols,
2831 windows->im_retain_colors,CurrentTime);
2832 XSetCursorState(display,windows,MagickFalse);
2833 (void) XMagickCommand(display,resource_info,windows,UndoCommand,image,
2839 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2843 + X C h o p I m a g e %
2847 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2849 % XChopImage() chops the X image.
2851 % The format of the XChopImage method is:
2853 % MagickBooleanType XChopImage(Display *display,XResourceInfo *resource_info,
2854 % XWindows *windows,Image **image,ExceptionInfo *exception)
2856 % A description of each parameter follows:
2858 % o display: Specifies a connection to an X server; returned from
2861 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
2863 % o windows: Specifies a pointer to a XWindows structure.
2865 % o image: the image.
2867 % o exception: return any errors or warnings in this structure.
2870 static MagickBooleanType XChopImage(Display *display,
2871 XResourceInfo *resource_info,XWindows *windows,Image **image,
2872 ExceptionInfo *exception)
2884 direction = HorizontalChopCommand;
2886 static const ModeType
2889 ChopDirectionCommand,
2893 DirectionCommands[] =
2895 HorizontalChopCommand,
2900 text[MaxTextExtent];
2933 (void) CloneString(&windows->command.name,"Chop");
2934 windows->command.data=1;
2935 (void) XCommandWidget(display,windows,ChopMenu,(XEvent *) NULL);
2936 (void) XMapRaised(display,windows->command.id);
2937 XClientMessage(display,windows->image.id,windows->im_protocols,
2938 windows->im_update_widget,CurrentTime);
2940 Track pointer until button 1 is pressed.
2942 XQueryPosition(display,windows->image.id,&x,&y);
2943 (void) XSelectInput(display,windows->image.id,
2944 windows->image.attributes.event_mask | PointerMotionMask);
2948 if( IfMagickTrue(windows->info.mapped) )
2951 Display pointer position.
2953 (void) FormatLocaleString(text,MaxTextExtent," %+d%+d ",
2954 x+windows->image.x,y+windows->image.y);
2955 XInfoWidget(display,windows,text);
2958 Wait for next event.
2960 XScreenEvent(display,windows,&event,exception);
2961 if (event.xany.window == windows->command.id)
2964 Select a command from the Command widget.
2966 id=XCommandWidget(display,windows,ChopMenu,&event);
2969 switch (ChopCommands[id])
2971 case ChopDirectionCommand:
2974 command[MaxTextExtent];
2985 Select a command from the pop-up menu.
2987 id=XMenuWidget(display,windows,ChopMenu[id],Directions,command);
2989 direction=DirectionCommands[id];
2992 case ChopHelpCommand:
2994 XTextViewWidget(display,resource_info,windows,MagickFalse,
2995 "Help Viewer - Image Chop",ImageChopHelp);
2998 case ChopDismissCommand:
3016 if (event.xbutton.button != Button1)
3018 if (event.xbutton.window != windows->image.id)
3021 User has committed to start point of chopping line.
3023 segment_info.x1=(short int) event.xbutton.x;
3024 segment_info.x2=(short int) event.xbutton.x;
3025 segment_info.y1=(short int) event.xbutton.y;
3026 segment_info.y2=(short int) event.xbutton.y;
3037 command[MaxTextExtent];
3042 if (event.xkey.window != windows->image.id)
3045 Respond to a user key press.
3047 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
3048 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
3049 switch ((int) key_symbol)
3064 (void) XSetFunction(display,windows->image.highlight_context,
3066 XTextViewWidget(display,resource_info,windows,MagickFalse,
3067 "Help Viewer - Image Chop",ImageChopHelp);
3068 (void) XSetFunction(display,windows->image.highlight_context,
3074 (void) XBell(display,0);
3083 Map and unmap Info widget as text cursor crosses its boundaries.
3087 if( IfMagickTrue(windows->info.mapped) )
3089 if ((x < (int) (windows->info.x+windows->info.width)) &&
3090 (y < (int) (windows->info.y+windows->info.height)))
3091 (void) XWithdrawWindow(display,windows->info.id,
3092 windows->info.screen);
3095 if ((x > (int) (windows->info.x+windows->info.width)) ||
3096 (y > (int) (windows->info.y+windows->info.height)))
3097 (void) XMapWindow(display,windows->info.id);
3100 } while ((state & ExitState) == 0);
3101 (void) XSelectInput(display,windows->image.id,
3102 windows->image.attributes.event_mask);
3103 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
3104 if ((state & EscapeState) != 0)
3107 Draw line as pointer moves until the mouse button is released.
3114 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
3121 Display info and draw chopping line.
3123 if( IfMagickFalse(windows->info.mapped) )
3124 (void) XMapWindow(display,windows->info.id);
3125 (void) FormatLocaleString(text,MaxTextExtent,
3126 " %.20gx%.20g%+.20g%+.20g",(double) chop_info.width,(double)
3127 chop_info.height,(double) chop_info.x,(double) chop_info.y);
3128 XInfoWidget(display,windows,text);
3129 XHighlightLine(display,windows->image.id,
3130 windows->image.highlight_context,&segment_info);
3133 if( IfMagickTrue(windows->info.mapped) )
3134 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
3136 Wait for next event.
3138 XScreenEvent(display,windows,&event,exception);
3140 XHighlightLine(display,windows->image.id,
3141 windows->image.highlight_context,&segment_info);
3146 segment_info.x2=(short int) event.xmotion.x;
3147 segment_info.y2=(short int) event.xmotion.y;
3153 User has committed to chopping line.
3155 segment_info.x2=(short int) event.xbutton.x;
3156 segment_info.y2=(short int) event.xbutton.y;
3164 segment_info.x2=(short int) event.xmotion.x;
3165 segment_info.y2=(short int) event.xmotion.y;
3171 Check boundary conditions.
3173 if (segment_info.x2 < 0)
3176 if (segment_info.x2 > windows->image.ximage->width)
3177 segment_info.x2=windows->image.ximage->width;
3178 if (segment_info.y2 < 0)
3181 if (segment_info.y2 > windows->image.ximage->height)
3182 segment_info.y2=windows->image.ximage->height;
3183 distance=(unsigned int)
3184 (((segment_info.x2-segment_info.x1)*(segment_info.x2-segment_info.x1))+
3185 ((segment_info.y2-segment_info.y1)*(segment_info.y2-segment_info.y1)));
3187 Compute chopping geometry.
3189 if (direction == HorizontalChopCommand)
3191 chop_info.width=(size_t) (segment_info.x2-segment_info.x1+1);
3192 chop_info.x=(ssize_t) windows->image.x+segment_info.x1;
3195 if (segment_info.x1 > (int) segment_info.x2)
3197 chop_info.width=(size_t) (segment_info.x1-segment_info.x2+1);
3198 chop_info.x=(ssize_t) windows->image.x+segment_info.x2;
3204 chop_info.height=(size_t) (segment_info.y2-segment_info.y1+1);
3206 chop_info.y=(ssize_t) windows->image.y+segment_info.y1;
3207 if (segment_info.y1 > segment_info.y2)
3209 chop_info.height=(size_t) (segment_info.y1-segment_info.y2+1);
3210 chop_info.y=(ssize_t) windows->image.y+segment_info.y2;
3213 } while ((state & ExitState) == 0);
3214 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
3215 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
3219 Image chopping is relative to image configuration.
3221 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image,
3223 XSetCursorState(display,windows,MagickTrue);
3224 XCheckRefreshWindows(display,windows);
3225 windows->image.window_changes.width=windows->image.ximage->width-
3226 (unsigned int) chop_info.width;
3227 windows->image.window_changes.height=windows->image.ximage->height-
3228 (unsigned int) chop_info.height;
3229 width=(unsigned int) (*image)->columns;
3230 height=(unsigned int) (*image)->rows;
3233 if (windows->image.crop_geometry != (char *) NULL)
3234 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
3235 scale_factor=(double) width/windows->image.ximage->width;
3237 chop_info.x=(ssize_t) (scale_factor*chop_info.x+0.5);
3238 chop_info.width=(unsigned int) (scale_factor*chop_info.width+0.5);
3239 scale_factor=(double) height/windows->image.ximage->height;
3241 chop_info.y=(ssize_t) (scale_factor*chop_info.y+0.5);
3242 chop_info.height=(unsigned int) (scale_factor*chop_info.height+0.5);
3246 chop_image=ChopImage(*image,&chop_info,exception);
3247 XSetCursorState(display,windows,MagickFalse);
3248 if (chop_image == (Image *) NULL)
3249 return(MagickFalse);
3250 *image=DestroyImage(*image);
3253 Update image configuration.
3255 XConfigureImageColormap(display,resource_info,windows,*image,exception);
3256 (void) XConfigureImage(display,resource_info,windows,*image,exception);
3261 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3265 + X C o l o r E d i t I m a g e %
3269 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3271 % XColorEditImage() allows the user to interactively change the color of one
3272 % pixel for a DirectColor image or one colormap entry for a PseudoClass image.
3274 % The format of the XColorEditImage method is:
3276 % MagickBooleanType XColorEditImage(Display *display,
3277 % XResourceInfo *resource_info,XWindows *windows,Image **image,
3278 % ExceptionInfo *exception)
3280 % A description of each parameter follows:
3282 % o display: Specifies a connection to an X server; returned from
3285 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
3287 % o windows: Specifies a pointer to a XWindows structure.
3289 % o image: the image; returned from ReadImage.
3291 % o exception: return any errors or warnings in this structure.
3294 static MagickBooleanType XColorEditImage(Display *display,
3295 XResourceInfo *resource_info,XWindows *windows,Image **image,
3296 ExceptionInfo *exception)
3311 static const ModeType
3312 ColorEditCommands[] =
3314 ColorEditMethodCommand,
3315 ColorEditColorCommand,
3316 ColorEditBorderCommand,
3317 ColorEditFuzzCommand,
3318 ColorEditUndoCommand,
3319 ColorEditHelpCommand,
3320 ColorEditDismissCommand
3324 method = PointMethod;
3330 border_color = { 0, 0, 0, 0, 0, 0 };
3333 command[MaxTextExtent],
3334 text[MaxTextExtent];
3369 (void) CloneString(&windows->command.name,"Color Edit");
3370 windows->command.data=4;
3371 (void) XCommandWidget(display,windows,ColorEditMenu,(XEvent *) NULL);
3372 (void) XMapRaised(display,windows->command.id);
3373 XClientMessage(display,windows->image.id,windows->im_protocols,
3374 windows->im_update_widget,CurrentTime);
3378 cursor=XMakeCursor(display,windows->image.id,windows->map_info->colormap,
3379 resource_info->background_color,resource_info->foreground_color);
3380 (void) XCheckDefineCursor(display,windows->image.id,cursor);
3382 Track pointer until button 1 is pressed.
3384 XQueryPosition(display,windows->image.id,&x,&y);
3385 (void) XSelectInput(display,windows->image.id,
3386 windows->image.attributes.event_mask | PointerMotionMask);
3390 if( IfMagickTrue(windows->info.mapped) )
3393 Display pointer position.
3395 (void) FormatLocaleString(text,MaxTextExtent," %+d%+d ",
3396 x+windows->image.x,y+windows->image.y);
3397 XInfoWidget(display,windows,text);
3400 Wait for next event.
3402 XScreenEvent(display,windows,&event,exception);
3403 if (event.xany.window == windows->command.id)
3406 Select a command from the Command widget.
3408 id=XCommandWidget(display,windows,ColorEditMenu,&event);
3411 (void) XCheckDefineCursor(display,windows->image.id,cursor);
3414 switch (ColorEditCommands[id])
3416 case ColorEditMethodCommand:
3422 Select a method from the pop-up menu.
3424 methods=(char **) GetCommandOptions(MagickMethodOptions);
3425 if (methods == (char **) NULL)
3427 entry=XMenuWidget(display,windows,ColorEditMenu[id],
3428 (const char **) methods,command);
3430 method=(PaintMethod) ParseCommandOption(MagickMethodOptions,
3431 MagickFalse,methods[entry]);
3432 methods=DestroyStringList(methods);
3435 case ColorEditColorCommand:
3438 *ColorMenu[MaxNumberPens];
3444 Initialize menu selections.
3446 for (i=0; i < (int) (MaxNumberPens-2); i++)
3447 ColorMenu[i]=resource_info->pen_colors[i];
3448 ColorMenu[MaxNumberPens-2]="Browser...";
3449 ColorMenu[MaxNumberPens-1]=(const char *) NULL;
3451 Select a pen color from the pop-up menu.
3453 pen_number=XMenuWidget(display,windows,ColorEditMenu[id],
3454 (const char **) ColorMenu,command);
3457 if (pen_number == (MaxNumberPens-2))
3460 color_name[MaxTextExtent] = "gray";
3463 Select a pen color from a dialog.
3465 resource_info->pen_colors[pen_number]=color_name;
3466 XColorBrowserWidget(display,windows,"Select",color_name);
3467 if (*color_name == '\0')
3473 (void) XParseColor(display,windows->map_info->colormap,
3474 resource_info->pen_colors[pen_number],&color);
3475 XBestPixel(display,windows->map_info->colormap,(XColor *) NULL,
3476 (unsigned int) MaxColors,&color);
3477 windows->pixel_info->pen_colors[pen_number]=color;
3478 pen_id=(unsigned int) pen_number;
3481 case ColorEditBorderCommand:
3484 *ColorMenu[MaxNumberPens];
3490 Initialize menu selections.
3492 for (i=0; i < (int) (MaxNumberPens-2); i++)
3493 ColorMenu[i]=resource_info->pen_colors[i];
3494 ColorMenu[MaxNumberPens-2]="Browser...";
3495 ColorMenu[MaxNumberPens-1]=(const char *) NULL;
3497 Select a pen color from the pop-up menu.
3499 pen_number=XMenuWidget(display,windows,ColorEditMenu[id],
3500 (const char **) ColorMenu,command);
3503 if (pen_number == (MaxNumberPens-2))
3506 color_name[MaxTextExtent] = "gray";
3509 Select a pen color from a dialog.
3511 resource_info->pen_colors[pen_number]=color_name;
3512 XColorBrowserWidget(display,windows,"Select",color_name);
3513 if (*color_name == '\0')
3519 (void) XParseColor(display,windows->map_info->colormap,
3520 resource_info->pen_colors[pen_number],&border_color);
3523 case ColorEditFuzzCommand:
3526 fuzz[MaxTextExtent];
3541 Select a command from the pop-up menu.
3543 entry=XMenuWidget(display,windows,ColorEditMenu[id],FuzzMenu,
3549 (*image)->fuzz=StringToDoubleInterval(FuzzMenu[entry],(double)
3553 (void) (void) CopyMagickString(fuzz,"20%",MaxTextExtent);
3554 (void) XDialogWidget(display,windows,"Ok",
3555 "Enter fuzz factor (0.0 - 99.9%):",fuzz);
3558 (void) ConcatenateMagickString(fuzz,"%",MaxTextExtent);
3559 (*image)->fuzz=StringToDoubleInterval(fuzz,(double) QuantumRange+
3563 case ColorEditUndoCommand:
3565 (void) XMagickCommand(display,resource_info,windows,UndoCommand,
3569 case ColorEditHelpCommand:
3572 XTextViewWidget(display,resource_info,windows,MagickFalse,
3573 "Help Viewer - Image Annotation",ImageColorEditHelp);
3576 case ColorEditDismissCommand:
3586 (void) XCheckDefineCursor(display,windows->image.id,cursor);
3593 if (event.xbutton.button != Button1)
3595 if ((event.xbutton.window != windows->image.id) &&
3596 (event.xbutton.window != windows->magnify.id))
3603 (void) XMagickCommand(display,resource_info,windows,
3604 SaveToUndoBufferCommand,image,exception);
3605 state|=UpdateConfigurationState;
3610 if (event.xbutton.button != Button1)
3612 if ((event.xbutton.window != windows->image.id) &&
3613 (event.xbutton.window != windows->magnify.id))
3616 Update colormap information.
3620 XConfigureImageColormap(display,resource_info,windows,*image,exception);
3621 (void) XConfigureImage(display,resource_info,windows,*image,exception);
3622 XInfoWidget(display,windows,text);
3623 (void) XCheckDefineCursor(display,windows->image.id,cursor);
3624 state&=(~UpdateConfigurationState);
3634 if (event.xkey.window == windows->magnify.id)
3639 window=windows->magnify.id;
3640 while (XCheckWindowEvent(display,window,KeyPressMask,&event)) ;
3642 if (event.xkey.window != windows->image.id)
3645 Respond to a user key press.
3647 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
3648 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
3649 switch ((int) key_symbol)
3663 XTextViewWidget(display,resource_info,windows,MagickFalse,
3664 "Help Viewer - Image Annotation",ImageColorEditHelp);
3669 (void) XBell(display,0);
3678 Map and unmap Info widget as cursor crosses its boundaries.
3682 if( IfMagickTrue(windows->info.mapped) )
3684 if ((x < (int) (windows->info.x+windows->info.width)) &&
3685 (y < (int) (windows->info.y+windows->info.height)))
3686 (void) XWithdrawWindow(display,windows->info.id,
3687 windows->info.screen);
3690 if ((x > (int) (windows->info.x+windows->info.width)) ||
3691 (y > (int) (windows->info.y+windows->info.height)))
3692 (void) XMapWindow(display,windows->info.id);
3698 if (event.xany.window == windows->magnify.id)
3700 x=windows->magnify.x-windows->image.x;
3701 y=windows->magnify.y-windows->image.y;
3705 if ((state & UpdateConfigurationState) != 0)
3715 Pixel edit is relative to image configuration.
3717 (void) XClearArea(display,windows->image.id,x_offset,y_offset,1,1,
3719 color=windows->pixel_info->pen_colors[pen_id];
3720 XPutPixel(windows->image.ximage,x_offset,y_offset,color.pixel);
3721 width=(unsigned int) (*image)->columns;
3722 height=(unsigned int) (*image)->rows;
3725 if (windows->image.crop_geometry != (char *) NULL)
3726 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,
3729 (width*(windows->image.x+x_offset)/windows->image.ximage->width+x);
3731 (height*(windows->image.y+y_offset)/windows->image.ximage->height+y);
3732 if ((x_offset < 0) || (y_offset < 0))
3734 if ((x_offset >= (int) (*image)->columns) ||
3735 (y_offset >= (int) (*image)->rows))
3737 image_view=AcquireAuthenticCacheView(*image,exception);
3744 Update color information using point algorithm.
3746 if( IfMagickFalse(SetImageStorageClass(*image,DirectClass,exception)) )
3747 return(MagickFalse);
3748 q=GetCacheViewAuthenticPixels(image_view,(ssize_t)x_offset,
3749 (ssize_t) y_offset,1,1,exception);
3750 if (q == (Quantum *) NULL)
3752 SetPixelRed(*image,ScaleShortToQuantum(color.red),q);
3753 SetPixelGreen(*image,ScaleShortToQuantum(color.green),q);
3754 SetPixelBlue(*image,ScaleShortToQuantum(color.blue),q);
3755 (void) SyncCacheViewAuthenticPixels(image_view,exception);
3765 Update color information using replace algorithm.
3767 (void) GetOneCacheViewVirtualPixelInfo(image_view,(ssize_t)
3768 x_offset,(ssize_t) y_offset,&target,exception);
3769 if ((*image)->storage_class == DirectClass)
3771 for (y=0; y < (int) (*image)->rows; y++)
3773 q=GetCacheViewAuthenticPixels(image_view,0,(ssize_t) y,
3774 (*image)->columns,1,exception);
3775 if (q == (Quantum *) NULL)
3777 for (x=0; x < (int) (*image)->columns; x++)
3779 GetPixelInfoPixel(*image,q,&pixel);
3780 if (IsFuzzyEquivalencePixelInfo(&pixel,&target))
3782 SetPixelRed(*image,ScaleShortToQuantum(
3784 SetPixelGreen(*image,ScaleShortToQuantum(
3786 SetPixelBlue(*image,ScaleShortToQuantum(
3789 q+=GetPixelChannels(*image);
3791 if( IfMagickFalse(SyncCacheViewAuthenticPixels(image_view,exception)) )
3797 for (i=0; i < (ssize_t) (*image)->colors; i++)
3798 if (IsFuzzyEquivalencePixelInfo((*image)->colormap+i,&target))
3800 (*image)->colormap[i].red=(double) ScaleShortToQuantum(
3802 (*image)->colormap[i].green=(double) ScaleShortToQuantum(
3804 (*image)->colormap[i].blue=(double) ScaleShortToQuantum(
3807 (void) SyncImage(*image,exception);
3811 case FloodfillMethod:
3812 case FillToBorderMethod:
3821 Update color information using floodfill algorithm.
3823 (void) GetOneVirtualPixelInfo(*image,
3824 GetPixelCacheVirtualMethod(*image),(ssize_t) x_offset,(ssize_t)
3825 y_offset,&target,exception);
3826 if (method == FillToBorderMethod)
3829 ScaleShortToQuantum(border_color.red);
3830 target.green=(double)
3831 ScaleShortToQuantum(border_color.green);
3832 target.blue=(double)
3833 ScaleShortToQuantum(border_color.blue);
3835 draw_info=CloneDrawInfo(resource_info->image_info,
3837 (void) QueryColorCompliance(resource_info->pen_colors[pen_id],
3838 AllCompliance,&draw_info->fill,exception);
3839 (void) FloodfillPaintImage(*image,draw_info,&target,
3840 (ssize_t)x_offset,(ssize_t)y_offset,
3841 IsMagickFalse(method == FloodfillMethod),exception);
3842 draw_info=DestroyDrawInfo(draw_info);
3848 Update color information using reset algorithm.
3850 if( IfMagickFalse(SetImageStorageClass(*image,DirectClass,exception)) )
3851 return(MagickFalse);
3852 for (y=0; y < (int) (*image)->rows; y++)
3854 q=QueueCacheViewAuthenticPixels(image_view,0,(ssize_t) y,
3855 (*image)->columns,1,exception);
3856 if (q == (Quantum *) NULL)
3858 for (x=0; x < (int) (*image)->columns; x++)
3860 SetPixelRed(*image,ScaleShortToQuantum(color.red),q);
3861 SetPixelGreen(*image,ScaleShortToQuantum(color.green),q);
3862 SetPixelBlue(*image,ScaleShortToQuantum(color.blue),q);
3863 q+=GetPixelChannels(*image);
3865 if( IfMagickFalse(SyncCacheViewAuthenticPixels(image_view,exception)) )
3871 image_view=DestroyCacheView(image_view);
3872 state&=(~UpdateConfigurationState);
3874 } while ((state & ExitState) == 0);
3875 (void) XSelectInput(display,windows->image.id,
3876 windows->image.attributes.event_mask);
3877 XSetCursorState(display,windows,MagickFalse);
3878 (void) XFreeCursor(display,cursor);
3883 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3887 + X C o m p o s i t e I m a g e %
3891 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3893 % XCompositeImage() requests an image name from the user, reads the image and
3894 % composites it with the X window image at a location the user chooses with
3897 % The format of the XCompositeImage method is:
3899 % MagickBooleanType XCompositeImage(Display *display,
3900 % XResourceInfo *resource_info,XWindows *windows,Image *image,
3901 % ExceptionInfo *exception)
3903 % A description of each parameter follows:
3905 % o display: Specifies a connection to an X server; returned from
3908 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
3910 % o windows: Specifies a pointer to a XWindows structure.
3912 % o image: the image; returned from ReadImage.
3914 % o exception: return any errors or warnings in this structure.
3917 static MagickBooleanType XCompositeImage(Display *display,
3918 XResourceInfo *resource_info,XWindows *windows,Image *image,
3919 ExceptionInfo *exception)
3922 displacement_geometry[MaxTextExtent] = "30x30",
3923 filename[MaxTextExtent] = "\0";
3936 static CompositeOperator
3937 compose = CopyCompositeOp;
3939 static const ModeType
3940 CompositeCommands[] =
3942 CompositeOperatorsCommand,
3943 CompositeDissolveCommand,
3944 CompositeDisplaceCommand,
3945 CompositeHelpCommand,
3946 CompositeDismissCommand
3950 text[MaxTextExtent];
3983 Request image file name from user.
3985 XFileBrowserWidget(display,windows,"Composite",filename);
3986 if (*filename == '\0')
3991 XSetCursorState(display,windows,MagickTrue);
3992 XCheckRefreshWindows(display,windows);
3993 (void) CopyMagickString(resource_info->image_info->filename,filename,
3995 composite_image=ReadImage(resource_info->image_info,exception);
3996 CatchException(exception);
3997 XSetCursorState(display,windows,MagickFalse);
3998 if (composite_image == (Image *) NULL)
3999 return(MagickFalse);
4003 (void) CloneString(&windows->command.name,"Composite");
4004 windows->command.data=1;
4005 (void) XCommandWidget(display,windows,CompositeMenu,(XEvent *) NULL);
4006 (void) XMapRaised(display,windows->command.id);
4007 XClientMessage(display,windows->image.id,windows->im_protocols,
4008 windows->im_update_widget,CurrentTime);
4010 Track pointer until button 1 is pressed.
4012 XQueryPosition(display,windows->image.id,&x,&y);
4013 (void) XSelectInput(display,windows->image.id,
4014 windows->image.attributes.event_mask | PointerMotionMask);
4015 composite_info.x=(ssize_t) windows->image.x+x;
4016 composite_info.y=(ssize_t) windows->image.y+y;
4017 composite_info.width=0;
4018 composite_info.height=0;
4019 cursor=XCreateFontCursor(display,XC_ul_angle);
4020 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
4025 if( IfMagickTrue(windows->info.mapped) )
4028 Display pointer position.
4030 (void) FormatLocaleString(text,MaxTextExtent," %+ld%+ld ",
4031 (long) composite_info.x,(long) composite_info.y);
4032 XInfoWidget(display,windows,text);
4034 highlight_info=composite_info;
4035 highlight_info.x=composite_info.x-windows->image.x;
4036 highlight_info.y=composite_info.y-windows->image.y;
4037 XHighlightRectangle(display,windows->image.id,
4038 windows->image.highlight_context,&highlight_info);
4040 Wait for next event.
4042 XScreenEvent(display,windows,&event,exception);
4043 XHighlightRectangle(display,windows->image.id,
4044 windows->image.highlight_context,&highlight_info);
4045 if (event.xany.window == windows->command.id)
4048 Select a command from the Command widget.
4050 id=XCommandWidget(display,windows,CompositeMenu,&event);
4053 switch (CompositeCommands[id])
4055 case CompositeOperatorsCommand:
4058 command[MaxTextExtent],
4062 Select a command from the pop-up menu.
4064 operators=GetCommandOptions(MagickComposeOptions);
4065 if (operators == (char **) NULL)
4067 entry=XMenuWidget(display,windows,CompositeMenu[id],
4068 (const char **) operators,command);
4070 compose=(CompositeOperator) ParseCommandOption(
4071 MagickComposeOptions,MagickFalse,operators[entry]);
4072 operators=DestroyStringList(operators);
4075 case CompositeDissolveCommand:
4078 factor[MaxTextExtent] = "20.0";
4081 Dissolve the two images a given percent.
4083 (void) XSetFunction(display,windows->image.highlight_context,
4085 (void) XDialogWidget(display,windows,"Dissolve",
4086 "Enter the blend factor (0.0 - 99.9%):",factor);
4087 (void) XSetFunction(display,windows->image.highlight_context,
4089 if (*factor == '\0')
4091 blend=StringToDouble(factor,(char **) NULL);
4092 compose=DissolveCompositeOp;
4095 case CompositeDisplaceCommand:
4098 Get horizontal and vertical scale displacement geometry.
4100 (void) XSetFunction(display,windows->image.highlight_context,
4102 (void) XDialogWidget(display,windows,"Displace",
4103 "Enter the horizontal and vertical scale:",displacement_geometry);
4104 (void) XSetFunction(display,windows->image.highlight_context,
4106 if (*displacement_geometry == '\0')
4108 compose=DisplaceCompositeOp;
4111 case CompositeHelpCommand:
4113 (void) XSetFunction(display,windows->image.highlight_context,
4115 XTextViewWidget(display,resource_info,windows,MagickFalse,
4116 "Help Viewer - Image Composite",ImageCompositeHelp);
4117 (void) XSetFunction(display,windows->image.highlight_context,
4121 case CompositeDismissCommand:
4139 if( IfMagickTrue(image->debug) )
4140 (void) LogMagickEvent(X11Event,GetMagickModule(),
4141 "Button Press: 0x%lx %u +%d+%d",event.xbutton.window,
4142 event.xbutton.button,event.xbutton.x,event.xbutton.y);
4143 if (event.xbutton.button != Button1)
4145 if (event.xbutton.window != windows->image.id)
4150 composite_info.width=composite_image->columns;
4151 composite_info.height=composite_image->rows;
4152 (void) XCheckDefineCursor(display,windows->image.id,cursor);
4153 composite_info.x=(ssize_t) windows->image.x+event.xbutton.x;
4154 composite_info.y=(ssize_t) windows->image.y+event.xbutton.y;
4159 if( IfMagickTrue(image->debug) )
4160 (void) LogMagickEvent(X11Event,GetMagickModule(),
4161 "Button Release: 0x%lx %u +%d+%d",event.xbutton.window,
4162 event.xbutton.button,event.xbutton.x,event.xbutton.y);
4163 if (event.xbutton.button != Button1)
4165 if (event.xbutton.window != windows->image.id)
4167 if ((composite_info.width != 0) && (composite_info.height != 0))
4170 User has selected the location of the composite image.
4172 composite_info.x=(ssize_t) windows->image.x+event.xbutton.x;
4173 composite_info.y=(ssize_t) windows->image.y+event.xbutton.y;
4183 command[MaxTextExtent];
4191 if (event.xkey.window != windows->image.id)
4194 Respond to a user key press.
4196 length=XLookupString((XKeyEvent *) &event.xkey,command,(int)
4197 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
4198 *(command+length)='\0';
4199 if( IfMagickTrue(image->debug) )
4200 (void) LogMagickEvent(X11Event,GetMagickModule(),
4201 "Key press: 0x%lx (%s)",(unsigned long) key_symbol,command);
4202 switch ((int) key_symbol)
4210 composite_image=DestroyImage(composite_image);
4218 (void) XSetFunction(display,windows->image.highlight_context,
4220 XTextViewWidget(display,resource_info,windows,MagickFalse,
4221 "Help Viewer - Image Composite",ImageCompositeHelp);
4222 (void) XSetFunction(display,windows->image.highlight_context,
4228 (void) XBell(display,0);
4237 Map and unmap Info widget as text cursor crosses its boundaries.
4241 if( IfMagickTrue(windows->info.mapped) )
4243 if ((x < (int) (windows->info.x+windows->info.width)) &&
4244 (y < (int) (windows->info.y+windows->info.height)))
4245 (void) XWithdrawWindow(display,windows->info.id,
4246 windows->info.screen);
4249 if ((x > (int) (windows->info.x+windows->info.width)) ||
4250 (y > (int) (windows->info.y+windows->info.height)))
4251 (void) XMapWindow(display,windows->info.id);
4252 composite_info.x=(ssize_t) windows->image.x+x;
4253 composite_info.y=(ssize_t) windows->image.y+y;
4258 if( IfMagickTrue(image->debug) )
4259 (void) LogMagickEvent(X11Event,GetMagickModule(),"Event type: %d",
4264 } while ((state & ExitState) == 0);
4265 (void) XSelectInput(display,windows->image.id,
4266 windows->image.attributes.event_mask);
4267 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
4268 XSetCursorState(display,windows,MagickFalse);
4269 (void) XFreeCursor(display,cursor);
4270 if ((state & EscapeState) != 0)
4273 Image compositing is relative to image configuration.
4275 XSetCursorState(display,windows,MagickTrue);
4276 XCheckRefreshWindows(display,windows);
4277 width=(unsigned int) image->columns;
4278 height=(unsigned int) image->rows;
4281 if (windows->image.crop_geometry != (char *) NULL)
4282 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
4283 scale_factor=(double) width/windows->image.ximage->width;
4284 composite_info.x+=x;
4285 composite_info.x=(ssize_t) (scale_factor*composite_info.x+0.5);
4286 composite_info.width=(unsigned int) (scale_factor*composite_info.width+0.5);
4287 scale_factor=(double) height/windows->image.ximage->height;
4288 composite_info.y+=y;
4289 composite_info.y=(ssize_t) (scale_factor*composite_info.y+0.5);
4290 composite_info.height=(unsigned int) (scale_factor*composite_info.height+0.5);
4291 if ((composite_info.width != composite_image->columns) ||
4292 (composite_info.height != composite_image->rows))
4298 Scale composite image.
4300 resize_image=ResizeImage(composite_image,composite_info.width,
4301 composite_info.height,composite_image->filter,exception);
4302 composite_image=DestroyImage(composite_image);
4303 if (resize_image == (Image *) NULL)
4305 XSetCursorState(display,windows,MagickFalse);
4306 return(MagickFalse);
4308 composite_image=resize_image;
4310 if (compose == DisplaceCompositeOp)
4311 (void) SetImageArtifact(composite_image,"compose:args",
4312 displacement_geometry);
4331 Create mattes for blending.
4333 (void) SetImageAlphaChannel(composite_image,OpaqueAlphaChannel,exception);
4334 opacity=(Quantum) (ScaleQuantumToChar(QuantumRange)-
4335 ((ssize_t) ScaleQuantumToChar(QuantumRange)*blend)/100);
4336 if( IfMagickFalse(SetImageStorageClass(image,DirectClass,exception)) )
4337 return(MagickFalse);
4338 image->alpha_trait=BlendPixelTrait;
4339 image_view=AcquireAuthenticCacheView(image,exception);
4340 for (y=0; y < (int) image->rows; y++)
4342 q=GetCacheViewAuthenticPixels(image_view,0,(ssize_t) y,image->columns,1,
4344 if (q == (Quantum *) NULL)
4346 for (x=0; x < (int) image->columns; x++)
4348 SetPixelAlpha(image,opacity,q);
4349 q+=GetPixelChannels(image);
4351 if( IfMagickFalse(SyncCacheViewAuthenticPixels(image_view,exception)) )
4354 image_view=DestroyCacheView(image_view);
4357 Composite image with X Image window.
4359 (void) CompositeImage(image,composite_image,compose,MagickTrue,
4360 composite_info.x,composite_info.y,exception);
4361 composite_image=DestroyImage(composite_image);
4362 XSetCursorState(display,windows,MagickFalse);
4364 Update image configuration.
4366 XConfigureImageColormap(display,resource_info,windows,image,exception);
4367 (void) XConfigureImage(display,resource_info,windows,image,exception);
4372 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4376 + X C o n f i g u r e I m a g e %
4380 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4382 % XConfigureImage() creates a new X image. It also notifies the window
4383 % manager of the new image size and configures the transient widows.
4385 % The format of the XConfigureImage method is:
4387 % MagickBooleanType XConfigureImage(Display *display,
4388 % XResourceInfo *resource_info,XWindows *windows,Image *image,
4389 % ExceptionInfo *exception)
4391 % A description of each parameter follows:
4393 % o display: Specifies a connection to an X server; returned from
4396 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
4398 % o windows: Specifies a pointer to a XWindows structure.
4400 % o image: the image.
4402 % o exception: return any errors or warnings in this structure.
4404 % o exception: return any errors or warnings in this structure.
4407 static MagickBooleanType XConfigureImage(Display *display,
4408 XResourceInfo *resource_info,XWindows *windows,Image *image,
4409 ExceptionInfo *exception)
4412 geometry[MaxTextExtent];
4433 Dismiss if window dimensions are zero.
4435 width=(unsigned int) windows->image.window_changes.width;
4436 height=(unsigned int) windows->image.window_changes.height;
4437 if( IfMagickTrue(image->debug) )
4438 (void) LogMagickEvent(X11Event,GetMagickModule(),
4439 "Configure Image: %dx%d=>%.20gx%.20g",windows->image.ximage->width,
4440 windows->image.ximage->height,(double) width,(double) height);
4441 if ((width*height) == 0)
4446 Resize image to fit Image window dimensions.
4448 XSetCursorState(display,windows,MagickTrue);
4449 (void) XFlush(display);
4450 if (((int) width != windows->image.ximage->width) ||
4451 ((int) height != windows->image.ximage->height))
4452 image->taint=MagickTrue;
4453 windows->magnify.x=(int)
4454 width*windows->magnify.x/windows->image.ximage->width;
4455 windows->magnify.y=(int)
4456 height*windows->magnify.y/windows->image.ximage->height;
4457 windows->image.x=(int) (width*windows->image.x/windows->image.ximage->width);
4458 windows->image.y=(int)
4459 (height*windows->image.y/windows->image.ximage->height);
4460 status=XMakeImage(display,resource_info,&windows->image,image,
4461 (unsigned int) width,(unsigned int) height,exception);
4462 if( IfMagickFalse(status) )
4463 XNoticeWidget(display,windows,"Unable to configure X image:",
4464 windows->image.name);
4466 Notify window manager of the new configuration.
4468 if (resource_info->image_geometry != (char *) NULL)
4469 (void) FormatLocaleString(geometry,MaxTextExtent,"%s>!",
4470 resource_info->image_geometry);
4472 (void) FormatLocaleString(geometry,MaxTextExtent,"%ux%u+0+0>!",
4473 XDisplayWidth(display,windows->image.screen),
4474 XDisplayHeight(display,windows->image.screen));
4475 (void) ParseMetaGeometry(geometry,&x,&y,&width,&height);
4476 window_changes.width=(int) width;
4477 if (window_changes.width > XDisplayWidth(display,windows->image.screen))
4478 window_changes.width=XDisplayWidth(display,windows->image.screen);
4479 window_changes.height=(int) height;
4480 if (window_changes.height > XDisplayHeight(display,windows->image.screen))
4481 window_changes.height=XDisplayHeight(display,windows->image.screen);
4482 mask=(size_t) (CWWidth | CWHeight);
4483 if (resource_info->backdrop)
4486 window_changes.x=(int)
4487 ((XDisplayWidth(display,windows->image.screen)/2)-(width/2));
4488 window_changes.y=(int)
4489 ((XDisplayHeight(display,windows->image.screen)/2)-(height/2));
4491 (void) XReconfigureWMWindow(display,windows->image.id,windows->image.screen,
4492 (unsigned int) mask,&window_changes);
4493 (void) XClearWindow(display,windows->image.id);
4494 XRefreshWindow(display,&windows->image,(XEvent *) NULL);
4496 Update Magnify window configuration.
4498 if( IfMagickTrue(windows->magnify.mapped) )
4499 XMakeMagnifyImage(display,windows,exception);
4500 windows->pan.crop_geometry=windows->image.crop_geometry;
4501 XBestIconSize(display,&windows->pan,image);
4502 while (((windows->pan.width << 1) < MaxIconSize) &&
4503 ((windows->pan.height << 1) < MaxIconSize))
4505 windows->pan.width<<=1;
4506 windows->pan.height<<=1;
4508 if (windows->pan.geometry != (char *) NULL)
4509 (void) XParseGeometry(windows->pan.geometry,&windows->pan.x,&windows->pan.y,
4510 &windows->pan.width,&windows->pan.height);
4511 window_changes.width=(int) windows->pan.width;
4512 window_changes.height=(int) windows->pan.height;
4513 size_hints=XAllocSizeHints();
4514 if (size_hints != (XSizeHints *) NULL)
4519 size_hints->flags=PSize | PMinSize | PMaxSize;
4520 size_hints->width=window_changes.width;
4521 size_hints->height=window_changes.height;
4522 size_hints->min_width=size_hints->width;
4523 size_hints->min_height=size_hints->height;
4524 size_hints->max_width=size_hints->width;
4525 size_hints->max_height=size_hints->height;
4526 (void) XSetNormalHints(display,windows->pan.id,size_hints);
4527 (void) XFree((void *) size_hints);
4529 (void) XReconfigureWMWindow(display,windows->pan.id,windows->pan.screen,
4530 (unsigned int) (CWWidth | CWHeight),&window_changes);
4532 Update icon window configuration.
4534 windows->icon.crop_geometry=windows->image.crop_geometry;
4535 XBestIconSize(display,&windows->icon,image);
4536 window_changes.width=(int) windows->icon.width;
4537 window_changes.height=(int) windows->icon.height;
4538 (void) XReconfigureWMWindow(display,windows->icon.id,windows->icon.screen,
4539 (unsigned int) (CWWidth | CWHeight),&window_changes);
4540 XSetCursorState(display,windows,MagickFalse);
4541 return(IsMagickTrue(status));
4545 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4549 + X C r o p I m a g e %
4553 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4555 % XCropImage() allows the user to select a region of the image and crop, copy,
4556 % or cut it. For copy or cut, the image can subsequently be composited onto
4557 % the image with XPasteImage.
4559 % The format of the XCropImage method is:
4561 % MagickBooleanType XCropImage(Display *display,
4562 % XResourceInfo *resource_info,XWindows *windows,Image *image,
4563 % const ClipboardMode mode,ExceptionInfo *exception)
4565 % A description of each parameter follows:
4567 % o display: Specifies a connection to an X server; returned from
4570 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
4572 % o windows: Specifies a pointer to a XWindows structure.
4574 % o image: the image; returned from ReadImage.
4576 % o mode: This unsigned value specified whether the image should be
4577 % cropped, copied, or cut.
4579 % o exception: return any errors or warnings in this structure.
4582 static MagickBooleanType XCropImage(Display *display,
4583 XResourceInfo *resource_info,XWindows *windows,Image *image,
4584 const ClipboardMode mode,ExceptionInfo *exception)
4593 *RectifyModeMenu[] =
4601 static const ModeType
4611 RectifyDismissCommand
4618 command[MaxTextExtent],
4619 text[MaxTextExtent];
4662 (void) CloneString(&windows->command.name,"Copy");
4667 (void) CloneString(&windows->command.name,"Crop");
4672 (void) CloneString(&windows->command.name,"Cut");
4676 RectifyModeMenu[0]=windows->command.name;
4677 windows->command.data=0;
4678 (void) XCommandWidget(display,windows,CropModeMenu,(XEvent *) NULL);
4679 (void) XMapRaised(display,windows->command.id);
4680 XClientMessage(display,windows->image.id,windows->im_protocols,
4681 windows->im_update_widget,CurrentTime);
4683 Track pointer until button 1 is pressed.
4685 XQueryPosition(display,windows->image.id,&x,&y);
4686 (void) XSelectInput(display,windows->image.id,
4687 windows->image.attributes.event_mask | PointerMotionMask);
4688 crop_info.x=(ssize_t) windows->image.x+x;
4689 crop_info.y=(ssize_t) windows->image.y+y;
4692 cursor=XCreateFontCursor(display,XC_fleur);
4696 if( IfMagickTrue(windows->info.mapped) )
4699 Display pointer position.
4701 (void) FormatLocaleString(text,MaxTextExtent," %+ld%+ld ",
4702 (long) crop_info.x,(long) crop_info.y);
4703 XInfoWidget(display,windows,text);
4706 Wait for next event.
4708 XScreenEvent(display,windows,&event,exception);
4709 if (event.xany.window == windows->command.id)
4712 Select a command from the Command widget.
4714 id=XCommandWidget(display,windows,CropModeMenu,&event);
4717 switch (CropCommands[id])
4719 case CropHelpCommand:
4725 XTextViewWidget(display,resource_info,windows,MagickFalse,
4726 "Help Viewer - Image Copy",ImageCopyHelp);
4731 XTextViewWidget(display,resource_info,windows,MagickFalse,
4732 "Help Viewer - Image Crop",ImageCropHelp);
4737 XTextViewWidget(display,resource_info,windows,MagickFalse,
4738 "Help Viewer - Image Cut",ImageCutHelp);
4744 case CropDismissCommand:
4762 if (event.xbutton.button != Button1)
4764 if (event.xbutton.window != windows->image.id)
4767 Note first corner of cropping rectangle-- exit loop.
4769 (void) XCheckDefineCursor(display,windows->image.id,cursor);
4770 crop_info.x=(ssize_t) windows->image.x+event.xbutton.x;
4771 crop_info.y=(ssize_t) windows->image.y+event.xbutton.y;
4781 if (event.xkey.window != windows->image.id)
4784 Respond to a user key press.
4786 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
4787 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
4788 switch ((int) key_symbol)
4807 XTextViewWidget(display,resource_info,windows,MagickFalse,
4808 "Help Viewer - Image Copy",ImageCopyHelp);
4813 XTextViewWidget(display,resource_info,windows,MagickFalse,
4814 "Help Viewer - Image Crop",ImageCropHelp);
4819 XTextViewWidget(display,resource_info,windows,MagickFalse,
4820 "Help Viewer - Image Cut",ImageCutHelp);
4828 (void) XBell(display,0);
4836 if (event.xmotion.window != windows->image.id)
4839 Map and unmap Info widget as text cursor crosses its boundaries.
4843 if( IfMagickTrue(windows->info.mapped) )
4845 if ((x < (int) (windows->info.x+windows->info.width)) &&
4846 (y < (int) (windows->info.y+windows->info.height)))
4847 (void) XWithdrawWindow(display,windows->info.id,
4848 windows->info.screen);
4851 if ((x > (int) (windows->info.x+windows->info.width)) ||
4852 (y > (int) (windows->info.y+windows->info.height)))
4853 (void) XMapWindow(display,windows->info.id);
4854 crop_info.x=(ssize_t) windows->image.x+x;
4855 crop_info.y=(ssize_t) windows->image.y+y;
4861 } while ((state & ExitState) == 0);
4862 (void) XSelectInput(display,windows->image.id,
4863 windows->image.attributes.event_mask);
4864 if ((state & EscapeState) != 0)
4867 User want to exit without cropping.
4869 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
4870 (void) XFreeCursor(display,cursor);
4873 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
4877 Size rectangle as pointer moves until the mouse button is released.
4879 x=(int) crop_info.x;
4880 y=(int) crop_info.y;
4886 highlight_info=crop_info;
4887 highlight_info.x=crop_info.x-windows->image.x;
4888 highlight_info.y=crop_info.y-windows->image.y;
4889 if ((highlight_info.width > 3) && (highlight_info.height > 3))
4892 Display info and draw cropping rectangle.
4894 if( IfMagickFalse(windows->info.mapped) )
4895 (void) XMapWindow(display,windows->info.id);
4896 (void) FormatLocaleString(text,MaxTextExtent,
4897 " %.20gx%.20g%+.20g%+.20g",(double) crop_info.width,(double)
4898 crop_info.height,(double) crop_info.x,(double) crop_info.y);
4899 XInfoWidget(display,windows,text);
4900 XHighlightRectangle(display,windows->image.id,
4901 windows->image.highlight_context,&highlight_info);
4904 if( IfMagickTrue(windows->info.mapped) )
4905 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
4907 Wait for next event.
4909 XScreenEvent(display,windows,&event,exception);
4910 if ((highlight_info.width > 3) && (highlight_info.height > 3))
4911 XHighlightRectangle(display,windows->image.id,
4912 windows->image.highlight_context,&highlight_info);
4917 crop_info.x=(ssize_t) windows->image.x+event.xbutton.x;
4918 crop_info.y=(ssize_t) windows->image.y+event.xbutton.y;
4924 User has committed to cropping rectangle.
4926 crop_info.x=(ssize_t) windows->image.x+event.xbutton.x;
4927 crop_info.y=(ssize_t) windows->image.y+event.xbutton.y;
4928 XSetCursorState(display,windows,MagickFalse);
4930 windows->command.data=0;
4931 (void) XCommandWidget(display,windows,RectifyModeMenu,
4939 crop_info.x=(ssize_t) windows->image.x+event.xmotion.x;
4940 crop_info.y=(ssize_t) windows->image.y+event.xmotion.y;
4945 if ((((int) crop_info.x != x) && ((int) crop_info.y != y)) ||
4946 ((state & ExitState) != 0))
4949 Check boundary conditions.
4951 if (crop_info.x < 0)
4954 if (crop_info.x > (ssize_t) windows->image.ximage->width)
4955 crop_info.x=(ssize_t) windows->image.ximage->width;
4956 if ((int) crop_info.x < x)
4957 crop_info.width=(unsigned int) (x-crop_info.x);
4960 crop_info.width=(unsigned int) (crop_info.x-x);
4961 crop_info.x=(ssize_t) x;
4963 if (crop_info.y < 0)
4966 if (crop_info.y > (ssize_t) windows->image.ximage->height)
4967 crop_info.y=(ssize_t) windows->image.ximage->height;
4968 if ((int) crop_info.y < y)
4969 crop_info.height=(unsigned int) (y-crop_info.y);
4972 crop_info.height=(unsigned int) (crop_info.y-y);
4973 crop_info.y=(ssize_t) y;
4976 } while ((state & ExitState) == 0);
4978 Wait for user to grab a corner of the rectangle or press return.
4981 (void) XMapWindow(display,windows->info.id);
4984 if( IfMagickTrue(windows->info.mapped) )
4987 Display pointer position.
4989 (void) FormatLocaleString(text,MaxTextExtent,
4990 " %.20gx%.20g%+.20g%+.20g",(double) crop_info.width,(double)
4991 crop_info.height,(double) crop_info.x,(double) crop_info.y);
4992 XInfoWidget(display,windows,text);
4994 highlight_info=crop_info;
4995 highlight_info.x=crop_info.x-windows->image.x;
4996 highlight_info.y=crop_info.y-windows->image.y;
4997 if ((highlight_info.width <= 3) || (highlight_info.height <= 3))
5003 XHighlightRectangle(display,windows->image.id,
5004 windows->image.highlight_context,&highlight_info);
5005 XScreenEvent(display,windows,&event,exception);
5006 if (event.xany.window == windows->command.id)
5009 Select a command from the Command widget.
5011 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
5012 id=XCommandWidget(display,windows,RectifyModeMenu,&event);
5013 (void) XSetFunction(display,windows->image.highlight_context,
5015 XHighlightRectangle(display,windows->image.id,
5016 windows->image.highlight_context,&highlight_info);
5018 switch (RectifyCommands[id])
5020 case RectifyCopyCommand:
5025 case RectifyHelpCommand:
5027 (void) XSetFunction(display,windows->image.highlight_context,
5033 XTextViewWidget(display,resource_info,windows,MagickFalse,
5034 "Help Viewer - Image Copy",ImageCopyHelp);
5039 XTextViewWidget(display,resource_info,windows,MagickFalse,
5040 "Help Viewer - Image Crop",ImageCropHelp);
5045 XTextViewWidget(display,resource_info,windows,MagickFalse,
5046 "Help Viewer - Image Cut",ImageCutHelp);
5050 (void) XSetFunction(display,windows->image.highlight_context,
5054 case RectifyDismissCommand:
5068 XHighlightRectangle(display,windows->image.id,
5069 windows->image.highlight_context,&highlight_info);
5074 if (event.xbutton.button != Button1)
5076 if (event.xbutton.window != windows->image.id)
5078 x=windows->image.x+event.xbutton.x;
5079 y=windows->image.y+event.xbutton.y;
5080 if ((x < (int) (crop_info.x+RoiDelta)) &&
5081 (x > (int) (crop_info.x-RoiDelta)) &&
5082 (y < (int) (crop_info.y+RoiDelta)) &&
5083 (y > (int) (crop_info.y-RoiDelta)))
5085 crop_info.x=(ssize_t) (crop_info.x+crop_info.width);
5086 crop_info.y=(ssize_t) (crop_info.y+crop_info.height);
5087 state|=UpdateConfigurationState;
5090 if ((x < (int) (crop_info.x+RoiDelta)) &&
5091 (x > (int) (crop_info.x-RoiDelta)) &&
5092 (y < (int) (crop_info.y+crop_info.height+RoiDelta)) &&
5093 (y > (int) (crop_info.y+crop_info.height-RoiDelta)))
5095 crop_info.x=(ssize_t) (crop_info.x+crop_info.width);
5096 state|=UpdateConfigurationState;
5099 if ((x < (int) (crop_info.x+crop_info.width+RoiDelta)) &&
5100 (x > (int) (crop_info.x+crop_info.width-RoiDelta)) &&
5101 (y < (int) (crop_info.y+RoiDelta)) &&
5102 (y > (int) (crop_info.y-RoiDelta)))
5104 crop_info.y=(ssize_t) (crop_info.y+crop_info.height);
5105 state|=UpdateConfigurationState;
5108 if ((x < (int) (crop_info.x+crop_info.width+RoiDelta)) &&
5109 (x > (int) (crop_info.x+crop_info.width-RoiDelta)) &&
5110 (y < (int) (crop_info.y+crop_info.height+RoiDelta)) &&
5111 (y > (int) (crop_info.y+crop_info.height-RoiDelta)))
5113 state|=UpdateConfigurationState;
5119 if (event.xbutton.window == windows->pan.id)
5120 if ((highlight_info.x != crop_info.x-windows->image.x) ||
5121 (highlight_info.y != crop_info.y-windows->image.y))
5122 XHighlightRectangle(display,windows->image.id,
5123 windows->image.highlight_context,&highlight_info);
5124 (void) XSetSelectionOwner(display,XA_PRIMARY,windows->image.id,
5125 event.xbutton.time);
5130 if (event.xexpose.window == windows->image.id)
5131 if (event.xexpose.count == 0)
5133 event.xexpose.x=(int) highlight_info.x;
5134 event.xexpose.y=(int) highlight_info.y;
5135 event.xexpose.width=(int) highlight_info.width;
5136 event.xexpose.height=(int) highlight_info.height;
5137 XRefreshWindow(display,&windows->image,&event);
5139 if (event.xexpose.window == windows->info.id)
5140 if (event.xexpose.count == 0)
5141 XInfoWidget(display,windows,text);
5146 if (event.xkey.window != windows->image.id)
5149 Respond to a user key press.
5151 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
5152 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
5153 switch ((int) key_symbol)
5166 crop_info.x=(ssize_t) (windows->image.width/2L-
5167 crop_info.width/2L);
5168 crop_info.y=(ssize_t) (windows->image.height/2L-
5169 crop_info.height/2L);
5201 (void) XSetFunction(display,windows->image.highlight_context,
5207 XTextViewWidget(display,resource_info,windows,MagickFalse,
5208 "Help Viewer - Image Copy",ImageCopyHelp);
5213 XTextViewWidget(display,resource_info,windows,MagickFalse,
5214 "Help Viewer - Image Cropg",ImageCropHelp);
5219 XTextViewWidget(display,resource_info,windows,MagickFalse,
5220 "Help Viewer - Image Cutg",ImageCutHelp);
5224 (void) XSetFunction(display,windows->image.highlight_context,
5230 (void) XBell(display,0);
5234 (void) XSetSelectionOwner(display,XA_PRIMARY,windows->image.id,
5242 if (event.xmotion.window != windows->image.id)
5245 Map and unmap Info widget as text cursor crosses its boundaries.
5249 if( IfMagickTrue(windows->info.mapped) )
5251 if ((x < (int) (windows->info.x+windows->info.width)) &&
5252 (y < (int) (windows->info.y+windows->info.height)))
5253 (void) XWithdrawWindow(display,windows->info.id,
5254 windows->info.screen);
5257 if ((x > (int) (windows->info.x+windows->info.width)) ||
5258 (y > (int) (windows->info.y+windows->info.height)))
5259 (void) XMapWindow(display,windows->info.id);
5260 crop_info.x=(ssize_t) windows->image.x+event.xmotion.x;
5261 crop_info.y=(ssize_t) windows->image.y+event.xmotion.y;
5264 case SelectionRequest:
5269 XSelectionRequestEvent
5273 Set primary selection.
5275 (void) FormatLocaleString(text,MaxTextExtent,
5276 "%.20gx%.20g%+.20g%+.20g",(double) crop_info.width,(double)
5277 crop_info.height,(double) crop_info.x,(double) crop_info.y);
5278 request=(&(event.xselectionrequest));
5279 (void) XChangeProperty(request->display,request->requestor,
5280 request->property,request->target,8,PropModeReplace,
5281 (unsigned char *) text,(int) strlen(text));
5282 notify.type=SelectionNotify;
5283 notify.display=request->display;
5284 notify.requestor=request->requestor;
5285 notify.selection=request->selection;
5286 notify.target=request->target;
5287 notify.time=request->time;
5288 if (request->property == None)
5289 notify.property=request->target;
5291 notify.property=request->property;
5292 (void) XSendEvent(request->display,request->requestor,False,0,
5293 (XEvent *) ¬ify);
5298 if ((state & UpdateConfigurationState) != 0)
5300 (void) XPutBackEvent(display,&event);
5301 (void) XCheckDefineCursor(display,windows->image.id,cursor);
5304 } while ((state & ExitState) == 0);
5305 } while ((state & ExitState) == 0);
5306 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
5307 XSetCursorState(display,windows,MagickFalse);
5308 if ((state & EscapeState) != 0)
5310 if (mode == CropMode)
5311 if (((int) crop_info.width != windows->image.ximage->width) ||
5312 ((int) crop_info.height != windows->image.ximage->height))
5315 Reconfigure Image window as defined by cropping rectangle.
5317 XSetCropGeometry(display,windows,&crop_info,image);
5318 windows->image.window_changes.width=(int) crop_info.width;
5319 windows->image.window_changes.height=(int) crop_info.height;
5320 (void) XConfigureImage(display,resource_info,windows,image,exception);
5324 Copy image before applying image transforms.
5326 XSetCursorState(display,windows,MagickTrue);
5327 XCheckRefreshWindows(display,windows);
5328 width=(unsigned int) image->columns;
5329 height=(unsigned int) image->rows;
5332 if (windows->image.crop_geometry != (char *) NULL)
5333 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
5334 scale_factor=(double) width/windows->image.ximage->width;
5336 crop_info.x=(ssize_t) (scale_factor*crop_info.x+0.5);
5337 crop_info.width=(unsigned int) (scale_factor*crop_info.width+0.5);
5338 scale_factor=(double) height/windows->image.ximage->height;
5340 crop_info.y=(ssize_t) (scale_factor*crop_info.y+0.5);
5341 crop_info.height=(unsigned int) (scale_factor*crop_info.height+0.5);
5342 crop_image=CropImage(image,&crop_info,exception);
5343 XSetCursorState(display,windows,MagickFalse);
5344 if (crop_image == (Image *) NULL)
5345 return(MagickFalse);
5346 if (resource_info->copy_image != (Image *) NULL)
5347 resource_info->copy_image=DestroyImage(resource_info->copy_image);
5348 resource_info->copy_image=crop_image;
5349 if (mode == CopyMode)
5351 (void) XConfigureImage(display,resource_info,windows,image,exception);
5357 if( IfMagickFalse(SetImageStorageClass(image,DirectClass,exception)) )
5358 return(MagickFalse);
5359 image->alpha_trait=BlendPixelTrait;
5360 image_view=AcquireAuthenticCacheView(image,exception);
5361 for (y=0; y < (int) crop_info.height; y++)
5363 q=GetCacheViewAuthenticPixels(image_view,crop_info.x,y+crop_info.y,
5364 crop_info.width,1,exception);
5365 if (q == (Quantum *) NULL)
5367 for (x=0; x < (int) crop_info.width; x++)
5369 SetPixelAlpha(image,TransparentAlpha,q);
5370 q+=GetPixelChannels(image);
5372 if( IfMagickFalse(SyncCacheViewAuthenticPixels(image_view,exception)) )
5375 image_view=DestroyCacheView(image_view);
5377 Update image configuration.
5379 XConfigureImageColormap(display,resource_info,windows,image,exception);
5380 (void) XConfigureImage(display,resource_info,windows,image,exception);
5385 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5389 + X D r a w I m a g e %
5393 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5395 % XDrawEditImage() draws a graphic element (point, line, rectangle, etc.) on
5398 % The format of the XDrawEditImage method is:
5400 % MagickBooleanType XDrawEditImage(Display *display,
5401 % XResourceInfo *resource_info,XWindows *windows,Image **image,
5402 % ExceptionInfo *exception)
5404 % A description of each parameter follows:
5406 % o display: Specifies a connection to an X server; returned from
5409 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
5411 % o windows: Specifies a pointer to a XWindows structure.
5413 % o image: the image.
5415 % o exception: return any errors or warnings in this structure.
5418 static MagickBooleanType XDrawEditImage(Display *display,
5419 XResourceInfo *resource_info,XWindows *windows,Image **image,
5420 ExceptionInfo *exception)
5436 element = PointElement;
5438 static const ModeType
5451 stipple = (Pixmap) NULL;
5458 command[MaxTextExtent],
5459 text[MaxTextExtent];
5508 Allocate polygon info.
5510 max_coordinates=2048;
5511 coordinate_info=(XPoint *) AcquireQuantumMemory((size_t) max_coordinates,
5512 sizeof(*coordinate_info));
5513 if (coordinate_info == (XPoint *) NULL)
5515 (void) ThrowMagickException(exception,GetMagickModule(),
5516 ResourceLimitError,"MemoryAllocationFailed","`%s'","...");
5517 return(MagickFalse);
5522 (void) CloneString(&windows->command.name,"Draw");
5523 windows->command.data=4;
5524 (void) XCommandWidget(display,windows,DrawMenu,(XEvent *) NULL);
5525 (void) XMapRaised(display,windows->command.id);
5526 XClientMessage(display,windows->image.id,windows->im_protocols,
5527 windows->im_update_widget,CurrentTime);
5529 Wait for first button press.
5531 root_window=XRootWindow(display,XDefaultScreen(display));
5532 draw_info.stencil=OpaqueStencil;
5534 cursor=XCreateFontCursor(display,XC_tcross);
5537 XQueryPosition(display,windows->image.id,&x,&y);
5538 (void) XSelectInput(display,windows->image.id,
5539 windows->image.attributes.event_mask | PointerMotionMask);
5540 (void) XCheckDefineCursor(display,windows->image.id,cursor);
5544 if( IfMagickTrue(windows->info.mapped) )
5547 Display pointer position.
5549 (void) FormatLocaleString(text,MaxTextExtent," %+d%+d ",
5550 x+windows->image.x,y+windows->image.y);
5551 XInfoWidget(display,windows,text);
5554 Wait for next event.
5556 XScreenEvent(display,windows,&event,exception);
5557 if (event.xany.window == windows->command.id)
5560 Select a command from the Command widget.
5562 id=XCommandWidget(display,windows,DrawMenu,&event);
5565 switch (DrawCommands[id])
5567 case DrawElementCommand:
5586 Select a command from the pop-up menu.
5588 element=(ElementType) (XMenuWidget(display,windows,
5589 DrawMenu[id],Elements,command)+1);
5592 case DrawColorCommand:
5595 *ColorMenu[MaxNumberPens+1];
5607 Initialize menu selections.
5609 for (i=0; i < (int) (MaxNumberPens-2); i++)
5610 ColorMenu[i]=resource_info->pen_colors[i];
5611 ColorMenu[MaxNumberPens-2]="transparent";
5612 ColorMenu[MaxNumberPens-1]="Browser...";
5613 ColorMenu[MaxNumberPens]=(char *) NULL;
5615 Select a pen color from the pop-up menu.
5617 pen_number=XMenuWidget(display,windows,DrawMenu[id],
5618 (const char **) ColorMenu,command);
5621 transparent=pen_number == (MaxNumberPens-2) ? MagickTrue :
5623 if( IfMagickTrue(transparent) )
5625 draw_info.stencil=TransparentStencil;
5628 if (pen_number == (MaxNumberPens-1))
5631 color_name[MaxTextExtent] = "gray";
5634 Select a pen color from a dialog.
5636 resource_info->pen_colors[pen_number]=color_name;
5637 XColorBrowserWidget(display,windows,"Select",color_name);
5638 if (*color_name == '\0')
5644 (void) XParseColor(display,windows->map_info->colormap,
5645 resource_info->pen_colors[pen_number],&color);
5646 XBestPixel(display,windows->map_info->colormap,(XColor *) NULL,
5647 (unsigned int) MaxColors,&color);
5648 windows->pixel_info->pen_colors[pen_number]=color;
5649 pen_id=(unsigned int) pen_number;
5650 draw_info.stencil=OpaqueStencil;
5653 case DrawStippleCommand:
5665 filename[MaxTextExtent] = "\0";
5682 Select a command from the pop-up menu.
5684 StipplesMenu[7]="Open...";
5685 entry=XMenuWidget(display,windows,DrawMenu[id],StipplesMenu,
5689 if (stipple != (Pixmap) NULL)
5690 (void) XFreePixmap(display,stipple);
5691 stipple=(Pixmap) NULL;
5698 stipple=XCreateBitmapFromData(display,root_window,
5699 (char *) BricksBitmap,BricksWidth,BricksHeight);
5704 stipple=XCreateBitmapFromData(display,root_window,
5705 (char *) DiagonalBitmap,DiagonalWidth,DiagonalHeight);
5710 stipple=XCreateBitmapFromData(display,root_window,
5711 (char *) ScalesBitmap,ScalesWidth,ScalesHeight);
5716 stipple=XCreateBitmapFromData(display,root_window,
5717 (char *) VerticalBitmap,VerticalWidth,VerticalHeight);
5722 stipple=XCreateBitmapFromData(display,root_window,
5723 (char *) WavyBitmap,WavyWidth,WavyHeight);
5728 stipple=XCreateBitmapFromData(display,root_window,
5729 (char *) HighlightBitmap,HighlightWidth,
5736 stipple=XCreateBitmapFromData(display,root_window,
5737 (char *) OpaqueBitmap,OpaqueWidth,OpaqueHeight);
5743 XFileBrowserWidget(display,windows,"Stipple",filename);
5744 if (*filename == '\0')
5749 XSetCursorState(display,windows,MagickTrue);
5750 XCheckRefreshWindows(display,windows);
5751 image_info=AcquireImageInfo();
5752 (void) CopyMagickString(image_info->filename,filename,
5754 stipple_image=ReadImage(image_info,exception);
5755 CatchException(exception);
5756 XSetCursorState(display,windows,MagickFalse);
5757 if (stipple_image == (Image *) NULL)
5759 (void) AcquireUniqueFileResource(filename);
5760 (void) FormatLocaleString(stipple_image->filename,MaxTextExtent,
5762 (void) WriteImage(image_info,stipple_image,exception);
5763 stipple_image=DestroyImage(stipple_image);
5764 image_info=DestroyImageInfo(image_info);
5765 status=XReadBitmapFile(display,root_window,filename,&width,
5766 &height,&stipple,&x,&y);
5767 (void) RelinquishUniqueFileResource(filename);
5768 if ((status != BitmapSuccess) != 0)
5769 XNoticeWidget(display,windows,"Unable to read X bitmap image:",
5773 case DrawWidthCommand:
5776 width[MaxTextExtent] = "0";
5791 Select a command from the pop-up menu.
5793 entry=XMenuWidget(display,windows,DrawMenu[id],WidthsMenu,
5799 line_width=(unsigned int) StringToUnsignedLong(
5803 (void) XDialogWidget(display,windows,"Ok","Enter line width:",
5807 line_width=(unsigned int) StringToUnsignedLong(width);
5810 case DrawUndoCommand:
5812 (void) XMagickCommand(display,resource_info,windows,UndoCommand,
5816 case DrawHelpCommand:
5818 XTextViewWidget(display,resource_info,windows,MagickFalse,
5819 "Help Viewer - Image Rotation",ImageDrawHelp);
5820 (void) XCheckDefineCursor(display,windows->image.id,cursor);
5823 case DrawDismissCommand:
5835 (void) XCheckDefineCursor(display,windows->image.id,cursor);
5842 if (event.xbutton.button != Button1)
5844 if (event.xbutton.window != windows->image.id)
5863 if (event.xkey.window != windows->image.id)
5866 Respond to a user key press.
5868 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
5869 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
5870 switch ((int) key_symbol)
5885 XTextViewWidget(display,resource_info,windows,MagickFalse,
5886 "Help Viewer - Image Rotation",ImageDrawHelp);
5891 (void) XBell(display,0);
5900 Map and unmap Info widget as text cursor crosses its boundaries.
5904 if( IfMagickTrue(windows->info.mapped) )
5906 if ((x < (int) (windows->info.x+windows->info.width)) &&
5907 (y < (int) (windows->info.y+windows->info.height)))
5908 (void) XWithdrawWindow(display,windows->info.id,
5909 windows->info.screen);
5912 if ((x > (int) (windows->info.x+windows->info.width)) ||
5913 (y > (int) (windows->info.y+windows->info.height)))
5914 (void) XMapWindow(display,windows->info.id);
5918 } while ((state & ExitState) == 0);
5919 (void) XSelectInput(display,windows->image.id,
5920 windows->image.attributes.event_mask);
5921 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
5922 if ((state & EscapeState) != 0)
5925 Draw element as pointer moves until the button is released.
5933 rectangle_info.x=(ssize_t) x;
5934 rectangle_info.y=(ssize_t) y;
5935 rectangle_info.width=0;
5936 rectangle_info.height=0;
5937 number_coordinates=1;
5938 coordinate_info->x=x;
5939 coordinate_info->y=y;
5940 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
5949 if (number_coordinates > 1)
5951 (void) XDrawLines(display,windows->image.id,
5952 windows->image.highlight_context,coordinate_info,
5953 number_coordinates,CoordModeOrigin);
5954 (void) FormatLocaleString(text,MaxTextExtent," %+d%+d",
5955 coordinate_info[number_coordinates-1].x,
5956 coordinate_info[number_coordinates-1].y);
5957 XInfoWidget(display,windows,text);
5966 Display angle of the line.
5968 degrees=RadiansToDegrees(-atan2((double) (line_info.y2-
5969 line_info.y1),(double) (line_info.x2-line_info.x1)));
5970 (void) FormatLocaleString(text,MaxTextExtent," %g",
5972 XInfoWidget(display,windows,text);
5973 XHighlightLine(display,windows->image.id,
5974 windows->image.highlight_context,&line_info);
5977 if( IfMagickTrue(windows->info.mapped) )
5978 (void) XWithdrawWindow(display,windows->info.id,
5979 windows->info.screen);
5982 case RectangleElement:
5983 case FillRectangleElement:
5985 if ((rectangle_info.width > 3) && (rectangle_info.height > 3))
5988 Display info and draw drawing rectangle.
5990 (void) FormatLocaleString(text,MaxTextExtent,
5991 " %.20gx%.20g%+.20g%+.20g",(double) rectangle_info.width,
5992 (double) rectangle_info.height,(double) rectangle_info.x,
5993 (double) rectangle_info.y);
5994 XInfoWidget(display,windows,text);
5995 XHighlightRectangle(display,windows->image.id,
5996 windows->image.highlight_context,&rectangle_info);
5999 if( IfMagickTrue(windows->info.mapped) )
6000 (void) XWithdrawWindow(display,windows->info.id,
6001 windows->info.screen);
6005 case FillCircleElement:
6006 case EllipseElement:
6007 case FillEllipseElement:
6009 if ((rectangle_info.width > 3) && (rectangle_info.height > 3))
6012 Display info and draw drawing rectangle.
6014 (void) FormatLocaleString(text,MaxTextExtent,
6015 " %.20gx%.20g%+.20g%+.20g",(double) rectangle_info.width,
6016 (double) rectangle_info.height,(double) rectangle_info.x,
6017 (double) rectangle_info.y);
6018 XInfoWidget(display,windows,text);
6019 XHighlightEllipse(display,windows->image.id,
6020 windows->image.highlight_context,&rectangle_info);
6023 if( IfMagickTrue(windows->info.mapped) )
6024 (void) XWithdrawWindow(display,windows->info.id,
6025 windows->info.screen);
6028 case PolygonElement:
6029 case FillPolygonElement:
6031 if (number_coordinates > 1)
6032 (void) XDrawLines(display,windows->image.id,
6033 windows->image.highlight_context,coordinate_info,
6034 number_coordinates,CoordModeOrigin);
6038 Display angle of the line.
6040 degrees=RadiansToDegrees(-atan2((double) (line_info.y2-
6041 line_info.y1),(double) (line_info.x2-line_info.x1)));
6042 (void) FormatLocaleString(text,MaxTextExtent," %g",
6044 XInfoWidget(display,windows,text);
6045 XHighlightLine(display,windows->image.id,
6046 windows->image.highlight_context,&line_info);
6049 if( IfMagickTrue(windows->info.mapped) )
6050 (void) XWithdrawWindow(display,windows->info.id,
6051 windows->info.screen);
6056 Wait for next event.
6058 XScreenEvent(display,windows,&event,exception);
6064 if (number_coordinates > 1)
6065 (void) XDrawLines(display,windows->image.id,
6066 windows->image.highlight_context,coordinate_info,
6067 number_coordinates,CoordModeOrigin);
6073 XHighlightLine(display,windows->image.id,
6074 windows->image.highlight_context,&line_info);
6077 case RectangleElement:
6078 case FillRectangleElement:
6080 if ((rectangle_info.width > 3) && (rectangle_info.height > 3))
6081 XHighlightRectangle(display,windows->image.id,
6082 windows->image.highlight_context,&rectangle_info);
6086 case FillCircleElement:
6087 case EllipseElement:
6088 case FillEllipseElement:
6090 if ((rectangle_info.width > 3) && (rectangle_info.height > 3))
6091 XHighlightEllipse(display,windows->image.id,
6092 windows->image.highlight_context,&rectangle_info);
6095 case PolygonElement:
6096 case FillPolygonElement:
6098 if (number_coordinates > 1)
6099 (void) XDrawLines(display,windows->image.id,
6100 windows->image.highlight_context,coordinate_info,
6101 number_coordinates,CoordModeOrigin);
6103 XHighlightLine(display,windows->image.id,
6104 windows->image.highlight_context,&line_info);
6115 User has committed to element.
6117 line_info.x2=event.xbutton.x;
6118 line_info.y2=event.xbutton.y;
6119 rectangle_info.x=(ssize_t) event.xbutton.x;
6120 rectangle_info.y=(ssize_t) event.xbutton.y;
6121 coordinate_info[number_coordinates].x=event.xbutton.x;
6122 coordinate_info[number_coordinates].y=event.xbutton.y;
6123 if (((element != PolygonElement) &&
6124 (element != FillPolygonElement)) || (distance <= 9))
6129 number_coordinates++;
6130 if (number_coordinates < (int) max_coordinates)
6132 line_info.x1=event.xbutton.x;
6133 line_info.y1=event.xbutton.y;
6136 max_coordinates<<=1;
6137 coordinate_info=(XPoint *) ResizeQuantumMemory(coordinate_info,
6138 max_coordinates,sizeof(*coordinate_info));
6139 if (coordinate_info == (XPoint *) NULL)
6140 (void) ThrowMagickException(exception,GetMagickModule(),
6141 ResourceLimitError,"MemoryAllocationFailed","`%s'","...");
6148 if (event.xmotion.window != windows->image.id)
6150 if (element != PointElement)
6152 line_info.x2=event.xmotion.x;
6153 line_info.y2=event.xmotion.y;
6154 rectangle_info.x=(ssize_t) event.xmotion.x;
6155 rectangle_info.y=(ssize_t) event.xmotion.y;
6158 coordinate_info[number_coordinates].x=event.xbutton.x;
6159 coordinate_info[number_coordinates].y=event.xbutton.y;
6160 number_coordinates++;
6161 if (number_coordinates < (int) max_coordinates)
6163 max_coordinates<<=1;
6164 coordinate_info=(XPoint *) ResizeQuantumMemory(coordinate_info,
6165 max_coordinates,sizeof(*coordinate_info));
6166 if (coordinate_info == (XPoint *) NULL)
6167 (void) ThrowMagickException(exception,GetMagickModule(),
6168 ResourceLimitError,"MemoryAllocationFailed","`%s'","...");
6175 Check boundary conditions.
6177 if (line_info.x2 < 0)
6180 if (line_info.x2 > (int) windows->image.width)
6181 line_info.x2=(short) windows->image.width;
6182 if (line_info.y2 < 0)
6185 if (line_info.y2 > (int) windows->image.height)
6186 line_info.y2=(short) windows->image.height;
6187 distance=(unsigned int)
6188 (((line_info.x2-line_info.x1+1)*(line_info.x2-line_info.x1+1))+
6189 ((line_info.y2-line_info.y1+1)*(line_info.y2-line_info.y1+1)));
6190 if ((((int) rectangle_info.x != x) && ((int) rectangle_info.y != y)) ||
6191 ((state & ExitState) != 0))
6193 if (rectangle_info.x < 0)
6196 if (rectangle_info.x > (ssize_t) windows->image.width)
6197 rectangle_info.x=(ssize_t) windows->image.width;
6198 if ((int) rectangle_info.x < x)
6199 rectangle_info.width=(unsigned int) (x-rectangle_info.x);
6202 rectangle_info.width=(unsigned int) (rectangle_info.x-x);
6203 rectangle_info.x=(ssize_t) x;
6205 if (rectangle_info.y < 0)
6208 if (rectangle_info.y > (ssize_t) windows->image.height)
6209 rectangle_info.y=(ssize_t) windows->image.height;
6210 if ((int) rectangle_info.y < y)
6211 rectangle_info.height=(unsigned int) (y-rectangle_info.y);
6214 rectangle_info.height=(unsigned int) (rectangle_info.y-y);
6215 rectangle_info.y=(ssize_t) y;
6218 } while ((state & ExitState) == 0);
6219 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
6220 if ((element == PointElement) || (element == PolygonElement) ||
6221 (element == FillPolygonElement))
6224 Determine polygon bounding box.
6226 rectangle_info.x=(ssize_t) coordinate_info->x;
6227 rectangle_info.y=(ssize_t) coordinate_info->y;
6228 x=coordinate_info->x;
6229 y=coordinate_info->y;
6230 for (i=1; i < number_coordinates; i++)
6232 if (coordinate_info[i].x > x)
6233 x=coordinate_info[i].x;
6234 if (coordinate_info[i].y > y)
6235 y=coordinate_info[i].y;
6236 if ((ssize_t) coordinate_info[i].x < rectangle_info.x)
6237 rectangle_info.x=MagickMax((ssize_t) coordinate_info[i].x,0);
6238 if ((ssize_t) coordinate_info[i].y < rectangle_info.y)
6239 rectangle_info.y=MagickMax((ssize_t) coordinate_info[i].y,0);
6241 rectangle_info.width=(size_t) (x-rectangle_info.x);
6242 rectangle_info.height=(size_t) (y-rectangle_info.y);
6243 for (i=0; i < number_coordinates; i++)
6245 coordinate_info[i].x-=rectangle_info.x;
6246 coordinate_info[i].y-=rectangle_info.y;
6253 if ((element == RectangleElement) ||
6254 (element == CircleElement) || (element == EllipseElement))
6256 rectangle_info.width--;
6257 rectangle_info.height--;
6260 Drawing is relative to image configuration.
6262 draw_info.x=(int) rectangle_info.x;
6263 draw_info.y=(int) rectangle_info.y;
6264 (void) XMagickCommand(display,resource_info,windows,SaveToUndoBufferCommand,
6266 width=(unsigned int) (*image)->columns;
6267 height=(unsigned int) (*image)->rows;
6270 if (windows->image.crop_geometry != (char *) NULL)
6271 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
6272 draw_info.x+=windows->image.x-(line_width/2);
6273 if (draw_info.x < 0)
6275 draw_info.x=(int) (width*draw_info.x/windows->image.ximage->width);
6276 draw_info.y+=windows->image.y-(line_width/2);
6277 if (draw_info.y < 0)
6279 draw_info.y=(int) height*draw_info.y/windows->image.ximage->height;
6280 draw_info.width=(unsigned int) rectangle_info.width+(line_width << 1);
6281 if (draw_info.width > (unsigned int) (*image)->columns)
6282 draw_info.width=(unsigned int) (*image)->columns;
6283 draw_info.height=(unsigned int) rectangle_info.height+(line_width << 1);
6284 if (draw_info.height > (unsigned int) (*image)->rows)
6285 draw_info.height=(unsigned int) (*image)->rows;
6286 (void) FormatLocaleString(draw_info.geometry,MaxTextExtent,"%ux%u%+d%+d",
6287 width*draw_info.width/windows->image.ximage->width,
6288 height*draw_info.height/windows->image.ximage->height,
6289 draw_info.x+x,draw_info.y+y);
6291 Initialize drawing attributes.
6293 draw_info.degrees=0.0;
6294 draw_info.element=element;
6295 draw_info.stipple=stipple;
6296 draw_info.line_width=line_width;
6297 draw_info.line_info=line_info;
6298 if (line_info.x1 > (int) (line_width/2))
6299 draw_info.line_info.x1=(short) line_width/2;
6300 if (line_info.y1 > (int) (line_width/2))
6301 draw_info.line_info.y1=(short) line_width/2;
6302 draw_info.line_info.x2=(short) (line_info.x2-line_info.x1+(line_width/2));
6303 draw_info.line_info.y2=(short) (line_info.y2-line_info.y1+(line_width/2));
6304 if ((draw_info.line_info.x2 < 0) && (draw_info.line_info.y2 < 0))
6306 draw_info.line_info.x2=(-draw_info.line_info.x2);
6307 draw_info.line_info.y2=(-draw_info.line_info.y2);
6309 if (draw_info.line_info.x2 < 0)
6311 draw_info.line_info.x2=(-draw_info.line_info.x2);
6312 Swap(draw_info.line_info.x1,draw_info.line_info.x2);
6314 if (draw_info.line_info.y2 < 0)
6316 draw_info.line_info.y2=(-draw_info.line_info.y2);
6317 Swap(draw_info.line_info.y1,draw_info.line_info.y2);
6319 draw_info.rectangle_info=rectangle_info;
6320 if (draw_info.rectangle_info.x > (ssize_t) (line_width/2))
6321 draw_info.rectangle_info.x=(ssize_t) line_width/2;
6322 if (draw_info.rectangle_info.y > (ssize_t) (line_width/2))
6323 draw_info.rectangle_info.y=(ssize_t) line_width/2;
6324 draw_info.number_coordinates=(unsigned int) number_coordinates;
6325 draw_info.coordinate_info=coordinate_info;
6326 windows->pixel_info->pen_color=windows->pixel_info->pen_colors[pen_id];
6328 Draw element on image.
6330 XSetCursorState(display,windows,MagickTrue);
6331 XCheckRefreshWindows(display,windows);
6332 status=XDrawImage(display,windows->pixel_info,&draw_info,*image,exception);
6333 XSetCursorState(display,windows,MagickFalse);
6335 Update image colormap and return to image drawing.
6337 XConfigureImageColormap(display,resource_info,windows,*image,exception);
6338 (void) XConfigureImage(display,resource_info,windows,*image,exception);
6340 XSetCursorState(display,windows,MagickFalse);
6341 coordinate_info=(XPoint *) RelinquishMagickMemory(coordinate_info);
6342 return(IsMagickTrue(status));
6346 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6350 + X D r a w P a n R e c t a n g l e %
6354 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6356 % XDrawPanRectangle() draws a rectangle in the pan window. The pan window
6357 % displays a zoom image and the rectangle shows which portion of the image is
6358 % displayed in the Image window.
6360 % The format of the XDrawPanRectangle method is:
6362 % XDrawPanRectangle(Display *display,XWindows *windows)
6364 % A description of each parameter follows:
6366 % o display: Specifies a connection to an X server; returned from
6369 % o windows: Specifies a pointer to a XWindows structure.
6372 static void XDrawPanRectangle(Display *display,XWindows *windows)
6381 Determine dimensions of the panning rectangle.
6383 scale_factor=(double) windows->pan.width/windows->image.ximage->width;
6384 highlight_info.x=(ssize_t) (scale_factor*windows->image.x+0.5);
6385 highlight_info.width=(unsigned int) (scale_factor*windows->image.width+0.5);
6386 scale_factor=(double)
6387 windows->pan.height/windows->image.ximage->height;
6388 highlight_info.y=(ssize_t) (scale_factor*windows->image.y+0.5);
6389 highlight_info.height=(unsigned int) (scale_factor*windows->image.height+0.5);
6391 Display the panning rectangle.
6393 (void) XClearWindow(display,windows->pan.id);
6394 XHighlightRectangle(display,windows->pan.id,windows->pan.annotate_context,
6399 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6403 + X I m a g e C a c h e %
6407 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6409 % XImageCache() handles the creation, manipulation, and destruction of the
6410 % image cache (undo and redo buffers).
6412 % The format of the XImageCache method is:
6414 % void XImageCache(Display *display,XResourceInfo *resource_info,
6415 % XWindows *windows,const CommandType command,Image **image,
6416 % ExceptionInfo *exception)
6418 % A description of each parameter follows:
6420 % o display: Specifies a connection to an X server; returned from
6423 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
6425 % o windows: Specifies a pointer to a XWindows structure.
6427 % o command: Specifies a command to perform.
6429 % o image: the image; XImageCache may transform the image and return a new
6432 % o exception: return any errors or warnings in this structure.
6435 static void XImageCache(Display *display,XResourceInfo *resource_info,
6436 XWindows *windows,const CommandType command,Image **image,
6437 ExceptionInfo *exception)
6443 *redo_image = (Image *) NULL,
6444 *undo_image = (Image *) NULL;
6448 case FreeBuffersCommand:
6451 Free memory from the undo and redo cache.
6453 while (undo_image != (Image *) NULL)
6455 cache_image=undo_image;
6456 undo_image=GetPreviousImageInList(undo_image);
6457 cache_image->list=DestroyImage(cache_image->list);
6458 cache_image=DestroyImage(cache_image);
6460 undo_image=NewImageList();
6461 if (redo_image != (Image *) NULL)
6462 redo_image=DestroyImage(redo_image);
6463 redo_image=NewImageList();
6469 image_geometry[MaxTextExtent];
6472 Undo the last image transformation.
6474 if (undo_image == (Image *) NULL)
6476 (void) XBell(display,0);
6479 cache_image=undo_image;
6480 undo_image=GetPreviousImageInList(undo_image);
6481 windows->image.window_changes.width=(int) cache_image->columns;
6482 windows->image.window_changes.height=(int) cache_image->rows;
6483 (void) FormatLocaleString(image_geometry,MaxTextExtent,"%dx%d!",
6484 windows->image.ximage->width,windows->image.ximage->height);
6485 (void) TransformImage(image,windows->image.crop_geometry,image_geometry,
6487 if (windows->image.crop_geometry != (char *) NULL)
6488 windows->image.crop_geometry=(char *) RelinquishMagickMemory(
6489 windows->image.crop_geometry);
6490 windows->image.crop_geometry=cache_image->geometry;
6491 if (redo_image != (Image *) NULL)
6492 redo_image=DestroyImage(redo_image);
6493 redo_image=(*image);
6494 *image=cache_image->list;
6495 cache_image=DestroyImage(cache_image);
6496 if( IfMagickTrue(windows->image.orphan) )
6498 XConfigureImageColormap(display,resource_info,windows,*image,exception);
6499 (void) XConfigureImage(display,resource_info,windows,*image,exception);
6505 case HalfSizeCommand:
6506 case OriginalSizeCommand:
6507 case DoubleSizeCommand:
6514 case RotateRightCommand:
6515 case RotateLeftCommand:
6520 case ContrastStretchCommand:
6521 case SigmoidalContrastCommand:
6522 case NormalizeCommand:
6523 case EqualizeCommand:
6525 case SaturationCommand:
6526 case BrightnessCommand:
6530 case GrayscaleCommand:
6532 case QuantizeCommand:
6533 case DespeckleCommand:
6535 case ReduceNoiseCommand:
6536 case AddNoiseCommand:
6537 case SharpenCommand:
6539 case ThresholdCommand:
6540 case EdgeDetectCommand:
6544 case SegmentCommand:
6545 case SolarizeCommand:
6546 case SepiaToneCommand:
6548 case ImplodeCommand:
6549 case VignetteCommand:
6551 case OilPaintCommand:
6552 case CharcoalDrawCommand:
6553 case AnnotateCommand:
6554 case AddBorderCommand:
6555 case AddFrameCommand:
6556 case CompositeCommand:
6557 case CommentCommand:
6559 case RegionofInterestCommand:
6560 case SaveToUndoBufferCommand:
6569 bytes=(ssize_t) ((*image)->columns*(*image)->rows*sizeof(PixelInfo));
6570 if (undo_image != (Image *) NULL)
6573 Ensure the undo cache has enough memory available.
6575 previous_image=undo_image;
6576 while (previous_image != (Image *) NULL)
6578 bytes+=previous_image->list->columns*previous_image->list->rows*
6580 if (bytes <= (ssize_t) (resource_info->undo_cache << 20))
6582 previous_image=GetPreviousImageInList(previous_image);
6585 bytes-=previous_image->list->columns*previous_image->list->rows*
6587 if (previous_image == undo_image)
6588 undo_image=NewImageList();
6590 previous_image->next->previous=NewImageList();
6593 while (previous_image != (Image *) NULL)
6596 Delete any excess memory from undo cache.
6598 cache_image=previous_image;
6599 previous_image=GetPreviousImageInList(previous_image);
6600 cache_image->list=DestroyImage(cache_image->list);
6601 cache_image=DestroyImage(cache_image);
6604 if (bytes > (ssize_t) (resource_info->undo_cache << 20))
6607 Save image before transformations are applied.
6609 cache_image=AcquireImage((ImageInfo *) NULL,exception);
6610 if (cache_image == (Image *) NULL)
6612 XSetCursorState(display,windows,MagickTrue);
6613 XCheckRefreshWindows(display,windows);
6614 cache_image->list=CloneImage(*image,0,0,MagickTrue,exception);
6615 XSetCursorState(display,windows,MagickFalse);
6616 if (cache_image->list == (Image *) NULL)
6618 cache_image=DestroyImage(cache_image);
6621 cache_image->columns=(size_t) windows->image.ximage->width;
6622 cache_image->rows=(size_t) windows->image.ximage->height;
6623 cache_image->geometry=windows->image.crop_geometry;
6624 if (windows->image.crop_geometry != (char *) NULL)
6626 cache_image->geometry=AcquireString((char *) NULL);
6627 (void) CopyMagickString(cache_image->geometry,
6628 windows->image.crop_geometry,MaxTextExtent);
6630 if (undo_image == (Image *) NULL)
6632 undo_image=cache_image;
6635 undo_image->next=cache_image;
6636 undo_image->next->previous=undo_image;
6637 undo_image=undo_image->next;
6643 if (command == RedoCommand)
6646 Redo the last image transformation.
6648 if (redo_image == (Image *) NULL)
6650 (void) XBell(display,0);
6653 windows->image.window_changes.width=(int) redo_image->columns;
6654 windows->image.window_changes.height=(int) redo_image->rows;
6655 if (windows->image.crop_geometry != (char *) NULL)
6656 windows->image.crop_geometry=(char *)
6657 RelinquishMagickMemory(windows->image.crop_geometry);
6658 windows->image.crop_geometry=redo_image->geometry;
6659 *image=DestroyImage(*image);
6661 redo_image=NewImageList();
6662 if( IfMagickTrue(windows->image.orphan) )
6664 XConfigureImageColormap(display,resource_info,windows,*image,exception);
6665 (void) XConfigureImage(display,resource_info,windows,*image,exception);
6668 if (command != InfoCommand)
6673 XSetCursorState(display,windows,MagickTrue);
6674 XCheckRefreshWindows(display,windows);
6675 XDisplayImageInfo(display,resource_info,windows,undo_image,*image,exception);
6676 XSetCursorState(display,windows,MagickFalse);
6680 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6684 + X I m a g e W i n d o w C o m m a n d %
6688 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6690 % XImageWindowCommand() makes a transform to the image or Image window as
6691 % specified by a user menu button or keyboard command.
6693 % The format of the XImageWindowCommand method is:
6695 % CommandType XImageWindowCommand(Display *display,
6696 % XResourceInfo *resource_info,XWindows *windows,
6697 % const MagickStatusType state,KeySym key_symbol,Image **image,
6698 % ExceptionInfo *exception)
6700 % A description of each parameter follows:
6702 % o nexus: Method XImageWindowCommand returns an image when the
6703 % user chooses 'Open Image' from the command menu. Otherwise a null
6704 % image is returned.
6706 % o display: Specifies a connection to an X server; returned from
6709 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
6711 % o windows: Specifies a pointer to a XWindows structure.
6713 % o state: key mask.
6715 % o key_symbol: Specifies a command to perform.
6717 % o image: the image; XImageWIndowCommand may transform the image and
6718 % return a new image pointer.
6720 % o exception: return any errors or warnings in this structure.
6723 static CommandType XImageWindowCommand(Display *display,
6724 XResourceInfo *resource_info,XWindows *windows,const MagickStatusType state,
6725 KeySym key_symbol,Image **image,ExceptionInfo *exception)
6728 delta[MaxTextExtent] = "";
6731 Digits[] = "01234567890";
6736 if ((key_symbol >= XK_0) && (key_symbol <= XK_9))
6738 if (((last_symbol < XK_0) || (last_symbol > XK_9)))
6741 resource_info->quantum=1;
6743 last_symbol=key_symbol;
6744 delta[strlen(delta)+1]='\0';
6745 delta[strlen(delta)]=Digits[key_symbol-XK_0];
6746 resource_info->quantum=StringToLong(delta);
6747 return(NullCommand);
6749 last_symbol=key_symbol;
6750 if (resource_info->immutable)
6753 Virtual image window has a restricted command set.
6758 return(InfoCommand);
6761 return(PrintCommand);
6763 return(NextCommand);
6766 return(QuitCommand);
6770 return(NullCommand);
6772 switch ((int) key_symbol)
6776 if ((state & ControlMask) == 0)
6778 return(OpenCommand);
6781 return(NextCommand);
6783 return(FormerCommand);
6786 if ((state & Mod1Mask) != 0)
6787 return(SwirlCommand);
6788 if ((state & ControlMask) == 0)
6789 return(ShearCommand);
6790 return(SaveCommand);
6795 if ((state & Mod1Mask) != 0)
6796 return(OilPaintCommand);
6797 if ((state & Mod4Mask) != 0)
6798 return(ColorCommand);
6799 if ((state & ControlMask) == 0)
6800 return(NullCommand);
6801 return(PrintCommand);
6805 if ((state & Mod4Mask) != 0)
6806 return(DrawCommand);
6807 if ((state & ControlMask) == 0)
6808 return(NullCommand);
6809 return(DeleteCommand);
6813 if ((state & ControlMask) == 0)
6814 return(NullCommand);
6815 return(SelectCommand);
6819 if ((state & ControlMask) == 0)
6820 return(NullCommand);
6825 return(QuitCommand);
6829 if ((state & ControlMask) == 0)
6830 return(NullCommand);
6831 return(UndoCommand);
6836 if ((state & ControlMask) == 0)
6837 return(RollCommand);
6838 return(RedoCommand);
6842 if ((state & ControlMask) == 0)
6843 return(NullCommand);
6848 if ((state & Mod1Mask) != 0)
6849 return(CharcoalDrawCommand);
6850 if ((state & ControlMask) == 0)
6851 return(CropCommand);
6852 return(CopyCommand);
6857 if ((state & Mod4Mask) != 0)
6858 return(CompositeCommand);
6859 if ((state & ControlMask) == 0)
6860 return(FlipCommand);
6861 return(PasteCommand);
6864 return(HalfSizeCommand);
6866 return(OriginalSizeCommand);
6868 return(DoubleSizeCommand);
6870 return(ResizeCommand);
6872 return(RefreshCommand);
6873 case XK_bracketleft:
6874 return(ChopCommand);
6876 return(FlopCommand);
6878 return(RotateRightCommand);
6880 return(RotateLeftCommand);
6882 return(RotateCommand);
6884 return(TrimCommand);
6888 return(SaturationCommand);
6890 return(BrightnessCommand);
6892 return(GammaCommand);
6894 return(SpiffCommand);
6896 return(DullCommand);
6898 return(NormalizeCommand);
6900 return(EqualizeCommand);
6902 return(NegateCommand);
6904 return(GrayscaleCommand);
6906 return(QuantizeCommand);
6908 return(DespeckleCommand);
6910 return(EmbossCommand);
6912 return(ReduceNoiseCommand);
6914 return(AddNoiseCommand);
6916 return(SharpenCommand);
6918 return(BlurCommand);
6920 return(ThresholdCommand);
6922 return(EdgeDetectCommand);
6924 return(SpreadCommand);
6926 return(ShadeCommand);
6928 return(RaiseCommand);
6930 return(SegmentCommand);
6933 if ((state & Mod1Mask) == 0)
6934 return(NullCommand);
6935 return(ImplodeCommand);
6939 if ((state & Mod1Mask) == 0)
6940 return(NullCommand);
6941 return(WaveCommand);
6945 if ((state & Mod4Mask) == 0)
6946 return(NullCommand);
6947 return(MatteCommand);
6951 if ((state & Mod4Mask) == 0)
6952 return(NullCommand);
6953 return(AddBorderCommand);
6957 if ((state & Mod4Mask) == 0)
6958 return(NullCommand);
6959 return(AddFrameCommand);
6963 if ((state & Mod4Mask) == 0)
6964 return(NullCommand);
6965 return(CommentCommand);
6969 if ((state & Mod1Mask) != 0)
6970 return(ApplyCommand);
6971 if ((state & Mod4Mask) != 0)
6972 return(AnnotateCommand);
6973 if ((state & ControlMask) == 0)
6974 return(NullCommand);
6975 return(RegionofInterestCommand);
6978 return(InfoCommand);
6980 return(ZoomCommand);
6983 if ((state & ShiftMask) == 0)
6984 return(NullCommand);
6985 return(ShowPreviewCommand);
6988 return(LaunchCommand);
6990 return(HelpCommand);
6992 return(BrowseDocumentationCommand);
6995 (void) XMapRaised(display,windows->command.id);
6996 return(NullCommand);
7003 XTranslateImage(display,windows,*image,key_symbol);
7004 return(NullCommand);
7015 if ((state & Mod1Mask) != 0)
7021 Trim one pixel from edge of image.
7025 crop_info.width=(size_t) windows->image.ximage->width;
7026 crop_info.height=(size_t) windows->image.ximage->height;
7027 if ((key_symbol == XK_Up) || (key_symbol == XK_KP_Up))
7029 if (resource_info->quantum >= (int) crop_info.height)
7030 resource_info->quantum=(int) crop_info.height-1;
7031 crop_info.height-=resource_info->quantum;
7033 if ((key_symbol == XK_Down) || (key_symbol == XK_KP_Down))
7035 if (resource_info->quantum >= (int) (crop_info.height-crop_info.y))
7036 resource_info->quantum=(int) (crop_info.height-crop_info.y-1);
7037 crop_info.y+=resource_info->quantum;
7038 crop_info.height-=resource_info->quantum;
7040 if ((key_symbol == XK_Left) || (key_symbol == XK_KP_Left))
7042 if (resource_info->quantum >= (int) crop_info.width)
7043 resource_info->quantum=(int) crop_info.width-1;
7044 crop_info.width-=resource_info->quantum;
7046 if ((key_symbol == XK_Right) || (key_symbol == XK_KP_Right))
7048 if (resource_info->quantum >= (int) (crop_info.width-crop_info.x))
7049 resource_info->quantum=(int) (crop_info.width-crop_info.x-1);
7050 crop_info.x+=resource_info->quantum;
7051 crop_info.width-=resource_info->quantum;
7053 if ((int) (windows->image.x+windows->image.width) >
7054 (int) crop_info.width)
7055 windows->image.x=(int) (crop_info.width-windows->image.width);
7056 if ((int) (windows->image.y+windows->image.height) >
7057 (int) crop_info.height)
7058 windows->image.y=(int) (crop_info.height-windows->image.height);
7059 XSetCropGeometry(display,windows,&crop_info,*image);
7060 windows->image.window_changes.width=(int) crop_info.width;
7061 windows->image.window_changes.height=(int) crop_info.height;
7062 (void) XSetWindowBackgroundPixmap(display,windows->image.id,None);
7063 (void) XConfigureImage(display,resource_info,windows,*image,
7065 return(NullCommand);
7067 XTranslateImage(display,windows,*image,key_symbol);
7068 return(NullCommand);
7071 return(NullCommand);
7073 return(NullCommand);
7077 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7081 + X M a g i c k C o m m a n d %
7085 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7087 % XMagickCommand() makes a transform to the image or Image window as
7088 % specified by a user menu button or keyboard command.
7090 % The format of the XMagickCommand method is:
7092 % Image *XMagickCommand(Display *display,XResourceInfo *resource_info,
7093 % XWindows *windows,const CommandType command,Image **image,
7094 % ExceptionInfo *exception)
7096 % A description of each parameter follows:
7098 % o display: Specifies a connection to an X server; returned from
7101 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
7103 % o windows: Specifies a pointer to a XWindows structure.
7105 % o command: Specifies a command to perform.
7107 % o image: the image; XMagickCommand may transform the image and return a
7108 % new image pointer.
7110 % o exception: return any errors or warnings in this structure.
7113 static Image *XMagickCommand(Display *display,XResourceInfo *resource_info,
7114 XWindows *windows,const CommandType command,Image **image,
7115 ExceptionInfo *exception)
7118 filename[MaxTextExtent],
7119 geometry[MaxTextExtent],
7120 modulate_factors[MaxTextExtent];
7149 color[MaxTextExtent] = "gray";
7156 Process user command.
7158 XCheckRefreshWindows(display,windows);
7159 XImageCache(display,resource_info,windows,command,image,exception);
7160 nexus=NewImageList();
7161 windows->image.window_changes.width=windows->image.ximage->width;
7162 windows->image.window_changes.height=windows->image.ximage->height;
7163 image_info=CloneImageInfo(resource_info->image_info);
7164 SetGeometryInfo(&geometry_info);
7165 GetQuantizeInfo(&quantize_info);
7173 nexus=XOpenImage(display,resource_info,windows,MagickFalse);
7181 for (i=0; i < resource_info->quantum; i++)
7182 XClientMessage(display,windows->image.id,windows->im_protocols,
7183 windows->im_next_image,CurrentTime);
7189 Display former image.
7191 for (i=0; i < resource_info->quantum; i++)
7192 XClientMessage(display,windows->image.id,windows->im_protocols,
7193 windows->im_former_image,CurrentTime);
7204 if (*resource_info->home_directory == '\0')
7205 (void) CopyMagickString(resource_info->home_directory,".",
7207 status=chdir(resource_info->home_directory);
7209 (void) ThrowMagickException(exception,GetMagickModule(),FileOpenError,
7210 "UnableToOpenFile","%s",resource_info->home_directory);
7211 nexus=XOpenImage(display,resource_info,windows,MagickTrue);
7219 status=XSaveImage(display,resource_info,windows,*image,exception);
7220 if( IfMagickFalse(status) )
7223 message[MaxTextExtent];
7225 (void) FormatLocaleString(message,MaxTextExtent,"%s:%s",
7226 exception->reason != (char *) NULL ? exception->reason : "",
7227 exception->description != (char *) NULL ? exception->description :
7229 XNoticeWidget(display,windows,"Unable to save file:",message);
7239 status=XPrintImage(display,resource_info,windows,*image,exception);
7240 if( IfMagickFalse(status) )
7243 message[MaxTextExtent];
7245 (void) FormatLocaleString(message,MaxTextExtent,"%s:%s",
7246 exception->reason != (char *) NULL ? exception->reason : "",
7247 exception->description != (char *) NULL ? exception->description :
7249 XNoticeWidget(display,windows,"Unable to print file:",message);
7257 filename[MaxTextExtent] = "\0";
7262 XFileBrowserWidget(display,windows,"Delete",filename);
7263 if (*filename == '\0')
7265 status=IsMagickTrue(remove_utf8(filename));
7266 if( IfMagickTrue(status) )
7267 XNoticeWidget(display,windows,"Unable to delete image file:",filename);
7276 color[MaxTextExtent] = "gray",
7277 geometry[MaxTextExtent] = "640x480";
7280 *format = "gradient";
7283 Query user for canvas geometry.
7285 status=XDialogWidget(display,windows,"New","Enter image geometry:",
7287 if (*geometry == '\0')
7291 XColorBrowserWidget(display,windows,"Select",color);
7297 (void) FormatLocaleString(image_info->filename,MaxTextExtent,
7298 "%s:%s",format,color);
7299 (void) CloneString(&image_info->size,geometry);
7300 nexus=ReadImage(image_info,exception);
7301 CatchException(exception);
7302 XClientMessage(display,windows->image.id,windows->im_protocols,
7303 windows->im_next_image,CurrentTime);
7306 case VisualDirectoryCommand:
7309 Visual Image directory.
7311 nexus=XVisualDirectoryImage(display,resource_info,windows,exception);
7319 if( IfMagickFalse(resource_info->confirm_exit) )
7320 XClientMessage(display,windows->image.id,windows->im_protocols,
7321 windows->im_exit,CurrentTime);
7328 Confirm program exit.
7330 status=XConfirmWidget(display,windows,"Do you really want to exit",
7331 resource_info->client_name);
7333 XClientMessage(display,windows->image.id,windows->im_protocols,
7334 windows->im_exit,CurrentTime);
7343 (void) XCropImage(display,resource_info,windows,*image,CutMode,exception);
7351 (void) XCropImage(display,resource_info,windows,*image,CopyMode,
7360 status=XPasteImage(display,resource_info,windows,*image,exception);
7361 if( IfMagickFalse(status) )
7363 XNoticeWidget(display,windows,"Unable to paste X image",
7364 (*image)->filename);
7369 case HalfSizeCommand:
7374 windows->image.window_changes.width=windows->image.ximage->width/2;
7375 windows->image.window_changes.height=windows->image.ximage->height/2;
7376 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7379 case OriginalSizeCommand:
7382 Original image size.
7384 windows->image.window_changes.width=(int) (*image)->columns;
7385 windows->image.window_changes.height=(int) (*image)->rows;
7386 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7389 case DoubleSizeCommand:
7392 Double the image size.
7394 windows->image.window_changes.width=windows->image.ximage->width << 1;
7395 windows->image.window_changes.height=windows->image.ximage->height << 1;
7396 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7415 width=(size_t) windows->image.ximage->width;
7416 height=(size_t) windows->image.ximage->height;
7419 (void) FormatLocaleString(geometry,MaxTextExtent,"%.20gx%.20g+0+0",
7420 (double) width,(double) height);
7421 status=XDialogWidget(display,windows,"Resize",
7422 "Enter resize geometry (e.g. 640x480, 200%):",geometry);
7423 if (*geometry == '\0')
7426 (void) ConcatenateMagickString(geometry,"!",MaxTextExtent);
7427 (void) ParseMetaGeometry(geometry,&x,&y,&width,&height);
7428 windows->image.window_changes.width=(int) width;
7429 windows->image.window_changes.height=(int) height;
7430 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7436 image_geometry[MaxTextExtent];
7438 if ((windows->image.crop_geometry == (char *) NULL) &&
7439 ((int) (*image)->columns == windows->image.ximage->width) &&
7440 ((int) (*image)->rows == windows->image.ximage->height))
7443 Apply size transforms to image.
7445 XSetCursorState(display,windows,MagickTrue);
7446 XCheckRefreshWindows(display,windows);
7448 Crop and/or scale displayed image.
7450 (void) FormatLocaleString(image_geometry,MaxTextExtent,"%dx%d!",
7451 windows->image.ximage->width,windows->image.ximage->height);
7452 (void) TransformImage(image,windows->image.crop_geometry,image_geometry,
7454 if (windows->image.crop_geometry != (char *) NULL)
7455 windows->image.crop_geometry=(char *) RelinquishMagickMemory(
7456 windows->image.crop_geometry);
7459 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7460 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7463 case RefreshCommand:
7465 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7468 case RestoreCommand:
7471 Restore Image window to its original size.
7473 if ((windows->image.width == (unsigned int) (*image)->columns) &&
7474 (windows->image.height == (unsigned int) (*image)->rows) &&
7475 (windows->image.crop_geometry == (char *) NULL))
7477 (void) XBell(display,0);
7480 windows->image.window_changes.width=(int) (*image)->columns;
7481 windows->image.window_changes.height=(int) (*image)->rows;
7482 if (windows->image.crop_geometry != (char *) NULL)
7484 windows->image.crop_geometry=(char *)
7485 RelinquishMagickMemory(windows->image.crop_geometry);
7486 windows->image.crop_geometry=(char *) NULL;
7490 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7491 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7499 (void) XCropImage(display,resource_info,windows,*image,CropMode,
7508 status=XChopImage(display,resource_info,windows,image,exception);
7509 if( IfMagickFalse(status) )
7511 XNoticeWidget(display,windows,"Unable to cut X image",
7512 (*image)->filename);
7523 Flop image scanlines.
7525 XSetCursorState(display,windows,MagickTrue);
7526 XCheckRefreshWindows(display,windows);
7527 flop_image=FlopImage(*image,exception);
7528 if (flop_image != (Image *) NULL)
7530 *image=DestroyImage(*image);
7533 CatchException(exception);
7534 XSetCursorState(display,windows,MagickFalse);
7535 if (windows->image.crop_geometry != (char *) NULL)
7540 width=(unsigned int) (*image)->columns;
7541 height=(unsigned int) (*image)->rows;
7542 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,
7544 (void) FormatLocaleString(windows->image.crop_geometry,MaxTextExtent,
7545 "%ux%u%+d%+d",width,height,(int) (*image)->columns-(int) width-x,y);
7547 if( IfMagickTrue(windows->image.orphan) )
7549 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7558 Flip image scanlines.
7560 XSetCursorState(display,windows,MagickTrue);
7561 XCheckRefreshWindows(display,windows);
7562 flip_image=FlipImage(*image,exception);
7563 if (flip_image != (Image *) NULL)
7565 *image=DestroyImage(*image);
7568 CatchException(exception);
7569 XSetCursorState(display,windows,MagickFalse);
7570 if (windows->image.crop_geometry != (char *) NULL)
7575 width=(unsigned int) (*image)->columns;
7576 height=(unsigned int) (*image)->rows;
7577 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,
7579 (void) FormatLocaleString(windows->image.crop_geometry,MaxTextExtent,
7580 "%ux%u%+d%+d",width,height,x,(int) (*image)->rows-(int) height-y);
7582 if( IfMagickTrue(windows->image.orphan) )
7584 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7587 case RotateRightCommand:
7590 Rotate image 90 degrees clockwise.
7592 status=XRotateImage(display,resource_info,windows,90.0,image,exception);
7593 if( IfMagickFalse(status) )
7595 XNoticeWidget(display,windows,"Unable to rotate X image",
7596 (*image)->filename);
7601 case RotateLeftCommand:
7604 Rotate image 90 degrees counter-clockwise.
7606 status=XRotateImage(display,resource_info,windows,-90.0,image,exception);
7607 if( IfMagickFalse(status) )
7609 XNoticeWidget(display,windows,"Unable to rotate X image",
7610 (*image)->filename);
7620 status=XRotateImage(display,resource_info,windows,0.0,image,exception);
7621 if( IfMagickFalse(status) )
7623 XNoticeWidget(display,windows,"Unable to rotate X image",
7624 (*image)->filename);
7635 geometry[MaxTextExtent] = "45.0x45.0";
7638 Query user for shear color and geometry.
7640 XColorBrowserWidget(display,windows,"Select",color);
7643 (void) XDialogWidget(display,windows,"Shear","Enter shear geometry:",
7645 if (*geometry == '\0')
7650 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image,
7652 XSetCursorState(display,windows,MagickTrue);
7653 XCheckRefreshWindows(display,windows);
7654 (void) QueryColorCompliance(color,AllCompliance,
7655 &(*image)->background_color,exception);
7656 flags=ParseGeometry(geometry,&geometry_info);
7657 if ((flags & SigmaValue) == 0)
7658 geometry_info.sigma=geometry_info.rho;
7659 shear_image=ShearImage(*image,geometry_info.rho,geometry_info.sigma,
7661 if (shear_image != (Image *) NULL)
7663 *image=DestroyImage(*image);
7666 CatchException(exception);
7667 XSetCursorState(display,windows,MagickFalse);
7668 if( IfMagickTrue(windows->image.orphan) )
7670 windows->image.window_changes.width=(int) (*image)->columns;
7671 windows->image.window_changes.height=(int) (*image)->rows;
7672 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7673 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7682 geometry[MaxTextExtent] = "+2+2";
7685 Query user for the roll geometry.
7687 (void) XDialogWidget(display,windows,"Roll","Enter roll geometry:",
7689 if (*geometry == '\0')
7694 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image,
7696 XSetCursorState(display,windows,MagickTrue);
7697 XCheckRefreshWindows(display,windows);
7698 (void) ParsePageGeometry(*image,geometry,&page_geometry,
7700 roll_image=RollImage(*image,page_geometry.x,page_geometry.y,
7702 if (roll_image != (Image *) NULL)
7704 *image=DestroyImage(*image);
7707 CatchException(exception);
7708 XSetCursorState(display,windows,MagickFalse);
7709 if( IfMagickTrue(windows->image.orphan) )
7711 windows->image.window_changes.width=(int) (*image)->columns;
7712 windows->image.window_changes.height=(int) (*image)->rows;
7713 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7714 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7720 fuzz[MaxTextExtent];
7723 Query user for the fuzz factor.
7725 (void) FormatLocaleString(fuzz,MaxTextExtent,"%g%%",100.0*
7726 (*image)->fuzz/(QuantumRange+1.0));
7727 (void) XDialogWidget(display,windows,"Trim","Enter fuzz factor:",fuzz);
7730 (*image)->fuzz=StringToDoubleInterval(fuzz,(double) QuantumRange+1.0);
7734 status=XTrimImage(display,resource_info,windows,*image,exception);
7735 if( IfMagickFalse(status) )
7737 XNoticeWidget(display,windows,"Unable to trim X image",
7738 (*image)->filename);
7746 hue_percent[MaxTextExtent] = "110";
7749 Query user for percent hue change.
7751 (void) XDialogWidget(display,windows,"Apply",
7752 "Enter percent change in image hue (0-200):",hue_percent);
7753 if (*hue_percent == '\0')
7758 XSetCursorState(display,windows,MagickTrue);
7759 XCheckRefreshWindows(display,windows);
7760 (void) CopyMagickString(modulate_factors,"100.0/100.0/",MaxTextExtent);
7761 (void) ConcatenateMagickString(modulate_factors,hue_percent,
7763 (void) ModulateImage(*image,modulate_factors,exception);
7764 XSetCursorState(display,windows,MagickFalse);
7765 if( IfMagickTrue(windows->image.orphan) )
7767 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7768 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7771 case SaturationCommand:
7774 saturation_percent[MaxTextExtent] = "110";
7777 Query user for percent saturation change.
7779 (void) XDialogWidget(display,windows,"Apply",
7780 "Enter percent change in color saturation (0-200):",saturation_percent);
7781 if (*saturation_percent == '\0')
7784 Vary color saturation.
7786 XSetCursorState(display,windows,MagickTrue);
7787 XCheckRefreshWindows(display,windows);
7788 (void) CopyMagickString(modulate_factors,"100.0/",MaxTextExtent);
7789 (void) ConcatenateMagickString(modulate_factors,saturation_percent,
7791 (void) ModulateImage(*image,modulate_factors,exception);
7792 XSetCursorState(display,windows,MagickFalse);
7793 if( IfMagickTrue(windows->image.orphan) )
7795 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7796 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7799 case BrightnessCommand:
7802 brightness_percent[MaxTextExtent] = "110";
7805 Query user for percent brightness change.
7807 (void) XDialogWidget(display,windows,"Apply",
7808 "Enter percent change in color brightness (0-200):",brightness_percent);
7809 if (*brightness_percent == '\0')
7812 Vary the color brightness.
7814 XSetCursorState(display,windows,MagickTrue);
7815 XCheckRefreshWindows(display,windows);
7816 (void) CopyMagickString(modulate_factors,brightness_percent,
7818 (void) ModulateImage(*image,modulate_factors,exception);
7819 XSetCursorState(display,windows,MagickFalse);
7820 if( IfMagickTrue(windows->image.orphan) )
7822 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7823 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7829 factor[MaxTextExtent] = "1.6";
7832 Query user for gamma value.
7834 (void) XDialogWidget(display,windows,"Gamma",
7835 "Enter gamma value (e.g. 1.2):",factor);
7836 if (*factor == '\0')
7839 Gamma correct image.
7841 XSetCursorState(display,windows,MagickTrue);
7842 XCheckRefreshWindows(display,windows);
7843 (void) GammaImage(*image,atof(factor),exception);
7844 XSetCursorState(display,windows,MagickFalse);
7845 if( IfMagickTrue(windows->image.orphan) )
7847 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7848 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7854 Sharpen the image contrast.
7856 XSetCursorState(display,windows,MagickTrue);
7857 XCheckRefreshWindows(display,windows);
7858 (void) ContrastImage(*image,MagickTrue,exception);
7859 XSetCursorState(display,windows,MagickFalse);
7860 if( IfMagickTrue(windows->image.orphan) )
7862 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7863 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7869 Dull the image contrast.
7871 XSetCursorState(display,windows,MagickTrue);
7872 XCheckRefreshWindows(display,windows);
7873 (void) ContrastImage(*image,MagickFalse,exception);
7874 XSetCursorState(display,windows,MagickFalse);
7875 if( IfMagickTrue(windows->image.orphan) )
7877 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7878 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7881 case ContrastStretchCommand:
7888 levels[MaxTextExtent] = "1%";
7891 Query user for gamma value.
7893 (void) XDialogWidget(display,windows,"Contrast Stretch",
7894 "Enter black and white points:",levels);
7895 if (*levels == '\0')
7898 Contrast stretch image.
7900 XSetCursorState(display,windows,MagickTrue);
7901 XCheckRefreshWindows(display,windows);
7902 flags=ParseGeometry(levels,&geometry_info);
7903 black_point=geometry_info.rho;
7904 white_point=(flags & SigmaValue) != 0 ? geometry_info.sigma : black_point;
7905 if ((flags & PercentValue) != 0)
7907 black_point*=(double) (*image)->columns*(*image)->rows/100.0;
7908 white_point*=(double) (*image)->columns*(*image)->rows/100.0;
7910 white_point=(double) (*image)->columns*(*image)->rows-white_point;
7911 (void) ContrastStretchImage(*image,black_point,white_point,
7913 XSetCursorState(display,windows,MagickFalse);
7914 if( IfMagickTrue(windows->image.orphan) )
7916 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7917 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7920 case SigmoidalContrastCommand:
7929 levels[MaxTextExtent] = "3x50%";
7932 Query user for gamma value.
7934 (void) XDialogWidget(display,windows,"Sigmoidal Contrast",
7935 "Enter contrast and midpoint:",levels);
7936 if (*levels == '\0')
7939 Contrast stretch image.
7941 XSetCursorState(display,windows,MagickTrue);
7942 XCheckRefreshWindows(display,windows);
7943 flags=ParseGeometry(levels,&geometry_info);
7944 if ((flags & SigmaValue) == 0)
7945 geometry_info.sigma=1.0*QuantumRange/2.0;
7946 if ((flags & PercentValue) != 0)
7947 geometry_info.sigma=1.0*QuantumRange*geometry_info.sigma/100.0;
7948 (void) SigmoidalContrastImage(*image,MagickTrue,geometry_info.rho,
7949 geometry_info.sigma,exception);
7950 XSetCursorState(display,windows,MagickFalse);
7951 if( IfMagickTrue(windows->image.orphan) )
7953 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7954 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7957 case NormalizeCommand:
7960 Perform histogram normalization on the image.
7962 XSetCursorState(display,windows,MagickTrue);
7963 XCheckRefreshWindows(display,windows);
7964 (void) NormalizeImage(*image,exception);
7965 XSetCursorState(display,windows,MagickFalse);
7966 if( IfMagickTrue(windows->image.orphan) )
7968 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7969 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7972 case EqualizeCommand:
7975 Perform histogram equalization on the image.
7977 XSetCursorState(display,windows,MagickTrue);
7978 XCheckRefreshWindows(display,windows);
7979 (void) EqualizeImage(*image,exception);
7980 XSetCursorState(display,windows,MagickFalse);
7981 if( IfMagickTrue(windows->image.orphan) )
7983 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7984 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7990 Negate colors in image.
7992 XSetCursorState(display,windows,MagickTrue);
7993 XCheckRefreshWindows(display,windows);
7994 (void) NegateImage(*image,MagickFalse,exception);
7995 XSetCursorState(display,windows,MagickFalse);
7996 if( IfMagickTrue(windows->image.orphan) )
7998 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7999 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8002 case GrayscaleCommand:
8005 Convert image to grayscale.
8007 XSetCursorState(display,windows,MagickTrue);
8008 XCheckRefreshWindows(display,windows);
8009 (void) SetImageType(*image,(*image)->alpha_trait != BlendPixelTrait ?
8010 GrayscaleType : GrayscaleMatteType,exception);
8011 XSetCursorState(display,windows,MagickFalse);
8012 if( IfMagickTrue(windows->image.orphan) )
8014 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8015 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8024 filename[MaxTextExtent] = "\0";
8027 Request image file name from user.
8029 XFileBrowserWidget(display,windows,"Map",filename);
8030 if (*filename == '\0')
8035 XSetCursorState(display,windows,MagickTrue);
8036 XCheckRefreshWindows(display,windows);
8037 (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
8038 affinity_image=ReadImage(image_info,exception);
8039 if (affinity_image != (Image *) NULL)
8041 (void) RemapImage(&quantize_info,*image,affinity_image,exception);
8042 affinity_image=DestroyImage(affinity_image);
8044 CatchException(exception);
8045 XSetCursorState(display,windows,MagickFalse);
8046 if( IfMagickTrue(windows->image.orphan) )
8048 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8049 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8052 case QuantizeCommand:
8058 colors[MaxTextExtent] = "256";
8061 Query user for maximum number of colors.
8063 status=XDialogWidget(display,windows,"Quantize",
8064 "Maximum number of colors:",colors);
8065 if (*colors == '\0')
8068 Color reduce the image.
8070 XSetCursorState(display,windows,MagickTrue);
8071 XCheckRefreshWindows(display,windows);
8072 quantize_info.number_colors=StringToUnsignedLong(colors);
8073 quantize_info.dither_method=status != 0 ? RiemersmaDitherMethod :
8075 (void) QuantizeImage(&quantize_info,*image,exception);
8076 XSetCursorState(display,windows,MagickFalse);
8077 if( IfMagickTrue(windows->image.orphan) )
8079 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8080 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8083 case DespeckleCommand:
8091 XSetCursorState(display,windows,MagickTrue);
8092 XCheckRefreshWindows(display,windows);
8093 despeckle_image=DespeckleImage(*image,exception);
8094 if (despeckle_image != (Image *) NULL)
8096 *image=DestroyImage(*image);
8097 *image=despeckle_image;
8099 CatchException(exception);
8100 XSetCursorState(display,windows,MagickFalse);
8101 if( IfMagickTrue(windows->image.orphan) )
8103 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8104 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8113 radius[MaxTextExtent] = "0.0x1.0";
8116 Query user for emboss radius.
8118 (void) XDialogWidget(display,windows,"Emboss",
8119 "Enter the emboss radius and standard deviation:",radius);
8120 if (*radius == '\0')
8123 Reduce noise in the image.
8125 XSetCursorState(display,windows,MagickTrue);
8126 XCheckRefreshWindows(display,windows);
8127 flags=ParseGeometry(radius,&geometry_info);
8128 if ((flags & SigmaValue) == 0)
8129 geometry_info.sigma=1.0;
8130 emboss_image=EmbossImage(*image,geometry_info.rho,geometry_info.sigma,
8132 if (emboss_image != (Image *) NULL)
8134 *image=DestroyImage(*image);
8135 *image=emboss_image;
8137 CatchException(exception);
8138 XSetCursorState(display,windows,MagickFalse);
8139 if( IfMagickTrue(windows->image.orphan) )
8141 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8142 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8145 case ReduceNoiseCommand:
8151 radius[MaxTextExtent] = "0";
8154 Query user for noise radius.
8156 (void) XDialogWidget(display,windows,"Reduce Noise",
8157 "Enter the noise radius:",radius);
8158 if (*radius == '\0')
8161 Reduce noise in the image.
8163 XSetCursorState(display,windows,MagickTrue);
8164 XCheckRefreshWindows(display,windows);
8165 flags=ParseGeometry(radius,&geometry_info);
8166 noise_image=StatisticImage(*image,NonpeakStatistic,(size_t)
8167 geometry_info.rho,(size_t) geometry_info.rho,exception);
8168 if (noise_image != (Image *) NULL)
8170 *image=DestroyImage(*image);
8173 CatchException(exception);
8174 XSetCursorState(display,windows,MagickFalse);
8175 if( IfMagickTrue(windows->image.orphan) )
8177 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8178 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8181 case AddNoiseCommand:
8190 noise_type[MaxTextExtent] = "Gaussian";
8193 Add noise to the image.
8195 noises=GetCommandOptions(MagickNoiseOptions);
8196 if (noises == (char **) NULL)
8198 XListBrowserWidget(display,windows,&windows->widget,
8199 (const char **) noises,"Add Noise",
8200 "Select a type of noise to add to your image:",noise_type);
8201 noises=DestroyStringList(noises);
8202 if (*noise_type == '\0')
8204 XSetCursorState(display,windows,MagickTrue);
8205 XCheckRefreshWindows(display,windows);
8206 noise_image=AddNoiseImage(*image,(NoiseType) ParseCommandOption(
8207 MagickNoiseOptions,MagickFalse,noise_type),1.0,exception);
8208 if (noise_image != (Image *) NULL)
8210 *image=DestroyImage(*image);
8213 CatchException(exception);
8214 XSetCursorState(display,windows,MagickFalse);
8215 if( IfMagickTrue(windows->image.orphan) )
8217 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8218 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8221 case SharpenCommand:
8227 radius[MaxTextExtent] = "0.0x1.0";
8230 Query user for sharpen radius.
8232 (void) XDialogWidget(display,windows,"Sharpen",
8233 "Enter the sharpen radius and standard deviation:",radius);
8234 if (*radius == '\0')
8237 Sharpen image scanlines.
8239 XSetCursorState(display,windows,MagickTrue);
8240 XCheckRefreshWindows(display,windows);
8241 flags=ParseGeometry(radius,&geometry_info);
8242 sharp_image=SharpenImage(*image,geometry_info.rho,geometry_info.sigma,
8244 if (sharp_image != (Image *) NULL)
8246 *image=DestroyImage(*image);
8249 CatchException(exception);
8250 XSetCursorState(display,windows,MagickFalse);
8251 if( IfMagickTrue(windows->image.orphan) )
8253 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8254 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8263 radius[MaxTextExtent] = "0.0x1.0";
8266 Query user for blur radius.
8268 (void) XDialogWidget(display,windows,"Blur",
8269 "Enter the blur radius and standard deviation:",radius);
8270 if (*radius == '\0')
8275 XSetCursorState(display,windows,MagickTrue);
8276 XCheckRefreshWindows(display,windows);
8277 flags=ParseGeometry(radius,&geometry_info);
8278 blur_image=BlurImage(*image,geometry_info.rho,geometry_info.sigma,
8280 if (blur_image != (Image *) NULL)
8282 *image=DestroyImage(*image);
8285 CatchException(exception);
8286 XSetCursorState(display,windows,MagickFalse);
8287 if( IfMagickTrue(windows->image.orphan) )
8289 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8290 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8293 case ThresholdCommand:
8299 factor[MaxTextExtent] = "128";
8302 Query user for threshold value.
8304 (void) XDialogWidget(display,windows,"Threshold",
8305 "Enter threshold value:",factor);
8306 if (*factor == '\0')
8309 Gamma correct image.
8311 XSetCursorState(display,windows,MagickTrue);
8312 XCheckRefreshWindows(display,windows);
8313 threshold=StringToDoubleInterval(factor,(double) QuantumRange+1.0);
8314 (void) BilevelImage(*image,threshold,exception);
8315 XSetCursorState(display,windows,MagickFalse);
8316 if( IfMagickTrue(windows->image.orphan) )
8318 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8319 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8322 case EdgeDetectCommand:
8328 radius[MaxTextExtent] = "0";
8331 Query user for edge factor.
8333 (void) XDialogWidget(display,windows,"Detect Edges",
8334 "Enter the edge detect radius:",radius);
8335 if (*radius == '\0')
8338 Detect edge in image.
8340 XSetCursorState(display,windows,MagickTrue);
8341 XCheckRefreshWindows(display,windows);
8342 flags=ParseGeometry(radius,&geometry_info);
8343 edge_image=EdgeImage(*image,geometry_info.rho,geometry_info.sigma,
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,geometry_info.sigma,
8381 if (spread_image != (Image *) NULL)
8383 *image=DestroyImage(*image);
8384 *image=spread_image;
8386 CatchException(exception);
8387 XSetCursorState(display,windows,MagickFalse);
8388 if( IfMagickTrue(windows->image.orphan) )
8390 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8391 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8403 geometry[MaxTextExtent] = "30x30";
8406 Query user for the shade geometry.
8408 status=XDialogWidget(display,windows,"Shade",
8409 "Enter the azimuth and elevation of the light source:",geometry);
8410 if (*geometry == '\0')
8415 XSetCursorState(display,windows,MagickTrue);
8416 XCheckRefreshWindows(display,windows);
8417 flags=ParseGeometry(geometry,&geometry_info);
8418 if ((flags & SigmaValue) == 0)
8419 geometry_info.sigma=1.0;
8420 shade_image=ShadeImage(*image,IsMagickTrue(status),
8421 geometry_info.rho,geometry_info.sigma,exception);
8422 if (shade_image != (Image *) NULL)
8424 *image=DestroyImage(*image);
8427 CatchException(exception);
8428 XSetCursorState(display,windows,MagickFalse);
8429 if( IfMagickTrue(windows->image.orphan) )
8431 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8432 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8438 bevel_width[MaxTextExtent] = "10";
8441 Query user for bevel width.
8443 (void) XDialogWidget(display,windows,"Raise","Bevel width:",bevel_width);
8444 if (*bevel_width == '\0')
8449 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image,
8451 XSetCursorState(display,windows,MagickTrue);
8452 XCheckRefreshWindows(display,windows);
8453 (void) ParsePageGeometry(*image,bevel_width,&page_geometry,
8455 (void) RaiseImage(*image,&page_geometry,MagickTrue,exception);
8456 XSetCursorState(display,windows,MagickFalse);
8457 if( IfMagickTrue(windows->image.orphan) )
8459 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8460 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8463 case SegmentCommand:
8466 threshold[MaxTextExtent] = "1.0x1.5";
8469 Query user for smoothing threshold.
8471 (void) XDialogWidget(display,windows,"Segment","Smooth threshold:",
8473 if (*threshold == '\0')
8478 XSetCursorState(display,windows,MagickTrue);
8479 XCheckRefreshWindows(display,windows);
8480 flags=ParseGeometry(threshold,&geometry_info);
8481 if ((flags & SigmaValue) == 0)
8482 geometry_info.sigma=1.0;
8483 (void) SegmentImage(*image,sRGBColorspace,MagickFalse,geometry_info.rho,
8484 geometry_info.sigma,exception);
8485 XSetCursorState(display,windows,MagickFalse);
8486 if( IfMagickTrue(windows->image.orphan) )
8488 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8489 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8492 case SepiaToneCommand:
8501 factor[MaxTextExtent] = "80%";
8504 Query user for sepia-tone factor.
8506 (void) XDialogWidget(display,windows,"Sepia Tone",
8507 "Enter the sepia tone factor (0 - 99.9%):",factor);
8508 if (*factor == '\0')
8511 Sepia tone image pixels.
8513 XSetCursorState(display,windows,MagickTrue);
8514 XCheckRefreshWindows(display,windows);
8515 threshold=StringToDoubleInterval(factor,(double) QuantumRange+1.0);
8516 sepia_image=SepiaToneImage(*image,threshold,exception);
8517 if (sepia_image != (Image *) NULL)
8519 *image=DestroyImage(*image);
8522 CatchException(exception);
8523 XSetCursorState(display,windows,MagickFalse);
8524 if( IfMagickTrue(windows->image.orphan) )
8526 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8527 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8530 case SolarizeCommand:
8536 factor[MaxTextExtent] = "60%";
8539 Query user for solarize factor.
8541 (void) XDialogWidget(display,windows,"Solarize",
8542 "Enter the solarize factor (0 - 99.9%):",factor);
8543 if (*factor == '\0')
8546 Solarize image pixels.
8548 XSetCursorState(display,windows,MagickTrue);
8549 XCheckRefreshWindows(display,windows);
8550 threshold=StringToDoubleInterval(factor,(double) QuantumRange+1.0);
8551 (void) SolarizeImage(*image,threshold,exception);
8552 XSetCursorState(display,windows,MagickFalse);
8553 if( IfMagickTrue(windows->image.orphan) )
8555 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8556 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8565 degrees[MaxTextExtent] = "60";
8568 Query user for swirl angle.
8570 (void) XDialogWidget(display,windows,"Swirl","Enter the swirl angle:",
8572 if (*degrees == '\0')
8575 Swirl image pixels about the center.
8577 XSetCursorState(display,windows,MagickTrue);
8578 XCheckRefreshWindows(display,windows);
8579 flags=ParseGeometry(degrees,&geometry_info);
8580 swirl_image=SwirlImage(*image,geometry_info.rho,(*image)->interpolate,
8582 if (swirl_image != (Image *) NULL)
8584 *image=DestroyImage(*image);
8587 CatchException(exception);
8588 XSetCursorState(display,windows,MagickFalse);
8589 if( IfMagickTrue(windows->image.orphan) )
8591 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8592 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8595 case ImplodeCommand:
8601 factor[MaxTextExtent] = "0.3";
8604 Query user for implode factor.
8606 (void) XDialogWidget(display,windows,"Implode",
8607 "Enter the implosion/explosion factor (-1.0 - 1.0):",factor);
8608 if (*factor == '\0')
8611 Implode image pixels about the center.
8613 XSetCursorState(display,windows,MagickTrue);
8614 XCheckRefreshWindows(display,windows);
8615 flags=ParseGeometry(factor,&geometry_info);
8616 implode_image=ImplodeImage(*image,geometry_info.rho,(*image)->interpolate,
8618 if (implode_image != (Image *) NULL)
8620 *image=DestroyImage(*image);
8621 *image=implode_image;
8623 CatchException(exception);
8624 XSetCursorState(display,windows,MagickFalse);
8625 if( IfMagickTrue(windows->image.orphan) )
8627 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8628 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8631 case VignetteCommand:
8637 geometry[MaxTextExtent] = "0x20";
8640 Query user for the vignette geometry.
8642 (void) XDialogWidget(display,windows,"Vignette",
8643 "Enter the radius, sigma, and x and y offsets:",geometry);
8644 if (*geometry == '\0')
8647 Soften the edges of the image in vignette style
8649 XSetCursorState(display,windows,MagickTrue);
8650 XCheckRefreshWindows(display,windows);
8651 flags=ParseGeometry(geometry,&geometry_info);
8652 if ((flags & SigmaValue) == 0)
8653 geometry_info.sigma=1.0;
8654 if ((flags & XiValue) == 0)
8655 geometry_info.xi=0.1*(*image)->columns;
8656 if ((flags & PsiValue) == 0)
8657 geometry_info.psi=0.1*(*image)->rows;
8658 vignette_image=VignetteImage(*image,geometry_info.rho,0.0,(ssize_t)
8659 ceil(geometry_info.xi-0.5),(ssize_t) ceil(geometry_info.psi-0.5),
8661 if (vignette_image != (Image *) NULL)
8663 *image=DestroyImage(*image);
8664 *image=vignette_image;
8666 CatchException(exception);
8667 XSetCursorState(display,windows,MagickFalse);
8668 if( IfMagickTrue(windows->image.orphan) )
8670 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8671 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8680 geometry[MaxTextExtent] = "25x150";
8683 Query user for the wave geometry.
8685 (void) XDialogWidget(display,windows,"Wave",
8686 "Enter the amplitude and length of the wave:",geometry);
8687 if (*geometry == '\0')
8690 Alter an image along a sine wave.
8692 XSetCursorState(display,windows,MagickTrue);
8693 XCheckRefreshWindows(display,windows);
8694 flags=ParseGeometry(geometry,&geometry_info);
8695 if ((flags & SigmaValue) == 0)
8696 geometry_info.sigma=1.0;
8697 wave_image=WaveImage(*image,geometry_info.rho,geometry_info.sigma,
8698 (*image)->interpolate,exception);
8699 if (wave_image != (Image *) NULL)
8701 *image=DestroyImage(*image);
8704 CatchException(exception);
8705 XSetCursorState(display,windows,MagickFalse);
8706 if( IfMagickTrue(windows->image.orphan) )
8708 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8709 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8712 case OilPaintCommand:
8718 radius[MaxTextExtent] = "0";
8721 Query user for circular neighborhood radius.
8723 (void) XDialogWidget(display,windows,"Oil Paint",
8724 "Enter the mask radius:",radius);
8725 if (*radius == '\0')
8728 OilPaint image scanlines.
8730 XSetCursorState(display,windows,MagickTrue);
8731 XCheckRefreshWindows(display,windows);
8732 flags=ParseGeometry(radius,&geometry_info);
8733 paint_image=OilPaintImage(*image,geometry_info.rho,geometry_info.sigma,
8735 if (paint_image != (Image *) NULL)
8737 *image=DestroyImage(*image);
8740 CatchException(exception);
8741 XSetCursorState(display,windows,MagickFalse);
8742 if( IfMagickTrue(windows->image.orphan) )
8744 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8745 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8748 case CharcoalDrawCommand:
8754 radius[MaxTextExtent] = "0x1";
8757 Query user for charcoal radius.
8759 (void) XDialogWidget(display,windows,"Charcoal Draw",
8760 "Enter the charcoal radius and sigma:",radius);
8761 if (*radius == '\0')
8766 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image,
8768 XSetCursorState(display,windows,MagickTrue);
8769 XCheckRefreshWindows(display,windows);
8770 flags=ParseGeometry(radius,&geometry_info);
8771 if ((flags & SigmaValue) == 0)
8772 geometry_info.sigma=geometry_info.rho;
8773 charcoal_image=CharcoalImage(*image,geometry_info.rho,geometry_info.sigma,
8775 if (charcoal_image != (Image *) NULL)
8777 *image=DestroyImage(*image);
8778 *image=charcoal_image;
8780 CatchException(exception);
8781 XSetCursorState(display,windows,MagickFalse);
8782 if( IfMagickTrue(windows->image.orphan) )
8784 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8785 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8788 case AnnotateCommand:
8791 Annotate the image with text.
8793 status=XAnnotateEditImage(display,resource_info,windows,*image,exception);
8794 if( IfMagickFalse(status) )
8796 XNoticeWidget(display,windows,"Unable to annotate X image",
8797 (*image)->filename);
8807 status=XDrawEditImage(display,resource_info,windows,image,exception);
8808 if( IfMagickFalse(status) )
8810 XNoticeWidget(display,windows,"Unable to draw on the X image",
8811 (*image)->filename);
8821 status=XColorEditImage(display,resource_info,windows,image,exception);
8822 if( IfMagickFalse(status) )
8824 XNoticeWidget(display,windows,"Unable to pixel edit X image",
8825 (*image)->filename);
8835 status=XMatteEditImage(display,resource_info,windows,image,exception);
8836 if( IfMagickFalse(status) )
8838 XNoticeWidget(display,windows,"Unable to matte edit X image",
8839 (*image)->filename);
8844 case CompositeCommand:
8849 status=XCompositeImage(display,resource_info,windows,*image,
8851 if( IfMagickFalse(status) )
8853 XNoticeWidget(display,windows,"Unable to composite X image",
8854 (*image)->filename);
8859 case AddBorderCommand:
8865 geometry[MaxTextExtent] = "6x6";
8868 Query user for border color and geometry.
8870 XColorBrowserWidget(display,windows,"Select",color);
8873 (void) XDialogWidget(display,windows,"Add Border",
8874 "Enter border geometry:",geometry);
8875 if (*geometry == '\0')
8878 Add a border to the image.
8880 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image,
8882 XSetCursorState(display,windows,MagickTrue);
8883 XCheckRefreshWindows(display,windows);
8884 (void) QueryColorCompliance(color,AllCompliance,&(*image)->border_color,
8886 (void) ParsePageGeometry(*image,geometry,&page_geometry,
8888 border_image=BorderImage(*image,&page_geometry,(*image)->compose,
8890 if (border_image != (Image *) NULL)
8892 *image=DestroyImage(*image);
8893 *image=border_image;
8895 CatchException(exception);
8896 XSetCursorState(display,windows,MagickFalse);
8897 if( IfMagickTrue(windows->image.orphan) )
8899 windows->image.window_changes.width=(int) (*image)->columns;
8900 windows->image.window_changes.height=(int) (*image)->rows;
8901 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8902 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8905 case AddFrameCommand:
8914 geometry[MaxTextExtent] = "6x6";
8917 Query user for frame color and geometry.
8919 XColorBrowserWidget(display,windows,"Select",color);
8922 (void) XDialogWidget(display,windows,"Add Frame","Enter frame geometry:",
8924 if (*geometry == '\0')
8927 Surround image with an ornamental border.
8929 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image,
8931 XSetCursorState(display,windows,MagickTrue);
8932 XCheckRefreshWindows(display,windows);
8933 (void) QueryColorCompliance(color,AllCompliance,&(*image)->matte_color,
8935 (void) ParsePageGeometry(*image,geometry,&page_geometry,
8937 frame_info.width=page_geometry.width;
8938 frame_info.height=page_geometry.height;
8939 frame_info.outer_bevel=page_geometry.x;
8940 frame_info.inner_bevel=page_geometry.y;
8941 frame_info.x=(ssize_t) frame_info.width;
8942 frame_info.y=(ssize_t) frame_info.height;
8943 frame_info.width=(*image)->columns+2*frame_info.width;
8944 frame_info.height=(*image)->rows+2*frame_info.height;
8945 frame_image=FrameImage(*image,&frame_info,(*image)->compose,exception);
8946 if (frame_image != (Image *) NULL)
8948 *image=DestroyImage(*image);
8951 CatchException(exception);
8952 XSetCursorState(display,windows,MagickFalse);
8953 if( IfMagickTrue(windows->image.orphan) )
8955 windows->image.window_changes.width=(int) (*image)->columns;
8956 windows->image.window_changes.height=(int) (*image)->rows;
8957 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8958 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8961 case CommentCommand:
8975 unique_file=AcquireUniqueFileResource(image_info->filename);
8976 if (unique_file == -1)
8977 XNoticeWidget(display,windows,"Unable to edit image comment",
8978 image_info->filename);
8979 value=GetImageProperty(*image,"comment",exception);
8980 if (value == (char *) NULL)
8981 unique_file=close(unique_file)-1;
8987 file=fdopen(unique_file,"w");
8988 if (file == (FILE *) NULL)
8990 XNoticeWidget(display,windows,"Unable to edit image comment",
8991 image_info->filename);
8994 for (p=value; *p != '\0'; p++)
8995 (void) fputc((int) *p,file);
8996 (void) fputc('\n',file);
8997 (void) fclose(file);
8999 XSetCursorState(display,windows,MagickTrue);
9000 XCheckRefreshWindows(display,windows);
9001 status=InvokeDelegate(image_info,*image,"edit",(char *) NULL,
9003 if( IfMagickFalse(status) )
9004 XNoticeWidget(display,windows,"Unable to edit image comment",
9011 comment=FileToString(image_info->filename,~0UL,exception);
9012 if (comment != (char *) NULL)
9014 (void) SetImageProperty(*image,"comment",comment,exception);
9015 (*image)->taint=MagickTrue;
9018 (void) RelinquishUniqueFileResource(image_info->filename);
9019 XSetCursorState(display,windows,MagickFalse);
9027 XSetCursorState(display,windows,MagickTrue);
9028 XCheckRefreshWindows(display,windows);
9029 (void) AcquireUniqueFilename(filename);
9030 (void) FormatLocaleString((*image)->filename,MaxTextExtent,"launch:%s",
9032 status=WriteImage(image_info,*image,exception);
9033 if( IfMagickFalse(status) )
9034 XNoticeWidget(display,windows,"Unable to launch image editor",
9038 nexus=ReadImage(resource_info->image_info,exception);
9039 CatchException(exception);
9040 XClientMessage(display,windows->image.id,windows->im_protocols,
9041 windows->im_next_image,CurrentTime);
9043 (void) RelinquishUniqueFileResource(filename);
9044 XSetCursorState(display,windows,MagickFalse);
9047 case RegionofInterestCommand:
9050 Apply an image processing technique to a region of interest.
9052 (void) XROIImage(display,resource_info,windows,image,exception);
9062 if( IfMagickTrue(windows->magnify.mapped) )
9063 (void) XRaiseWindow(display,windows->magnify.id);
9069 XSetCursorState(display,windows,MagickTrue);
9070 (void) XMapRaised(display,windows->magnify.id);
9071 XSetCursorState(display,windows,MagickFalse);
9075 case ShowPreviewCommand:
9084 preview_type[MaxTextExtent] = "Gamma";
9087 Select preview type from menu.
9089 previews=GetCommandOptions(MagickPreviewOptions);
9090 if (previews == (char **) NULL)
9092 XListBrowserWidget(display,windows,&windows->widget,
9093 (const char **) previews,"Preview",
9094 "Select an enhancement, effect, or F/X:",preview_type);
9095 previews=DestroyStringList(previews);
9096 if (*preview_type == '\0')
9101 XSetCursorState(display,windows,MagickTrue);
9102 XCheckRefreshWindows(display,windows);
9103 image_info->preview_type=(PreviewType)
9104 ParseCommandOption(MagickPreviewOptions,MagickFalse,preview_type);
9105 image_info->group=(ssize_t) windows->image.id;
9106 (void) DeleteImageProperty(*image,"label");
9107 (void) SetImageProperty(*image,"label","Preview",exception);
9108 (void) AcquireUniqueFilename(filename);
9109 (void) FormatLocaleString((*image)->filename,MaxTextExtent,"preview:%s",
9111 status=WriteImage(image_info,*image,exception);
9112 (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
9113 preview_image=ReadImage(image_info,exception);
9114 (void) RelinquishUniqueFileResource(filename);
9115 if (preview_image == (Image *) NULL)
9117 (void) FormatLocaleString(preview_image->filename,MaxTextExtent,"show:%s",
9119 status=WriteImage(image_info,preview_image,exception);
9120 preview_image=DestroyImage(preview_image);
9121 if( IfMagickFalse(status) )
9122 XNoticeWidget(display,windows,"Unable to show image preview",
9123 (*image)->filename);
9124 XDelay(display,1500);
9125 XSetCursorState(display,windows,MagickFalse);
9128 case ShowHistogramCommand:
9134 Show image histogram.
9136 XSetCursorState(display,windows,MagickTrue);
9137 XCheckRefreshWindows(display,windows);
9138 image_info->group=(ssize_t) windows->image.id;
9139 (void) DeleteImageProperty(*image,"label");
9140 (void) SetImageProperty(*image,"label","Histogram",exception);
9141 (void) AcquireUniqueFilename(filename);
9142 (void) FormatLocaleString((*image)->filename,MaxTextExtent,"histogram:%s",
9144 status=WriteImage(image_info,*image,exception);
9145 (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
9146 histogram_image=ReadImage(image_info,exception);
9147 (void) RelinquishUniqueFileResource(filename);
9148 if (histogram_image == (Image *) NULL)
9150 (void) FormatLocaleString(histogram_image->filename,MaxTextExtent,
9151 "show:%s",filename);
9152 status=WriteImage(image_info,histogram_image,exception);
9153 histogram_image=DestroyImage(histogram_image);
9154 if( IfMagickFalse(status) )
9155 XNoticeWidget(display,windows,"Unable to show histogram",
9156 (*image)->filename);
9157 XDelay(display,1500);
9158 XSetCursorState(display,windows,MagickFalse);
9161 case ShowMatteCommand:
9166 if ((*image)->alpha_trait != BlendPixelTrait)
9168 XNoticeWidget(display,windows,
9169 "Image does not have any matte information",(*image)->filename);
9175 XSetCursorState(display,windows,MagickTrue);
9176 XCheckRefreshWindows(display,windows);
9177 image_info->group=(ssize_t) windows->image.id;
9178 (void) DeleteImageProperty(*image,"label");
9179 (void) SetImageProperty(*image,"label","Matte",exception);
9180 (void) AcquireUniqueFilename(filename);
9181 (void) FormatLocaleString((*image)->filename,MaxTextExtent,"matte:%s",
9183 status=WriteImage(image_info,*image,exception);
9184 (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
9185 matte_image=ReadImage(image_info,exception);
9186 (void) RelinquishUniqueFileResource(filename);
9187 if (matte_image == (Image *) NULL)
9189 (void) FormatLocaleString(matte_image->filename,MaxTextExtent,"show:%s",
9191 status=WriteImage(image_info,matte_image,exception);
9192 matte_image=DestroyImage(matte_image);
9193 if( IfMagickFalse(status) )
9194 XNoticeWidget(display,windows,"Unable to show matte",
9195 (*image)->filename);
9196 XDelay(display,1500);
9197 XSetCursorState(display,windows,MagickFalse);
9200 case BackgroundCommand:
9205 status=XBackgroundImage(display,resource_info,windows,image,exception);
9206 if( IfMagickFalse(status) )
9208 nexus=CloneImage(*image,0,0,MagickTrue,exception);
9209 if (nexus != (Image *) NULL)
9210 XClientMessage(display,windows->image.id,windows->im_protocols,
9211 windows->im_next_image,CurrentTime);
9214 case SlideShowCommand:
9217 delay[MaxTextExtent] = "5";
9220 Display next image after pausing.
9222 (void) XDialogWidget(display,windows,"Slide Show",
9223 "Pause how many 1/100ths of a second between images:",delay);
9226 resource_info->delay=StringToUnsignedLong(delay);
9227 XClientMessage(display,windows->image.id,windows->im_protocols,
9228 windows->im_next_image,CurrentTime);
9231 case PreferencesCommand:
9234 Set user preferences.
9236 status=XPreferencesWidget(display,resource_info,windows);
9237 if( IfMagickFalse(status) )
9239 nexus=CloneImage(*image,0,0,MagickTrue,exception);
9240 if (nexus != (Image *) NULL)
9241 XClientMessage(display,windows->image.id,windows->im_protocols,
9242 windows->im_next_image,CurrentTime);
9248 User requested help.
9250 XTextViewWidget(display,resource_info,windows,MagickFalse,
9251 "Help Viewer - Display",DisplayHelp);
9254 case BrowseDocumentationCommand:
9264 Browse the ImageMagick documentation.
9266 root_window=XRootWindow(display,XDefaultScreen(display));
9267 mozilla_atom=XInternAtom(display,"_MOZILLA_VERSION",MagickFalse);
9268 mozilla_window=XWindowByProperty(display,root_window,mozilla_atom);
9269 if (mozilla_window != (Window) NULL)
9272 command[MaxTextExtent],
9276 Display documentation using Netscape remote control.
9278 url=GetMagickHomeURL();
9279 (void) FormatLocaleString(command,MaxTextExtent,
9280 "openurl(%s,new-tab)",url);
9281 url=DestroyString(url);
9282 mozilla_atom=XInternAtom(display,"_MOZILLA_COMMAND",MagickFalse);
9283 (void) XChangeProperty(display,mozilla_window,mozilla_atom,XA_STRING,
9284 8,PropModeReplace,(unsigned char *) command,(int) strlen(command));
9285 XSetCursorState(display,windows,MagickFalse);
9288 XSetCursorState(display,windows,MagickTrue);
9289 XCheckRefreshWindows(display,windows);
9290 status=InvokeDelegate(image_info,*image,"browse",(char *) NULL,
9292 if( IfMagickFalse(status) )
9293 XNoticeWidget(display,windows,"Unable to browse documentation",
9295 XDelay(display,1500);
9296 XSetCursorState(display,windows,MagickFalse);
9299 case VersionCommand:
9301 XNoticeWidget(display,windows,GetMagickVersion((size_t *) NULL),
9302 GetMagickCopyright());
9305 case SaveToUndoBufferCommand:
9309 (void) XBell(display,0);
9313 image_info=DestroyImageInfo(image_info);
9318 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9322 + X M a g n i f y I m a g e %
9326 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9328 % XMagnifyImage() magnifies portions of the image as indicated by the pointer.
9329 % The magnified portion is displayed in a separate window.
9331 % The format of the XMagnifyImage method is:
9333 % void XMagnifyImage(Display *display,XWindows *windows,XEvent *event,
9334 % ExceptionInfo *exception)
9336 % A description of each parameter follows:
9338 % o display: Specifies a connection to an X server; returned from
9341 % o windows: Specifies a pointer to a XWindows structure.
9343 % o event: Specifies a pointer to a XEvent structure. If it is NULL,
9344 % the entire image is refreshed.
9346 % o exception: return any errors or warnings in this structure.
9349 static void XMagnifyImage(Display *display,XWindows *windows,XEvent *event,
9350 ExceptionInfo *exception)
9353 text[MaxTextExtent];
9363 Update magnified image until the mouse button is released.
9365 (void) XCheckDefineCursor(display,windows->image.id,windows->magnify.cursor);
9369 windows->magnify.x=(int) windows->image.x+x;
9370 windows->magnify.y=(int) windows->image.y+y;
9374 Map and unmap Info widget as text cursor crosses its boundaries.
9376 if( IfMagickTrue(windows->info.mapped) )
9378 if ((x < (int) (windows->info.x+windows->info.width)) &&
9379 (y < (int) (windows->info.y+windows->info.height)))
9380 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
9383 if ((x > (int) (windows->info.x+windows->info.width)) ||
9384 (y > (int) (windows->info.y+windows->info.height)))
9385 (void) XMapWindow(display,windows->info.id);
9386 if( IfMagickTrue(windows->info.mapped) )
9389 Display pointer position.
9391 (void) FormatLocaleString(text,MaxTextExtent," %+d%+d ",
9392 windows->magnify.x,windows->magnify.y);
9393 XInfoWidget(display,windows,text);
9396 Wait for next event.
9398 XScreenEvent(display,windows,event,exception);
9399 switch (event->type)
9406 User has finished magnifying image.
9425 Check boundary conditions.
9430 if (x >= (int) windows->image.width)
9431 x=(int) windows->image.width-1;
9435 if (y >= (int) windows->image.height)
9436 y=(int) windows->image.height-1;
9437 } while ((state & ExitState) == 0);
9439 Display magnified image.
9441 XSetCursorState(display,windows,MagickFalse);
9445 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9449 + X M a g n i f y W i n d o w C o m m a n d %
9453 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9455 % XMagnifyWindowCommand() moves the image within an Magnify window by one
9456 % pixel as specified by the key symbol.
9458 % The format of the XMagnifyWindowCommand method is:
9460 % void XMagnifyWindowCommand(Display *display,XWindows *windows,
9461 % const MagickStatusType state,const KeySym key_symbol,
9462 % ExceptionInfo *exception)
9464 % A description of each parameter follows:
9466 % o display: Specifies a connection to an X server; returned from
9469 % o windows: Specifies a pointer to a XWindows structure.
9471 % o state: key mask.
9473 % o key_symbol: Specifies a KeySym which indicates which side of the image
9476 % o exception: return any errors or warnings in this structure.
9479 static void XMagnifyWindowCommand(Display *display,XWindows *windows,
9480 const MagickStatusType state,const KeySym key_symbol,ExceptionInfo *exception)
9486 User specified a magnify factor or position.
9489 if ((state & Mod1Mask) != 0)
9491 switch ((int) key_symbol)
9495 (void) XWithdrawWindow(display,windows->magnify.id,
9496 windows->magnify.screen);
9502 windows->magnify.x=(int) windows->image.width/2;
9503 windows->magnify.y=(int) windows->image.height/2;
9509 if (windows->magnify.x > 0)
9510 windows->magnify.x-=quantum;
9516 if (windows->magnify.y > 0)
9517 windows->magnify.y-=quantum;
9523 if (windows->magnify.x < (int) (windows->image.ximage->width-1))
9524 windows->magnify.x+=quantum;
9530 if (windows->magnify.y < (int) (windows->image.ximage->height-1))
9531 windows->magnify.y+=quantum;
9545 windows->magnify.data=(key_symbol-XK_0);
9559 windows->magnify.data=(key_symbol-XK_KP_0);
9565 XMakeMagnifyImage(display,windows,exception);
9569 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9573 + X M a k e P a n I m a g e %
9577 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9579 % XMakePanImage() creates a thumbnail of the image and displays it in the Pan
9582 % The format of the XMakePanImage method is:
9584 % void XMakePanImage(Display *display,XResourceInfo *resource_info,
9585 % XWindows *windows,Image *image,ExceptionInfo *exception)
9587 % A description of each parameter follows:
9589 % o display: Specifies a connection to an X server; returned from
9592 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
9594 % o windows: Specifies a pointer to a XWindows structure.
9596 % o image: the image.
9598 % o exception: return any errors or warnings in this structure.
9601 static void XMakePanImage(Display *display,XResourceInfo *resource_info,
9602 XWindows *windows,Image *image,ExceptionInfo *exception)
9608 Create and display image for panning icon.
9610 XSetCursorState(display,windows,MagickTrue);
9611 XCheckRefreshWindows(display,windows);
9612 windows->pan.x=(int) windows->image.x;
9613 windows->pan.y=(int) windows->image.y;
9614 status=XMakeImage(display,resource_info,&windows->pan,image,
9615 windows->pan.width,windows->pan.height,exception);
9616 if( IfMagickFalse(status) )
9617 ThrowXWindowFatalException(ResourceLimitError,
9618 "MemoryAllocationFailed",image->filename);
9619 (void) XSetWindowBackgroundPixmap(display,windows->pan.id,
9620 windows->pan.pixmap);
9621 (void) XClearWindow(display,windows->pan.id);
9622 XDrawPanRectangle(display,windows);
9623 XSetCursorState(display,windows,MagickFalse);
9627 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9631 + X M a t t a E d i t I m a g e %
9635 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9637 % XMatteEditImage() allows the user to interactively change the Matte channel
9638 % of an image. If the image is PseudoClass it is promoted to DirectClass
9639 % before the matte information is stored.
9641 % The format of the XMatteEditImage method is:
9643 % MagickBooleanType XMatteEditImage(Display *display,
9644 % XResourceInfo *resource_info,XWindows *windows,Image **image,
9645 % ExceptionInfo *exception)
9647 % A description of each parameter follows:
9649 % o display: Specifies a connection to an X server; returned from
9652 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
9654 % o windows: Specifies a pointer to a XWindows structure.
9656 % o image: the image; returned from ReadImage.
9658 % o exception: return any errors or warnings in this structure.
9661 static MagickBooleanType XMatteEditImage(Display *display,
9662 XResourceInfo *resource_info,XWindows *windows,Image **image,
9663 ExceptionInfo *exception)
9666 matte[MaxTextExtent] = "0";
9681 static const ModeType
9682 MatteEditCommands[] =
9685 MatteEditBorderCommand,
9686 MatteEditFuzzCommand,
9687 MatteEditValueCommand,
9688 MatteEditUndoCommand,
9689 MatteEditHelpCommand,
9690 MatteEditDismissCommand
9694 method = PointMethod;
9697 border_color = { 0, 0, 0, 0, 0, 0 };
9700 command[MaxTextExtent],
9701 text[MaxTextExtent];
9733 (void) CloneString(&windows->command.name,"Matte Edit");
9734 windows->command.data=4;
9735 (void) XCommandWidget(display,windows,MatteEditMenu,(XEvent *) NULL);
9736 (void) XMapRaised(display,windows->command.id);
9737 XClientMessage(display,windows->image.id,windows->im_protocols,
9738 windows->im_update_widget,CurrentTime);
9742 cursor=XMakeCursor(display,windows->image.id,windows->map_info->colormap,
9743 resource_info->background_color,resource_info->foreground_color);
9744 (void) XCheckDefineCursor(display,windows->image.id,cursor);
9746 Track pointer until button 1 is pressed.
9748 XQueryPosition(display,windows->image.id,&x,&y);
9749 (void) XSelectInput(display,windows->image.id,
9750 windows->image.attributes.event_mask | PointerMotionMask);
9754 if( IfMagickTrue(windows->info.mapped) )
9757 Display pointer position.
9759 (void) FormatLocaleString(text,MaxTextExtent," %+d%+d ",
9760 x+windows->image.x,y+windows->image.y);
9761 XInfoWidget(display,windows,text);
9764 Wait for next event.
9766 XScreenEvent(display,windows,&event,exception);
9767 if (event.xany.window == windows->command.id)
9770 Select a command from the Command widget.
9772 id=XCommandWidget(display,windows,MatteEditMenu,&event);
9775 (void) XCheckDefineCursor(display,windows->image.id,cursor);
9778 switch (MatteEditCommands[id])
9780 case MatteEditMethod:
9786 Select a method from the pop-up menu.
9788 methods=GetCommandOptions(MagickMethodOptions);
9789 if (methods == (char **) NULL)
9791 entry=XMenuWidget(display,windows,MatteEditMenu[id],
9792 (const char **) methods,command);
9794 method=(PaintMethod) ParseCommandOption(MagickMethodOptions,
9795 MagickFalse,methods[entry]);
9796 methods=DestroyStringList(methods);
9799 case MatteEditBorderCommand:
9802 *ColorMenu[MaxNumberPens];
9808 Initialize menu selections.
9810 for (i=0; i < (int) (MaxNumberPens-2); i++)
9811 ColorMenu[i]=resource_info->pen_colors[i];
9812 ColorMenu[MaxNumberPens-2]="Browser...";
9813 ColorMenu[MaxNumberPens-1]=(const char *) NULL;
9815 Select a pen color from the pop-up menu.
9817 pen_number=XMenuWidget(display,windows,MatteEditMenu[id],
9818 (const char **) ColorMenu,command);
9821 if (pen_number == (MaxNumberPens-2))
9824 color_name[MaxTextExtent] = "gray";
9827 Select a pen color from a dialog.
9829 resource_info->pen_colors[pen_number]=color_name;
9830 XColorBrowserWidget(display,windows,"Select",color_name);
9831 if (*color_name == '\0')
9837 (void) XParseColor(display,windows->map_info->colormap,
9838 resource_info->pen_colors[pen_number],&border_color);
9841 case MatteEditFuzzCommand:
9844 fuzz[MaxTextExtent];
9859 Select a command from the pop-up menu.
9861 entry=XMenuWidget(display,windows,MatteEditMenu[id],FuzzMenu,
9867 (*image)->fuzz=StringToDoubleInterval(FuzzMenu[entry],(double)
9871 (void) CopyMagickString(fuzz,"20%",MaxTextExtent);
9872 (void) XDialogWidget(display,windows,"Ok",
9873 "Enter fuzz factor (0.0 - 99.9%):",fuzz);
9876 (void) ConcatenateMagickString(fuzz,"%",MaxTextExtent);
9877 (*image)->fuzz=StringToDoubleInterval(fuzz,(double) QuantumRange+
9881 case MatteEditValueCommand:
9884 message[MaxTextExtent];
9896 Select a command from the pop-up menu.
9898 entry=XMenuWidget(display,windows,MatteEditMenu[id],MatteMenu,
9904 (void) FormatLocaleString(matte,MaxTextExtent,QuantumFormat,
9906 if (LocaleCompare(MatteMenu[entry],"Transparent") == 0)
9907 (void) FormatLocaleString(matte,MaxTextExtent,QuantumFormat,
9908 (Quantum) TransparentAlpha);
9911 (void) FormatLocaleString(message,MaxTextExtent,
9912 "Enter matte value (0 - " QuantumFormat "):",(Quantum)
9914 (void) XDialogWidget(display,windows,"Matte",message,matte);
9919 case MatteEditUndoCommand:
9921 (void) XMagickCommand(display,resource_info,windows,UndoCommand,
9925 case MatteEditHelpCommand:
9927 XTextViewWidget(display,resource_info,windows,MagickFalse,
9928 "Help Viewer - Matte Edit",ImageMatteEditHelp);
9931 case MatteEditDismissCommand:
9943 (void) XCheckDefineCursor(display,windows->image.id,cursor);
9950 if (event.xbutton.button != Button1)
9952 if ((event.xbutton.window != windows->image.id) &&
9953 (event.xbutton.window != windows->magnify.id))
9960 (void) XMagickCommand(display,resource_info,windows,
9961 SaveToUndoBufferCommand,image,exception);
9962 state|=UpdateConfigurationState;
9967 if (event.xbutton.button != Button1)
9969 if ((event.xbutton.window != windows->image.id) &&
9970 (event.xbutton.window != windows->magnify.id))
9973 Update colormap information.
9977 XConfigureImageColormap(display,resource_info,windows,*image,exception);
9978 (void) XConfigureImage(display,resource_info,windows,*image,exception);
9979 XInfoWidget(display,windows,text);
9980 (void) XCheckDefineCursor(display,windows->image.id,cursor);
9981 state&=(~UpdateConfigurationState);
9989 command[MaxTextExtent];
9994 if (event.xkey.window == windows->magnify.id)
9999 window=windows->magnify.id;
10000 while (XCheckWindowEvent(display,window,KeyPressMask,&event)) ;
10002 if (event.xkey.window != windows->image.id)
10005 Respond to a user key press.
10007 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
10008 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
10009 switch ((int) key_symbol)
10023 XTextViewWidget(display,resource_info,windows,MagickFalse,
10024 "Help Viewer - Matte Edit",ImageMatteEditHelp);
10029 (void) XBell(display,0);
10038 Map and unmap Info widget as cursor crosses its boundaries.
10042 if( IfMagickTrue(windows->info.mapped) )
10044 if ((x < (int) (windows->info.x+windows->info.width)) &&
10045 (y < (int) (windows->info.y+windows->info.height)))
10046 (void) XWithdrawWindow(display,windows->info.id,
10047 windows->info.screen);
10050 if ((x > (int) (windows->info.x+windows->info.width)) ||
10051 (y > (int) (windows->info.y+windows->info.height)))
10052 (void) XMapWindow(display,windows->info.id);
10058 if (event.xany.window == windows->magnify.id)
10060 x=windows->magnify.x-windows->image.x;
10061 y=windows->magnify.y-windows->image.y;
10065 if ((state & UpdateConfigurationState) != 0)
10075 Matte edit is relative to image configuration.
10077 (void) XClearArea(display,windows->image.id,x_offset,y_offset,1,1,
10079 XPutPixel(windows->image.ximage,x_offset,y_offset,
10080 windows->pixel_info->background_color.pixel);
10081 width=(unsigned int) (*image)->columns;
10082 height=(unsigned int) (*image)->rows;
10085 if (windows->image.crop_geometry != (char *) NULL)
10086 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,
10088 x_offset=(int) (width*(windows->image.x+x_offset)/
10089 windows->image.ximage->width+x);
10090 y_offset=(int) (height*(windows->image.y+y_offset)/
10091 windows->image.ximage->height+y);
10092 if ((x_offset < 0) || (y_offset < 0))
10094 if ((x_offset >= (int) (*image)->columns) ||
10095 (y_offset >= (int) (*image)->rows))
10097 if( IfMagickFalse(SetImageStorageClass(*image,DirectClass,exception)) )
10098 return(MagickFalse);
10099 if ((*image)->alpha_trait != BlendPixelTrait)
10100 (void) SetImageAlphaChannel(*image,OpaqueAlphaChannel,exception);
10101 image_view=AcquireAuthenticCacheView(*image,exception);
10108 Update matte information using point algorithm.
10110 q=GetCacheViewAuthenticPixels(image_view,(ssize_t) x_offset,
10111 (ssize_t) y_offset,1,1,exception);
10112 if (q == (Quantum *) NULL)
10114 SetPixelAlpha(*image,(Quantum) StringToLong(matte),q);
10115 (void) SyncCacheViewAuthenticPixels(image_view,exception);
10118 case ReplaceMethod:
10125 Update matte information using replace algorithm.
10127 (void) GetOneCacheViewVirtualPixelInfo(image_view,(ssize_t)
10128 x_offset,(ssize_t) y_offset,&target,exception);
10129 for (y=0; y < (int) (*image)->rows; y++)
10131 q=GetCacheViewAuthenticPixels(image_view,0,(ssize_t) y,
10132 (*image)->columns,1,exception);
10133 if (q == (Quantum *) NULL)
10135 for (x=0; x < (int) (*image)->columns; x++)
10137 GetPixelInfoPixel(*image,q,&pixel);
10138 if (IsFuzzyEquivalencePixelInfo(&pixel,&target))
10139 SetPixelAlpha(*image,(Quantum) StringToLong(matte),q);
10140 q+=GetPixelChannels(*image);
10142 if( IfMagickFalse(SyncCacheViewAuthenticPixels(image_view,exception)) )
10147 case FloodfillMethod:
10148 case FillToBorderMethod:
10160 Update matte information using floodfill algorithm.
10162 (void) GetOneVirtualPixelInfo(*image,
10163 GetPixelCacheVirtualMethod(*image),(ssize_t) x_offset,(ssize_t)
10164 y_offset,&target,exception);
10165 if (method == FillToBorderMethod)
10167 target.red=(double) ScaleShortToQuantum(
10169 target.green=(double) ScaleShortToQuantum(
10170 border_color.green);
10171 target.blue=(double) ScaleShortToQuantum(
10172 border_color.blue);
10174 draw_info=CloneDrawInfo(resource_info->image_info,
10175 (DrawInfo *) NULL);
10176 draw_info->fill.alpha=(double) ClampToQuantum(
10177 StringToDouble(matte,(char **) NULL));
10178 channel_mask=SetImageChannelMask(*image,AlphaChannel);
10179 (void) FloodfillPaintImage(*image,draw_info,&target,(ssize_t)
10180 x_offset,(ssize_t) y_offset,
10181 IsMagickFalse(method == FloodfillMethod),exception);
10182 (void) SetPixelChannelMask(*image,channel_mask);
10183 draw_info=DestroyDrawInfo(draw_info);
10189 Update matte information using reset algorithm.
10191 if( IfMagickFalse(SetImageStorageClass(*image,DirectClass,exception)) )
10192 return(MagickFalse);
10193 for (y=0; y < (int) (*image)->rows; y++)
10195 q=QueueCacheViewAuthenticPixels(image_view,0,(ssize_t) y,
10196 (*image)->columns,1,exception);
10197 if (q == (Quantum *) NULL)
10199 for (x=0; x < (int) (*image)->columns; x++)
10201 SetPixelAlpha(*image,(Quantum) StringToLong(matte),q);
10202 q+=GetPixelChannels(*image);
10204 if( IfMagickFalse(SyncCacheViewAuthenticPixels(image_view,exception)) )
10207 if (StringToLong(matte) == (long) OpaqueAlpha)
10208 (*image)->alpha_trait=UndefinedPixelTrait;
10212 image_view=DestroyCacheView(image_view);
10213 state&=(~UpdateConfigurationState);
10215 } while ((state & ExitState) == 0);
10216 (void) XSelectInput(display,windows->image.id,
10217 windows->image.attributes.event_mask);
10218 XSetCursorState(display,windows,MagickFalse);
10219 (void) XFreeCursor(display,cursor);
10220 return(MagickTrue);
10224 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10228 + X O p e n I m a g e %
10232 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10234 % XOpenImage() loads an image from a file.
10236 % The format of the XOpenImage method is:
10238 % Image *XOpenImage(Display *display,XResourceInfo *resource_info,
10239 % XWindows *windows,const unsigned int command)
10241 % A description of each parameter follows:
10243 % o display: Specifies a connection to an X server; returned from
10246 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
10248 % o windows: Specifies a pointer to a XWindows structure.
10250 % o command: A value other than zero indicates that the file is selected
10251 % from the command line argument list.
10254 static Image *XOpenImage(Display *display,XResourceInfo *resource_info,
10255 XWindows *windows,const MagickBooleanType command)
10270 filename[MaxTextExtent] = "\0";
10273 Request file name from user.
10275 if( IfMagickFalse(command) )
10276 XFileBrowserWidget(display,windows,"Open",filename);
10292 Select next image from the command line.
10294 status=XGetCommand(display,windows->image.id,&files,&count);
10297 ThrowXWindowFatalException(XServerError,"UnableToGetProperty","...");
10298 return((Image *) NULL);
10300 filelist=(char **) AcquireQuantumMemory((size_t) count,sizeof(*filelist));
10301 if (filelist == (char **) NULL)
10303 ThrowXWindowFatalException(ResourceLimitError,
10304 "MemoryAllocationFailed","...");
10305 (void) XFreeStringList(files);
10306 return((Image *) NULL);
10309 for (i=1; i < count; i++)
10310 if (*files[i] != '-')
10311 filelist[j++]=files[i];
10312 filelist[j]=(char *) NULL;
10313 XListBrowserWidget(display,windows,&windows->widget,
10314 (const char **) filelist,"Load","Select Image to Load:",filename);
10315 filelist=(char **) RelinquishMagickMemory(filelist);
10316 (void) XFreeStringList(files);
10318 if (*filename == '\0')
10319 return((Image *) NULL);
10320 image_info=CloneImageInfo(resource_info->image_info);
10321 (void) SetImageInfoProgressMonitor(image_info,(MagickProgressMonitor) NULL,
10323 (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
10324 exception=AcquireExceptionInfo();
10325 (void) SetImageInfo(image_info,0,exception);
10326 if (LocaleCompare(image_info->magick,"X") == 0)
10329 seconds[MaxTextExtent];
10332 User may want to delay the X server screen grab.
10334 (void) CopyMagickString(seconds,"0",MaxTextExtent);
10335 (void) XDialogWidget(display,windows,"Grab","Enter any delay in seconds:",
10337 if (*seconds == '\0')
10338 return((Image *) NULL);
10339 XDelay(display,(size_t) (1000*StringToLong(seconds)));
10341 magick_info=GetMagickInfo(image_info->magick,exception);
10342 if ((magick_info != (const MagickInfo *) NULL) &&
10343 IfMagickTrue(magick_info->raw))
10346 geometry[MaxTextExtent];
10349 Request image size from the user.
10351 (void) CopyMagickString(geometry,"512x512",MaxTextExtent);
10352 if (image_info->size != (char *) NULL)
10353 (void) CopyMagickString(geometry,image_info->size,MaxTextExtent);
10354 (void) XDialogWidget(display,windows,"Load","Enter the image geometry:",
10356 (void) CloneString(&image_info->size,geometry);
10361 XSetCursorState(display,windows,MagickTrue);
10362 XCheckRefreshWindows(display,windows);
10363 (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
10364 nexus=ReadImage(image_info,exception);
10365 CatchException(exception);
10366 XSetCursorState(display,windows,MagickFalse);
10367 if (nexus != (Image *) NULL)
10368 XClientMessage(display,windows->image.id,windows->im_protocols,
10369 windows->im_next_image,CurrentTime);
10377 Unknown image format.
10379 text=FileToString(filename,~0,exception);
10380 if (text == (char *) NULL)
10381 return((Image *) NULL);
10382 textlist=StringToList(text);
10383 if (textlist != (char **) NULL)
10386 title[MaxTextExtent];
10391 (void) FormatLocaleString(title,MaxTextExtent,
10392 "Unknown format: %s",filename);
10393 XTextViewWidget(display,resource_info,windows,MagickTrue,title,
10394 (const char **) textlist);
10395 for (i=0; textlist[i] != (char *) NULL; i++)
10396 textlist[i]=DestroyString(textlist[i]);
10397 textlist=(char **) RelinquishMagickMemory(textlist);
10399 text=DestroyString(text);
10401 exception=DestroyExceptionInfo(exception);
10402 image_info=DestroyImageInfo(image_info);
10407 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10411 + X P a n I m a g e %
10415 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10417 % XPanImage() pans the image until the mouse button is released.
10419 % The format of the XPanImage method is:
10421 % void XPanImage(Display *display,XWindows *windows,XEvent *event,
10422 % ExceptionInfo *exception)
10424 % A description of each parameter follows:
10426 % o display: Specifies a connection to an X server; returned from
10429 % o windows: Specifies a pointer to a XWindows structure.
10431 % o event: Specifies a pointer to a XEvent structure. If it is NULL,
10432 % the entire image is refreshed.
10434 % o exception: return any errors or warnings in this structure.
10437 static void XPanImage(Display *display,XWindows *windows,XEvent *event,
10438 ExceptionInfo *exception)
10441 text[MaxTextExtent];
10459 if ((windows->image.ximage->width > (int) windows->image.width) &&
10460 (windows->image.ximage->height > (int) windows->image.height))
10461 cursor=XCreateFontCursor(display,XC_fleur);
10463 if (windows->image.ximage->width > (int) windows->image.width)
10464 cursor=XCreateFontCursor(display,XC_sb_h_double_arrow);
10466 if (windows->image.ximage->height > (int) windows->image.height)
10467 cursor=XCreateFontCursor(display,XC_sb_v_double_arrow);
10469 cursor=XCreateFontCursor(display,XC_arrow);
10470 (void) XCheckDefineCursor(display,windows->pan.id,cursor);
10472 Pan image as pointer moves until the mouse button is released.
10474 x_factor=(double) windows->image.ximage->width/windows->pan.width;
10475 y_factor=(double) windows->image.ximage->height/windows->pan.height;
10476 pan_info.width=windows->pan.width*windows->image.width/
10477 windows->image.ximage->width;
10478 pan_info.height=windows->pan.height*windows->image.height/
10479 windows->image.ximage->height;
10482 state=UpdateConfigurationState;
10485 switch (event->type)
10490 User choose an initial pan location.
10492 pan_info.x=(ssize_t) event->xbutton.x;
10493 pan_info.y=(ssize_t) event->xbutton.y;
10494 state|=UpdateConfigurationState;
10497 case ButtonRelease:
10500 User has finished panning the image.
10502 pan_info.x=(ssize_t) event->xbutton.x;
10503 pan_info.y=(ssize_t) event->xbutton.y;
10504 state|=UpdateConfigurationState | ExitState;
10509 pan_info.x=(ssize_t) event->xmotion.x;
10510 pan_info.y=(ssize_t) event->xmotion.y;
10511 state|=UpdateConfigurationState;
10516 if ((state & UpdateConfigurationState) != 0)
10519 Check boundary conditions.
10521 if (pan_info.x < (ssize_t) (pan_info.width/2))
10524 pan_info.x=(ssize_t) (x_factor*(pan_info.x-(pan_info.width/2)));
10525 if (pan_info.x < 0)
10528 if ((int) (pan_info.x+windows->image.width) >
10529 windows->image.ximage->width)
10530 pan_info.x=(ssize_t)
10531 (windows->image.ximage->width-windows->image.width);
10532 if (pan_info.y < (ssize_t) (pan_info.height/2))
10535 pan_info.y=(ssize_t) (y_factor*(pan_info.y-(pan_info.height/2)));
10536 if (pan_info.y < 0)
10539 if ((int) (pan_info.y+windows->image.height) >
10540 windows->image.ximage->height)
10541 pan_info.y=(ssize_t)
10542 (windows->image.ximage->height-windows->image.height);
10543 if ((windows->image.x != (int) pan_info.x) ||
10544 (windows->image.y != (int) pan_info.y))
10547 Display image pan offset.
10549 windows->image.x=(int) pan_info.x;
10550 windows->image.y=(int) pan_info.y;
10551 (void) FormatLocaleString(text,MaxTextExtent," %ux%u%+d%+d ",
10552 windows->image.width,windows->image.height,windows->image.x,
10554 XInfoWidget(display,windows,text);
10556 Refresh Image window.
10558 XDrawPanRectangle(display,windows);
10559 XRefreshWindow(display,&windows->image,(XEvent *) NULL);
10561 state&=(~UpdateConfigurationState);
10564 Wait for next event.
10566 if ((state & ExitState) == 0)
10567 XScreenEvent(display,windows,event,exception);
10568 } while ((state & ExitState) == 0);
10572 (void) XCheckDefineCursor(display,windows->pan.id,windows->pan.cursor);
10573 (void) XFreeCursor(display,cursor);
10574 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
10578 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10582 + X P a s t e I m a g e %
10586 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10588 % XPasteImage() pastes an image previously saved with XCropImage in the X
10589 % window image at a location the user chooses with the pointer.
10591 % The format of the XPasteImage method is:
10593 % MagickBooleanType XPasteImage(Display *display,
10594 % XResourceInfo *resource_info,XWindows *windows,Image *image,
10595 % ExceptionInfo *exception)
10597 % A description of each parameter follows:
10599 % o display: Specifies a connection to an X server; returned from
10602 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
10604 % o windows: Specifies a pointer to a XWindows structure.
10606 % o image: the image; returned from ReadImage.
10608 % o exception: return any errors or warnings in this structure.
10611 static MagickBooleanType XPasteImage(Display *display,
10612 XResourceInfo *resource_info,XWindows *windows,Image *image,
10613 ExceptionInfo *exception)
10624 static const ModeType
10627 PasteOperatorsCommand,
10629 PasteDismissCommand
10632 static CompositeOperator
10633 compose = CopyCompositeOp;
10636 text[MaxTextExtent];
10670 if (resource_info->copy_image == (Image *) NULL)
10671 return(MagickFalse);
10672 paste_image=CloneImage(resource_info->copy_image,0,0,MagickTrue,exception);
10674 Map Command widget.
10676 (void) CloneString(&windows->command.name,"Paste");
10677 windows->command.data=1;
10678 (void) XCommandWidget(display,windows,PasteMenu,(XEvent *) NULL);
10679 (void) XMapRaised(display,windows->command.id);
10680 XClientMessage(display,windows->image.id,windows->im_protocols,
10681 windows->im_update_widget,CurrentTime);
10683 Track pointer until button 1 is pressed.
10685 XSetCursorState(display,windows,MagickFalse);
10686 XQueryPosition(display,windows->image.id,&x,&y);
10687 (void) XSelectInput(display,windows->image.id,
10688 windows->image.attributes.event_mask | PointerMotionMask);
10689 paste_info.x=(ssize_t) windows->image.x+x;
10690 paste_info.y=(ssize_t) windows->image.y+y;
10691 paste_info.width=0;
10692 paste_info.height=0;
10693 cursor=XCreateFontCursor(display,XC_ul_angle);
10694 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
10695 state=DefaultState;
10698 if( IfMagickTrue(windows->info.mapped) )
10701 Display pointer position.
10703 (void) FormatLocaleString(text,MaxTextExtent," %+ld%+ld ",
10704 (long) paste_info.x,(long) paste_info.y);
10705 XInfoWidget(display,windows,text);
10707 highlight_info=paste_info;
10708 highlight_info.x=paste_info.x-windows->image.x;
10709 highlight_info.y=paste_info.y-windows->image.y;
10710 XHighlightRectangle(display,windows->image.id,
10711 windows->image.highlight_context,&highlight_info);
10713 Wait for next event.
10715 XScreenEvent(display,windows,&event,exception);
10716 XHighlightRectangle(display,windows->image.id,
10717 windows->image.highlight_context,&highlight_info);
10718 if (event.xany.window == windows->command.id)
10721 Select a command from the Command widget.
10723 id=XCommandWidget(display,windows,PasteMenu,&event);
10726 switch (PasteCommands[id])
10728 case PasteOperatorsCommand:
10731 command[MaxTextExtent],
10735 Select a command from the pop-up menu.
10737 operators=GetCommandOptions(MagickComposeOptions);
10738 if (operators == (char **) NULL)
10740 entry=XMenuWidget(display,windows,PasteMenu[id],
10741 (const char **) operators,command);
10743 compose=(CompositeOperator) ParseCommandOption(
10744 MagickComposeOptions,MagickFalse,operators[entry]);
10745 operators=DestroyStringList(operators);
10748 case PasteHelpCommand:
10750 XTextViewWidget(display,resource_info,windows,MagickFalse,
10751 "Help Viewer - Image Composite",ImagePasteHelp);
10754 case PasteDismissCommand:
10759 state|=EscapeState;
10768 switch (event.type)
10772 if( IfMagickTrue(image->debug) )
10773 (void) LogMagickEvent(X11Event,GetMagickModule(),
10774 "Button Press: 0x%lx %u +%d+%d",event.xbutton.window,
10775 event.xbutton.button,event.xbutton.x,event.xbutton.y);
10776 if (event.xbutton.button != Button1)
10778 if (event.xbutton.window != windows->image.id)
10781 Paste rectangle is relative to image configuration.
10783 width=(unsigned int) image->columns;
10784 height=(unsigned int) image->rows;
10787 if (windows->image.crop_geometry != (char *) NULL)
10788 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,
10790 scale_factor=(double) windows->image.ximage->width/width;
10791 paste_info.width=(unsigned int) (scale_factor*paste_image->columns+0.5);
10792 scale_factor=(double) windows->image.ximage->height/height;
10793 paste_info.height=(unsigned int) (scale_factor*paste_image->rows+0.5);
10794 (void) XCheckDefineCursor(display,windows->image.id,cursor);
10795 paste_info.x=(ssize_t) windows->image.x+event.xbutton.x;
10796 paste_info.y=(ssize_t) windows->image.y+event.xbutton.y;
10799 case ButtonRelease:
10801 if( IfMagickTrue(image->debug) )
10802 (void) LogMagickEvent(X11Event,GetMagickModule(),
10803 "Button Release: 0x%lx %u +%d+%d",event.xbutton.window,
10804 event.xbutton.button,event.xbutton.x,event.xbutton.y);
10805 if (event.xbutton.button != Button1)
10807 if (event.xbutton.window != windows->image.id)
10809 if ((paste_info.width != 0) && (paste_info.height != 0))
10812 User has selected the location of the paste image.
10814 paste_info.x=(ssize_t) windows->image.x+event.xbutton.x;
10815 paste_info.y=(ssize_t) windows->image.y+event.xbutton.y;
10825 command[MaxTextExtent];
10833 if (event.xkey.window != windows->image.id)
10836 Respond to a user key press.
10838 length=XLookupString((XKeyEvent *) &event.xkey,command,(int)
10839 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
10840 *(command+length)='\0';
10841 if( IfMagickTrue(image->debug) )
10842 (void) LogMagickEvent(X11Event,GetMagickModule(),
10843 "Key press: 0x%lx (%s)",(long) key_symbol,command);
10844 switch ((int) key_symbol)
10852 paste_image=DestroyImage(paste_image);
10853 state|=EscapeState;
10860 (void) XSetFunction(display,windows->image.highlight_context,
10862 XTextViewWidget(display,resource_info,windows,MagickFalse,
10863 "Help Viewer - Image Composite",ImagePasteHelp);
10864 (void) XSetFunction(display,windows->image.highlight_context,
10870 (void) XBell(display,0);
10879 Map and unmap Info widget as text cursor crosses its boundaries.
10883 if( IfMagickTrue(windows->info.mapped) )
10885 if ((x < (int) (windows->info.x+windows->info.width)) &&
10886 (y < (int) (windows->info.y+windows->info.height)))
10887 (void) XWithdrawWindow(display,windows->info.id,
10888 windows->info.screen);
10891 if ((x > (int) (windows->info.x+windows->info.width)) ||
10892 (y > (int) (windows->info.y+windows->info.height)))
10893 (void) XMapWindow(display,windows->info.id);
10894 paste_info.x=(ssize_t) windows->image.x+x;
10895 paste_info.y=(ssize_t) windows->image.y+y;
10900 if( IfMagickTrue(image->debug) )
10901 (void) LogMagickEvent(X11Event,GetMagickModule(),"Event type: %d",
10906 } while ((state & ExitState) == 0);
10907 (void) XSelectInput(display,windows->image.id,
10908 windows->image.attributes.event_mask);
10909 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
10910 XSetCursorState(display,windows,MagickFalse);
10911 (void) XFreeCursor(display,cursor);
10912 if ((state & EscapeState) != 0)
10913 return(MagickTrue);
10915 Image pasting is relative to image configuration.
10917 XSetCursorState(display,windows,MagickTrue);
10918 XCheckRefreshWindows(display,windows);
10919 width=(unsigned int) image->columns;
10920 height=(unsigned int) image->rows;
10923 if (windows->image.crop_geometry != (char *) NULL)
10924 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
10925 scale_factor=(double) width/windows->image.ximage->width;
10927 paste_info.x=(ssize_t) (scale_factor*paste_info.x+0.5);
10928 paste_info.width=(unsigned int) (scale_factor*paste_info.width+0.5);
10929 scale_factor=(double) height/windows->image.ximage->height;
10931 paste_info.y=(ssize_t) (scale_factor*paste_info.y*scale_factor+0.5);
10932 paste_info.height=(unsigned int) (scale_factor*paste_info.height+0.5);
10934 Paste image with X Image window.
10936 (void) CompositeImage(image,paste_image,compose,MagickTrue,paste_info.x,
10937 paste_info.y,exception);
10938 paste_image=DestroyImage(paste_image);
10939 XSetCursorState(display,windows,MagickFalse);
10941 Update image colormap.
10943 XConfigureImageColormap(display,resource_info,windows,image,exception);
10944 (void) XConfigureImage(display,resource_info,windows,image,exception);
10945 return(MagickTrue);
10949 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10953 + X P r i n t I m a g e %
10957 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10959 % XPrintImage() prints an image to a Postscript printer.
10961 % The format of the XPrintImage method is:
10963 % MagickBooleanType XPrintImage(Display *display,
10964 % XResourceInfo *resource_info,XWindows *windows,Image *image,
10965 % ExceptionInfo *exception)
10967 % A description of each parameter follows:
10969 % o display: Specifies a connection to an X server; returned from
10972 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
10974 % o windows: Specifies a pointer to a XWindows structure.
10976 % o image: the image.
10978 % o exception: return any errors or warnings in this structure.
10981 static MagickBooleanType XPrintImage(Display *display,
10982 XResourceInfo *resource_info,XWindows *windows,Image *image,
10983 ExceptionInfo *exception)
10986 filename[MaxTextExtent],
10987 geometry[MaxTextExtent];
10999 Request Postscript page geometry from user.
11001 image_info=CloneImageInfo(resource_info->image_info);
11002 (void) FormatLocaleString(geometry,MaxTextExtent,"Letter");
11003 if (image_info->page != (char *) NULL)
11004 (void) CopyMagickString(geometry,image_info->page,MaxTextExtent);
11005 XListBrowserWidget(display,windows,&windows->widget,PageSizes,"Select",
11006 "Select Postscript Page Geometry:",geometry);
11007 if (*geometry == '\0')
11008 return(MagickTrue);
11009 image_info->page=GetPageGeometry(geometry);
11011 Apply image transforms.
11013 XSetCursorState(display,windows,MagickTrue);
11014 XCheckRefreshWindows(display,windows);
11015 print_image=CloneImage(image,0,0,MagickTrue,exception);
11016 if (print_image == (Image *) NULL)
11017 return(MagickFalse);
11018 (void) FormatLocaleString(geometry,MaxTextExtent,"%dx%d!",
11019 windows->image.ximage->width,windows->image.ximage->height);
11020 (void) TransformImage(&print_image,windows->image.crop_geometry,geometry,
11025 (void) AcquireUniqueFilename(filename);
11026 (void) FormatLocaleString(print_image->filename,MaxTextExtent,"print:%s",
11028 status=WriteImage(image_info,print_image,exception);
11029 (void) RelinquishUniqueFileResource(filename);
11030 print_image=DestroyImage(print_image);
11031 image_info=DestroyImageInfo(image_info);
11032 XSetCursorState(display,windows,MagickFalse);
11033 return(IsMagickTrue(status));
11037 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
11041 + X R O I I m a g e %
11045 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
11047 % XROIImage() applies an image processing technique to a region of interest.
11049 % The format of the XROIImage method is:
11051 % MagickBooleanType XROIImage(Display *display,
11052 % XResourceInfo *resource_info,XWindows *windows,Image **image,
11053 % ExceptionInfo *exception)
11055 % A description of each parameter follows:
11057 % o display: Specifies a connection to an X server; returned from
11060 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
11062 % o windows: Specifies a pointer to a XWindows structure.
11064 % o image: the image; returned from ReadImage.
11066 % o exception: return any errors or warnings in this structure.
11069 static MagickBooleanType XROIImage(Display *display,
11070 XResourceInfo *resource_info,XWindows *windows,Image **image,
11071 ExceptionInfo *exception)
11073 #define ApplyMenus 7
11123 "Contrast Stretch...",
11124 "Sigmoidal Contrast...",
11158 "Charcoal Draw...",
11161 *MiscellanyMenu[] =
11172 **Menus[ApplyMenus] =
11183 static const CommandType
11206 TransformCommands[] =
11210 RotateRightCommand,
11213 EnhanceCommands[] =
11221 ContrastStretchCommand,
11222 SigmoidalContrastCommand,
11230 EffectsCommands[] =
11234 ReduceNoiseCommand,
11253 CharcoalDrawCommand
11255 MiscellanyCommands[] =
11259 ShowPreviewCommand,
11260 ShowHistogramCommand,
11269 static const CommandType
11270 *Commands[ApplyMenus] =
11282 command[MaxTextExtent],
11283 text[MaxTextExtent];
11303 MagickProgressMonitor
11322 Map Command widget.
11324 (void) CloneString(&windows->command.name,"ROI");
11325 windows->command.data=0;
11326 (void) XCommandWidget(display,windows,ROIMenu,(XEvent *) NULL);
11327 (void) XMapRaised(display,windows->command.id);
11328 XClientMessage(display,windows->image.id,windows->im_protocols,
11329 windows->im_update_widget,CurrentTime);
11331 Track pointer until button 1 is pressed.
11333 XQueryPosition(display,windows->image.id,&x,&y);
11334 (void) XSelectInput(display,windows->image.id,
11335 windows->image.attributes.event_mask | PointerMotionMask);
11336 roi_info.x=(ssize_t) windows->image.x+x;
11337 roi_info.y=(ssize_t) windows->image.y+y;
11340 cursor=XCreateFontCursor(display,XC_fleur);
11341 state=DefaultState;
11344 if( IfMagickTrue(windows->info.mapped) )
11347 Display pointer position.
11349 (void) FormatLocaleString(text,MaxTextExtent," %+ld%+ld ",
11350 (long) roi_info.x,(long) roi_info.y);
11351 XInfoWidget(display,windows,text);
11354 Wait for next event.
11356 XScreenEvent(display,windows,&event,exception);
11357 if (event.xany.window == windows->command.id)
11360 Select a command from the Command widget.
11362 id=XCommandWidget(display,windows,ROIMenu,&event);
11365 switch (ROICommands[id])
11367 case ROIHelpCommand:
11369 XTextViewWidget(display,resource_info,windows,MagickFalse,
11370 "Help Viewer - Region of Interest",ImageROIHelp);
11373 case ROIDismissCommand:
11378 state|=EscapeState;
11387 switch (event.type)
11391 if (event.xbutton.button != Button1)
11393 if (event.xbutton.window != windows->image.id)
11396 Note first corner of region of interest rectangle-- exit loop.
11398 (void) XCheckDefineCursor(display,windows->image.id,cursor);
11399 roi_info.x=(ssize_t) windows->image.x+event.xbutton.x;
11400 roi_info.y=(ssize_t) windows->image.y+event.xbutton.y;
11404 case ButtonRelease:
11413 if (event.xkey.window != windows->image.id)
11416 Respond to a user key press.
11418 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
11419 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
11420 switch ((int) key_symbol)
11428 state|=EscapeState;
11435 XTextViewWidget(display,resource_info,windows,MagickFalse,
11436 "Help Viewer - Region of Interest",ImageROIHelp);
11441 (void) XBell(display,0);
11450 Map and unmap Info widget as text cursor crosses its boundaries.
11454 if( IfMagickTrue(windows->info.mapped) )
11456 if ((x < (int) (windows->info.x+windows->info.width)) &&
11457 (y < (int) (windows->info.y+windows->info.height)))
11458 (void) XWithdrawWindow(display,windows->info.id,
11459 windows->info.screen);
11462 if ((x > (int) (windows->info.x+windows->info.width)) ||
11463 (y > (int) (windows->info.y+windows->info.height)))
11464 (void) XMapWindow(display,windows->info.id);
11465 roi_info.x=(ssize_t) windows->image.x+x;
11466 roi_info.y=(ssize_t) windows->image.y+y;
11472 } while ((state & ExitState) == 0);
11473 (void) XSelectInput(display,windows->image.id,
11474 windows->image.attributes.event_mask);
11475 if ((state & EscapeState) != 0)
11478 User want to exit without region of interest.
11480 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
11481 (void) XFreeCursor(display,cursor);
11482 return(MagickTrue);
11484 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
11488 Size rectangle as pointer moves until the mouse button is released.
11490 x=(int) roi_info.x;
11491 y=(int) roi_info.y;
11494 state=DefaultState;
11497 highlight_info=roi_info;
11498 highlight_info.x=roi_info.x-windows->image.x;
11499 highlight_info.y=roi_info.y-windows->image.y;
11500 if ((highlight_info.width > 3) && (highlight_info.height > 3))
11503 Display info and draw region of interest rectangle.
11505 if( IfMagickFalse(windows->info.mapped) )
11506 (void) XMapWindow(display,windows->info.id);
11507 (void) FormatLocaleString(text,MaxTextExtent,
11508 " %.20gx%.20g%+.20g%+.20g",(double) roi_info.width,(double)
11509 roi_info.height,(double) roi_info.x,(double) roi_info.y);
11510 XInfoWidget(display,windows,text);
11511 XHighlightRectangle(display,windows->image.id,
11512 windows->image.highlight_context,&highlight_info);
11515 if( IfMagickTrue(windows->info.mapped) )
11516 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
11518 Wait for next event.
11520 XScreenEvent(display,windows,&event,exception);
11521 if ((highlight_info.width > 3) && (highlight_info.height > 3))
11522 XHighlightRectangle(display,windows->image.id,
11523 windows->image.highlight_context,&highlight_info);
11524 switch (event.type)
11528 roi_info.x=(ssize_t) windows->image.x+event.xbutton.x;
11529 roi_info.y=(ssize_t) windows->image.y+event.xbutton.y;
11532 case ButtonRelease:
11535 User has committed to region of interest rectangle.
11537 roi_info.x=(ssize_t) windows->image.x+event.xbutton.x;
11538 roi_info.y=(ssize_t) windows->image.y+event.xbutton.y;
11539 XSetCursorState(display,windows,MagickFalse);
11541 if (LocaleCompare(windows->command.name,"Apply") == 0)
11543 (void) CloneString(&windows->command.name,"Apply");
11544 windows->command.data=ApplyMenus;
11545 (void) XCommandWidget(display,windows,ApplyMenu,(XEvent *) NULL);
11552 roi_info.x=(ssize_t) windows->image.x+event.xmotion.x;
11553 roi_info.y=(ssize_t) windows->image.y+event.xmotion.y;
11558 if ((((int) roi_info.x != x) && ((int) roi_info.y != y)) ||
11559 ((state & ExitState) != 0))
11562 Check boundary conditions.
11564 if (roi_info.x < 0)
11567 if (roi_info.x > (ssize_t) windows->image.ximage->width)
11568 roi_info.x=(ssize_t) windows->image.ximage->width;
11569 if ((int) roi_info.x < x)
11570 roi_info.width=(unsigned int) (x-roi_info.x);
11573 roi_info.width=(unsigned int) (roi_info.x-x);
11574 roi_info.x=(ssize_t) x;
11576 if (roi_info.y < 0)
11579 if (roi_info.y > (ssize_t) windows->image.ximage->height)
11580 roi_info.y=(ssize_t) windows->image.ximage->height;
11581 if ((int) roi_info.y < y)
11582 roi_info.height=(unsigned int) (y-roi_info.y);
11585 roi_info.height=(unsigned int) (roi_info.y-y);
11586 roi_info.y=(ssize_t) y;
11589 } while ((state & ExitState) == 0);
11591 Wait for user to grab a corner of the rectangle or press return.
11593 state=DefaultState;
11594 command_type=NullCommand;
11595 (void) XMapWindow(display,windows->info.id);
11598 if( IfMagickTrue(windows->info.mapped) )
11601 Display pointer position.
11603 (void) FormatLocaleString(text,MaxTextExtent,
11604 " %.20gx%.20g%+.20g%+.20g",(double) roi_info.width,(double)
11605 roi_info.height,(double) roi_info.x,(double) roi_info.y);
11606 XInfoWidget(display,windows,text);
11608 highlight_info=roi_info;
11609 highlight_info.x=roi_info.x-windows->image.x;
11610 highlight_info.y=roi_info.y-windows->image.y;
11611 if ((highlight_info.width <= 3) || (highlight_info.height <= 3))
11613 state|=EscapeState;
11617 if ((state & UpdateRegionState) != 0)
11619 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
11620 switch (command_type)
11625 (void) XMagickCommand(display,resource_info,windows,command_type,
11632 Region of interest is relative to image configuration.
11634 progress_monitor=SetImageProgressMonitor(*image,
11635 (MagickProgressMonitor) NULL,(*image)->client_data);
11636 crop_info=roi_info;
11637 width=(unsigned int) (*image)->columns;
11638 height=(unsigned int) (*image)->rows;
11641 if (windows->image.crop_geometry != (char *) NULL)
11642 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,
11644 scale_factor=(double) width/windows->image.ximage->width;
11646 crop_info.x=(ssize_t) (scale_factor*crop_info.x+0.5);
11647 crop_info.width=(unsigned int) (scale_factor*crop_info.width+0.5);
11648 scale_factor=(double)
11649 height/windows->image.ximage->height;
11651 crop_info.y=(ssize_t) (scale_factor*crop_info.y+0.5);
11652 crop_info.height=(unsigned int)
11653 (scale_factor*crop_info.height+0.5);
11654 roi_image=CropImage(*image,&crop_info,exception);
11655 (void) SetImageProgressMonitor(*image,progress_monitor,
11656 (*image)->client_data);
11657 if (roi_image == (Image *) NULL)
11660 Apply image processing technique to the region of interest.
11662 windows->image.orphan=MagickTrue;
11663 (void) XMagickCommand(display,resource_info,windows,command_type,
11664 &roi_image,exception);
11665 progress_monitor=SetImageProgressMonitor(*image,
11666 (MagickProgressMonitor) NULL,(*image)->client_data);
11667 (void) XMagickCommand(display,resource_info,windows,
11668 SaveToUndoBufferCommand,image,exception);
11669 windows->image.orphan=MagickFalse;
11670 (void) CompositeImage(*image,roi_image,CopyCompositeOp,
11671 MagickTrue,crop_info.x,crop_info.y,exception);
11672 roi_image=DestroyImage(roi_image);
11673 (void) SetImageProgressMonitor(*image,progress_monitor,
11674 (*image)->client_data);
11678 if (command_type != InfoCommand)
11680 XConfigureImageColormap(display,resource_info,windows,*image,
11682 (void) XConfigureImage(display,resource_info,windows,*image,
11685 XCheckRefreshWindows(display,windows);
11686 XInfoWidget(display,windows,text);
11687 (void) XSetFunction(display,windows->image.highlight_context,
11689 state&=(~UpdateRegionState);
11691 XHighlightRectangle(display,windows->image.id,
11692 windows->image.highlight_context,&highlight_info);
11693 XScreenEvent(display,windows,&event,exception);
11694 if (event.xany.window == windows->command.id)
11697 Select a command from the Command widget.
11699 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
11700 command_type=NullCommand;
11701 id=XCommandWidget(display,windows,ApplyMenu,&event);
11704 (void) CopyMagickString(command,ApplyMenu[id],MaxTextExtent);
11705 command_type=ApplyCommands[id];
11706 if (id < ApplyMenus)
11709 Select a command from a pop-up menu.
11711 entry=XMenuWidget(display,windows,ApplyMenu[id],
11712 (const char **) Menus[id],command);
11715 (void) CopyMagickString(command,Menus[id][entry],
11717 command_type=Commands[id][entry];
11721 (void) XSetFunction(display,windows->image.highlight_context,
11723 XHighlightRectangle(display,windows->image.id,
11724 windows->image.highlight_context,&highlight_info);
11725 if (command_type == HelpCommand)
11727 (void) XSetFunction(display,windows->image.highlight_context,
11729 XTextViewWidget(display,resource_info,windows,MagickFalse,
11730 "Help Viewer - Region of Interest",ImageROIHelp);
11731 (void) XSetFunction(display,windows->image.highlight_context,
11735 if (command_type == QuitCommand)
11740 state|=EscapeState;
11744 if (command_type != NullCommand)
11745 state|=UpdateRegionState;
11748 XHighlightRectangle(display,windows->image.id,
11749 windows->image.highlight_context,&highlight_info);
11750 switch (event.type)
11754 x=windows->image.x;
11755 y=windows->image.y;
11756 if (event.xbutton.button != Button1)
11758 if (event.xbutton.window != windows->image.id)
11760 x=windows->image.x+event.xbutton.x;
11761 y=windows->image.y+event.xbutton.y;
11762 if ((x < (int) (roi_info.x+RoiDelta)) &&
11763 (x > (int) (roi_info.x-RoiDelta)) &&
11764 (y < (int) (roi_info.y+RoiDelta)) &&
11765 (y > (int) (roi_info.y-RoiDelta)))
11767 roi_info.x=(ssize_t) (roi_info.x+roi_info.width);
11768 roi_info.y=(ssize_t) (roi_info.y+roi_info.height);
11769 state|=UpdateConfigurationState;
11772 if ((x < (int) (roi_info.x+RoiDelta)) &&
11773 (x > (int) (roi_info.x-RoiDelta)) &&
11774 (y < (int) (roi_info.y+roi_info.height+RoiDelta)) &&
11775 (y > (int) (roi_info.y+roi_info.height-RoiDelta)))
11777 roi_info.x=(ssize_t) (roi_info.x+roi_info.width);
11778 state|=UpdateConfigurationState;
11781 if ((x < (int) (roi_info.x+roi_info.width+RoiDelta)) &&
11782 (x > (int) (roi_info.x+roi_info.width-RoiDelta)) &&
11783 (y < (int) (roi_info.y+RoiDelta)) &&
11784 (y > (int) (roi_info.y-RoiDelta)))
11786 roi_info.y=(ssize_t) (roi_info.y+roi_info.height);
11787 state|=UpdateConfigurationState;
11790 if ((x < (int) (roi_info.x+roi_info.width+RoiDelta)) &&
11791 (x > (int) (roi_info.x+roi_info.width-RoiDelta)) &&
11792 (y < (int) (roi_info.y+roi_info.height+RoiDelta)) &&
11793 (y > (int) (roi_info.y+roi_info.height-RoiDelta)))
11795 state|=UpdateConfigurationState;
11799 case ButtonRelease:
11801 if (event.xbutton.window == windows->pan.id)
11802 if ((highlight_info.x != crop_info.x-windows->image.x) ||
11803 (highlight_info.y != crop_info.y-windows->image.y))
11804 XHighlightRectangle(display,windows->image.id,
11805 windows->image.highlight_context,&highlight_info);
11806 (void) XSetSelectionOwner(display,XA_PRIMARY,windows->image.id,
11807 event.xbutton.time);
11812 if (event.xexpose.window == windows->image.id)
11813 if (event.xexpose.count == 0)
11815 event.xexpose.x=(int) highlight_info.x;
11816 event.xexpose.y=(int) highlight_info.y;
11817 event.xexpose.width=(int) highlight_info.width;
11818 event.xexpose.height=(int) highlight_info.height;
11819 XRefreshWindow(display,&windows->image,&event);
11821 if (event.xexpose.window == windows->info.id)
11822 if (event.xexpose.count == 0)
11823 XInfoWidget(display,windows,text);
11831 if (event.xkey.window != windows->image.id)
11834 Respond to a user key press.
11836 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
11837 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
11838 switch ((int) key_symbol)
11845 state|=EscapeState;
11854 roi_info.x=(ssize_t) (windows->image.width/2L-roi_info.width/2L);
11855 roi_info.y=(ssize_t) (windows->image.height/2L-
11856 roi_info.height/2L);
11888 (void) XSetFunction(display,windows->image.highlight_context,
11890 XTextViewWidget(display,resource_info,windows,MagickFalse,
11891 "Help Viewer - Region of Interest",ImageROIHelp);
11892 (void) XSetFunction(display,windows->image.highlight_context,
11898 command_type=XImageWindowCommand(display,resource_info,windows,
11899 event.xkey.state,key_symbol,image,exception);
11900 if (command_type != NullCommand)
11901 state|=UpdateRegionState;
11905 (void) XSetSelectionOwner(display,XA_PRIMARY,windows->image.id,
11913 if (event.xbutton.window != windows->image.id)
11916 Map and unmap Info widget as text cursor crosses its boundaries.
11920 if( IfMagickTrue(windows->info.mapped) )
11922 if ((x < (int) (windows->info.x+windows->info.width)) &&
11923 (y < (int) (windows->info.y+windows->info.height)))
11924 (void) XWithdrawWindow(display,windows->info.id,
11925 windows->info.screen);
11928 if ((x > (int) (windows->info.x+windows->info.width)) ||
11929 (y > (int) (windows->info.y+windows->info.height)))
11930 (void) XMapWindow(display,windows->info.id);
11931 roi_info.x=(ssize_t) windows->image.x+event.xmotion.x;
11932 roi_info.y=(ssize_t) windows->image.y+event.xmotion.y;
11935 case SelectionRequest:
11940 XSelectionRequestEvent
11944 Set primary selection.
11946 (void) FormatLocaleString(text,MaxTextExtent,
11947 "%.20gx%.20g%+.20g%+.20g",(double) roi_info.width,(double)
11948 roi_info.height,(double) roi_info.x,(double) roi_info.y);
11949 request=(&(event.xselectionrequest));
11950 (void) XChangeProperty(request->display,request->requestor,
11951 request->property,request->target,8,PropModeReplace,
11952 (unsigned char *) text,(int) strlen(text));
11953 notify.type=SelectionNotify;
11954 notify.display=request->display;
11955 notify.requestor=request->requestor;
11956 notify.selection=request->selection;
11957 notify.target=request->target;
11958 notify.time=request->time;
11959 if (request->property == None)
11960 notify.property=request->target;
11962 notify.property=request->property;
11963 (void) XSendEvent(request->display,request->requestor,False,0,
11964 (XEvent *) ¬ify);
11969 if ((state & UpdateConfigurationState) != 0)
11971 (void) XPutBackEvent(display,&event);
11972 (void) XCheckDefineCursor(display,windows->image.id,cursor);
11975 } while ((state & ExitState) == 0);
11976 } while ((state & ExitState) == 0);
11977 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
11978 XSetCursorState(display,windows,MagickFalse);
11979 if ((state & EscapeState) != 0)
11980 return(MagickTrue);
11981 return(MagickTrue);
11985 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
11989 + X R o t a t e I m a g e %
11993 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
11995 % XRotateImage() rotates the X image. If the degrees parameter if zero, the
11996 % rotation angle is computed from the slope of a line drawn by the user.
11998 % The format of the XRotateImage method is:
12000 % MagickBooleanType XRotateImage(Display *display,
12001 % XResourceInfo *resource_info,XWindows *windows,double degrees,
12002 % Image **image,ExceptionInfo *exception)
12004 % A description of each parameter follows:
12006 % o display: Specifies a connection to an X server; returned from
12009 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
12011 % o windows: Specifies a pointer to a XWindows structure.
12013 % o degrees: Specifies the number of degrees to rotate the image.
12015 % o image: the image.
12017 % o exception: return any errors or warnings in this structure.
12020 static MagickBooleanType XRotateImage(Display *display,
12021 XResourceInfo *resource_info,XWindows *windows,double degrees,Image **image,
12022 ExceptionInfo *exception)
12035 direction = HorizontalRotateCommand;
12037 static const ModeType
12038 DirectionCommands[] =
12040 HorizontalRotateCommand,
12041 VerticalRotateCommand
12045 RotateColorCommand,
12046 RotateDirectionCommand,
12048 RotateDismissCommand
12051 static unsigned int
12055 command[MaxTextExtent],
12056 text[MaxTextExtent];
12067 normalized_degrees;
12077 if (degrees == 0.0)
12092 Map Command widget.
12094 (void) CloneString(&windows->command.name,"Rotate");
12095 windows->command.data=2;
12096 (void) XCommandWidget(display,windows,RotateMenu,(XEvent *) NULL);
12097 (void) XMapRaised(display,windows->command.id);
12098 XClientMessage(display,windows->image.id,windows->im_protocols,
12099 windows->im_update_widget,CurrentTime);
12101 Wait for first button press.
12103 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
12104 XQueryPosition(display,windows->image.id,&x,&y);
12109 state=DefaultState;
12112 XHighlightLine(display,windows->image.id,
12113 windows->image.highlight_context,&rotate_info);
12115 Wait for next event.
12117 XScreenEvent(display,windows,&event,exception);
12118 XHighlightLine(display,windows->image.id,
12119 windows->image.highlight_context,&rotate_info);
12120 if (event.xany.window == windows->command.id)
12123 Select a command from the Command widget.
12125 id=XCommandWidget(display,windows,RotateMenu,&event);
12128 (void) XSetFunction(display,windows->image.highlight_context,
12130 switch (RotateCommands[id])
12132 case RotateColorCommand:
12135 *ColorMenu[MaxNumberPens];
12144 Initialize menu selections.
12146 for (i=0; i < (int) (MaxNumberPens-2); i++)
12147 ColorMenu[i]=resource_info->pen_colors[i];
12148 ColorMenu[MaxNumberPens-2]="Browser...";
12149 ColorMenu[MaxNumberPens-1]=(const char *) NULL;
12151 Select a pen color from the pop-up menu.
12153 pen_number=XMenuWidget(display,windows,RotateMenu[id],
12154 (const char **) ColorMenu,command);
12155 if (pen_number < 0)
12157 if (pen_number == (MaxNumberPens-2))
12160 color_name[MaxTextExtent] = "gray";
12163 Select a pen color from a dialog.
12165 resource_info->pen_colors[pen_number]=color_name;
12166 XColorBrowserWidget(display,windows,"Select",color_name);
12167 if (*color_name == '\0')
12173 (void) XParseColor(display,windows->map_info->colormap,
12174 resource_info->pen_colors[pen_number],&color);
12175 XBestPixel(display,windows->map_info->colormap,(XColor *) NULL,
12176 (unsigned int) MaxColors,&color);
12177 windows->pixel_info->pen_colors[pen_number]=color;
12178 pen_id=(unsigned int) pen_number;
12181 case RotateDirectionCommand:
12192 Select a command from the pop-up menu.
12194 id=XMenuWidget(display,windows,RotateMenu[id],
12195 Directions,command);
12197 direction=DirectionCommands[id];
12200 case RotateHelpCommand:
12202 XTextViewWidget(display,resource_info,windows,MagickFalse,
12203 "Help Viewer - Image Rotation",ImageRotateHelp);
12206 case RotateDismissCommand:
12211 state|=EscapeState;
12218 (void) XSetFunction(display,windows->image.highlight_context,
12222 switch (event.type)
12226 if (event.xbutton.button != Button1)
12228 if (event.xbutton.window != windows->image.id)
12233 (void) XSetFunction(display,windows->image.highlight_context,
12235 rotate_info.x1=event.xbutton.x;
12236 rotate_info.y1=event.xbutton.y;
12240 case ButtonRelease:
12247 command[MaxTextExtent];
12252 if (event.xkey.window != windows->image.id)
12255 Respond to a user key press.
12257 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
12258 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
12259 switch ((int) key_symbol)
12267 state|=EscapeState;
12274 (void) XSetFunction(display,windows->image.highlight_context,
12276 XTextViewWidget(display,resource_info,windows,MagickFalse,
12277 "Help Viewer - Image Rotation",ImageRotateHelp);
12278 (void) XSetFunction(display,windows->image.highlight_context,
12284 (void) XBell(display,0);
12292 rotate_info.x1=event.xmotion.x;
12293 rotate_info.y1=event.xmotion.y;
12296 rotate_info.x2=rotate_info.x1;
12297 rotate_info.y2=rotate_info.y1;
12298 if (direction == HorizontalRotateCommand)
12299 rotate_info.x2+=32;
12301 rotate_info.y2-=32;
12302 } while ((state & ExitState) == 0);
12303 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
12304 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
12305 if ((state & EscapeState) != 0)
12306 return(MagickTrue);
12308 Draw line as pointer moves until the mouse button is released.
12311 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
12312 state=DefaultState;
12318 Display info and draw rotation line.
12320 if( IfMagickFalse(windows->info.mapped) )
12321 (void) XMapWindow(display,windows->info.id);
12322 (void) FormatLocaleString(text,MaxTextExtent," %g",
12323 direction == VerticalRotateCommand ? degrees-90.0 : degrees);
12324 XInfoWidget(display,windows,text);
12325 XHighlightLine(display,windows->image.id,
12326 windows->image.highlight_context,&rotate_info);
12329 if( IfMagickTrue(windows->info.mapped) )
12330 (void) XWithdrawWindow(display,windows->info.id,
12331 windows->info.screen);
12333 Wait for next event.
12335 XScreenEvent(display,windows,&event,exception);
12337 XHighlightLine(display,windows->image.id,
12338 windows->image.highlight_context,&rotate_info);
12339 switch (event.type)
12343 case ButtonRelease:
12346 User has committed to rotation line.
12348 rotate_info.x2=event.xbutton.x;
12349 rotate_info.y2=event.xbutton.y;
12357 rotate_info.x2=event.xmotion.x;
12358 rotate_info.y2=event.xmotion.y;
12364 Check boundary conditions.
12366 if (rotate_info.x2 < 0)
12369 if (rotate_info.x2 > (int) windows->image.width)
12370 rotate_info.x2=(short) windows->image.width;
12371 if (rotate_info.y2 < 0)
12374 if (rotate_info.y2 > (int) windows->image.height)
12375 rotate_info.y2=(short) windows->image.height;
12377 Compute rotation angle from the slope of the line.
12380 distance=(unsigned int)
12381 ((rotate_info.x2-rotate_info.x1+1)*(rotate_info.x2-rotate_info.x1+1))+
12382 ((rotate_info.y2-rotate_info.y1+1)*(rotate_info.y2-rotate_info.y1+1));
12384 degrees=RadiansToDegrees(-atan2((double) (rotate_info.y2-
12385 rotate_info.y1),(double) (rotate_info.x2-rotate_info.x1)));
12386 } while ((state & ExitState) == 0);
12387 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
12388 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
12390 return(MagickTrue);
12392 if (direction == VerticalRotateCommand)
12394 if (degrees == 0.0)
12395 return(MagickTrue);
12399 normalized_degrees=degrees;
12400 while (normalized_degrees < -45.0)
12401 normalized_degrees+=360.0;
12402 for (rotations=0; normalized_degrees > 45.0; rotations++)
12403 normalized_degrees-=90.0;
12404 if (normalized_degrees != 0.0)
12405 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image,
12407 XSetCursorState(display,windows,MagickTrue);
12408 XCheckRefreshWindows(display,windows);
12409 (*image)->background_color.red=(double) ScaleShortToQuantum(
12410 windows->pixel_info->pen_colors[pen_id].red);
12411 (*image)->background_color.green=(double) ScaleShortToQuantum(
12412 windows->pixel_info->pen_colors[pen_id].green);
12413 (*image)->background_color.blue=(double) ScaleShortToQuantum(
12414 windows->pixel_info->pen_colors[pen_id].blue);
12415 rotate_image=RotateImage(*image,degrees,exception);
12416 XSetCursorState(display,windows,MagickFalse);
12417 if (rotate_image == (Image *) NULL)
12418 return(MagickFalse);
12419 *image=DestroyImage(*image);
12420 *image=rotate_image;
12421 if (windows->image.crop_geometry != (char *) NULL)
12424 Rotate crop geometry.
12426 width=(unsigned int) (*image)->columns;
12427 height=(unsigned int) (*image)->rows;
12428 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
12429 switch (rotations % 4)
12439 (void) FormatLocaleString(windows->image.crop_geometry,MaxTextExtent,
12440 "%ux%u%+d%+d",height,width,(int) (*image)->columns-
12447 Rotate 180 degrees.
12449 (void) FormatLocaleString(windows->image.crop_geometry,MaxTextExtent,
12450 "%ux%u%+d%+d",width,height,(int) width-x,(int) height-y);
12456 Rotate 270 degrees.
12458 (void) FormatLocaleString(windows->image.crop_geometry,MaxTextExtent,
12459 "%ux%u%+d%+d",height,width,y,(int) (*image)->rows-(int) width-x);
12464 if( IfMagickTrue(windows->image.orphan) )
12465 return(MagickTrue);
12466 if (normalized_degrees != 0.0)
12469 Update image colormap.
12471 windows->image.window_changes.width=(int) (*image)->columns;
12472 windows->image.window_changes.height=(int) (*image)->rows;
12473 if (windows->image.crop_geometry != (char *) NULL)
12476 Obtain dimensions of image from crop geometry.
12478 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,
12480 windows->image.window_changes.width=(int) width;
12481 windows->image.window_changes.height=(int) height;
12483 XConfigureImageColormap(display,resource_info,windows,*image,exception);
12486 if (((rotations % 4) == 1) || ((rotations % 4) == 3))
12488 windows->image.window_changes.width=windows->image.ximage->height;
12489 windows->image.window_changes.height=windows->image.ximage->width;
12492 Update image configuration.
12494 (void) XConfigureImage(display,resource_info,windows,*image,exception);
12495 return(MagickTrue);
12499 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12503 + X S a v e I m a g e %
12507 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12509 % XSaveImage() saves an image to a file.
12511 % The format of the XSaveImage method is:
12513 % MagickBooleanType XSaveImage(Display *display,
12514 % XResourceInfo *resource_info,XWindows *windows,Image *image,
12515 % ExceptionInfo *exception)
12517 % A description of each parameter follows:
12519 % o display: Specifies a connection to an X server; returned from
12522 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
12524 % o windows: Specifies a pointer to a XWindows structure.
12526 % o image: the image.
12528 % o exception: return any errors or warnings in this structure.
12531 static MagickBooleanType XSaveImage(Display *display,
12532 XResourceInfo *resource_info,XWindows *windows,Image *image,
12533 ExceptionInfo *exception)
12536 filename[MaxTextExtent],
12537 geometry[MaxTextExtent];
12549 Request file name from user.
12551 if (resource_info->write_filename != (char *) NULL)
12552 (void) CopyMagickString(filename,resource_info->write_filename,
12557 path[MaxTextExtent];
12562 GetPathComponent(image->filename,HeadPath,path);
12563 GetPathComponent(image->filename,TailPath,filename);
12566 status=chdir(path);
12568 (void) ThrowMagickException(exception,GetMagickModule(),
12569 FileOpenError,"UnableToOpenFile","%s",path);
12572 XFileBrowserWidget(display,windows,"Save",filename);
12573 if (*filename == '\0')
12574 return(MagickTrue);
12575 if( IfMagickTrue(IsPathAccessible(filename)) )
12581 File exists-- seek user's permission before overwriting.
12583 status=XConfirmWidget(display,windows,"Overwrite",filename);
12585 return(MagickTrue);
12587 image_info=CloneImageInfo(resource_info->image_info);
12588 (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
12589 (void) SetImageInfo(image_info,1,exception);
12590 if ((LocaleCompare(image_info->magick,"JPEG") == 0) ||
12591 (LocaleCompare(image_info->magick,"JPG") == 0))
12594 quality[MaxTextExtent];
12600 Request JPEG quality from user.
12602 (void) FormatLocaleString(quality,MaxTextExtent,"%.20g",(double)
12604 status=XDialogWidget(display,windows,"Save","Enter JPEG quality:",
12606 if (*quality == '\0')
12607 return(MagickTrue);
12608 image->quality=StringToUnsignedLong(quality);
12609 image_info->interlace=status != 0 ? NoInterlace : PlaneInterlace;
12611 if ((LocaleCompare(image_info->magick,"EPS") == 0) ||
12612 (LocaleCompare(image_info->magick,"PDF") == 0) ||
12613 (LocaleCompare(image_info->magick,"PS") == 0) ||
12614 (LocaleCompare(image_info->magick,"PS2") == 0))
12617 geometry[MaxTextExtent];
12620 Request page geometry from user.
12622 (void) CopyMagickString(geometry,PSPageGeometry,MaxTextExtent);
12623 if (LocaleCompare(image_info->magick,"PDF") == 0)
12624 (void) CopyMagickString(geometry,PSPageGeometry,MaxTextExtent);
12625 if (image_info->page != (char *) NULL)
12626 (void) CopyMagickString(geometry,image_info->page,MaxTextExtent);
12627 XListBrowserWidget(display,windows,&windows->widget,PageSizes,"Select",
12628 "Select page geometry:",geometry);
12629 if (*geometry != '\0')
12630 image_info->page=GetPageGeometry(geometry);
12633 Apply image transforms.
12635 XSetCursorState(display,windows,MagickTrue);
12636 XCheckRefreshWindows(display,windows);
12637 save_image=CloneImage(image,0,0,MagickTrue,exception);
12638 if (save_image == (Image *) NULL)
12639 return(MagickFalse);
12640 (void) FormatLocaleString(geometry,MaxTextExtent,"%dx%d!",
12641 windows->image.ximage->width,windows->image.ximage->height);
12642 (void) TransformImage(&save_image,windows->image.crop_geometry,geometry,
12647 (void) CopyMagickString(save_image->filename,filename,MaxTextExtent);
12648 status=WriteImage(image_info,save_image,exception);
12649 if( IfMagickTrue(status) )
12650 image->taint=MagickFalse;
12651 save_image=DestroyImage(save_image);
12652 image_info=DestroyImageInfo(image_info);
12653 XSetCursorState(display,windows,MagickFalse);
12654 return(IsMagickTrue(status));
12658 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12662 + X S c r e e n E v e n t %
12666 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12668 % XScreenEvent() handles global events associated with the Pan and Magnify
12671 % The format of the XScreenEvent function is:
12673 % void XScreenEvent(Display *display,XWindows *windows,XEvent *event,
12674 % ExceptionInfo *exception)
12676 % A description of each parameter follows:
12678 % o display: Specifies a pointer to the Display structure; returned from
12681 % o windows: Specifies a pointer to a XWindows structure.
12683 % o event: Specifies a pointer to a X11 XEvent structure.
12685 % o exception: return any errors or warnings in this structure.
12689 #if defined(__cplusplus) || defined(c_plusplus)
12693 static int XPredicate(Display *magick_unused(display),XEvent *event,char *data)
12698 windows=(XWindows *) data;
12699 if ((event->type == ClientMessage) &&
12700 (event->xclient.window == windows->image.id))
12701 return(MagickFalse);
12702 return(MagickTrue);
12705 #if defined(__cplusplus) || defined(c_plusplus)
12709 static void XScreenEvent(Display *display,XWindows *windows,XEvent *event,
12710 ExceptionInfo *exception)
12716 (void) XIfEvent(display,event,XPredicate,(char *) windows);
12717 if (event->xany.window == windows->command.id)
12719 switch (event->type)
12722 case ButtonRelease:
12724 if ((event->xbutton.button == Button3) &&
12725 (event->xbutton.state & Mod1Mask))
12728 Convert Alt-Button3 to Button2.
12730 event->xbutton.button=Button2;
12731 event->xbutton.state&=(~Mod1Mask);
12733 if (event->xbutton.window == windows->backdrop.id)
12735 (void) XSetInputFocus(display,event->xbutton.window,RevertToParent,
12736 event->xbutton.time);
12739 if (event->xbutton.window == windows->pan.id)
12741 XPanImage(display,windows,event,exception);
12744 if (event->xbutton.window == windows->image.id)
12745 if (event->xbutton.button == Button2)
12748 Update magnified image.
12750 x=event->xbutton.x;
12751 y=event->xbutton.y;
12755 if (x >= (int) windows->image.width)
12756 x=(int) (windows->image.width-1);
12757 windows->magnify.x=(int) windows->image.x+x;
12761 if (y >= (int) windows->image.height)
12762 y=(int) (windows->image.height-1);
12763 windows->magnify.y=windows->image.y+y;
12764 if( IfMagickFalse(windows->magnify.mapped) )
12765 (void) XMapRaised(display,windows->magnify.id);
12766 XMakeMagnifyImage(display,windows,exception);
12767 if (event->type == ButtonRelease)
12768 (void) XWithdrawWindow(display,windows->info.id,
12769 windows->info.screen);
12774 case ClientMessage:
12777 If client window delete message, exit.
12779 if (event->xclient.message_type != windows->wm_protocols)
12781 if (*event->xclient.data.l != (long) windows->wm_delete_window)
12783 if (event->xclient.window == windows->magnify.id)
12785 (void) XWithdrawWindow(display,windows->magnify.id,
12786 windows->magnify.screen);
12791 case ConfigureNotify:
12793 if (event->xconfigure.window == windows->magnify.id)
12799 Magnify window has a new configuration.
12801 windows->magnify.width=(unsigned int) event->xconfigure.width;
12802 windows->magnify.height=(unsigned int) event->xconfigure.height;
12803 if( IfMagickFalse(windows->magnify.mapped) )
12806 while ((int) magnify <= event->xconfigure.width)
12808 while ((int) magnify <= event->xconfigure.height)
12811 if (((int) magnify != event->xconfigure.width) ||
12812 ((int) magnify != event->xconfigure.height))
12817 window_changes.width=(int) magnify;
12818 window_changes.height=(int) magnify;
12819 (void) XReconfigureWMWindow(display,windows->magnify.id,
12820 windows->magnify.screen,(unsigned int) (CWWidth | CWHeight),
12824 XMakeMagnifyImage(display,windows,exception);
12831 if (event->xexpose.window == windows->image.id)
12833 XRefreshWindow(display,&windows->image,event);
12836 if (event->xexpose.window == windows->pan.id)
12837 if (event->xexpose.count == 0)
12839 XDrawPanRectangle(display,windows);
12842 if (event->xexpose.window == windows->magnify.id)
12843 if (event->xexpose.count == 0)
12845 XMakeMagnifyImage(display,windows,exception);
12853 command[MaxTextExtent];
12858 if (event->xkey.window != windows->magnify.id)
12861 Respond to a user key press.
12863 (void) XLookupString((XKeyEvent *) &event->xkey,command,(int)
12864 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
12865 XMagnifyWindowCommand(display,windows,event->xkey.state,key_symbol,
12871 if (event->xmap.window == windows->magnify.id)
12873 windows->magnify.mapped=MagickTrue;
12874 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
12877 if (event->xmap.window == windows->info.id)
12879 windows->info.mapped=MagickTrue;
12886 while (XCheckMaskEvent(display,ButtonMotionMask,event)) ;
12887 if (event->xmotion.window == windows->image.id)
12888 if( IfMagickTrue(windows->magnify.mapped) )
12891 Update magnified image.
12893 x=event->xmotion.x;
12894 y=event->xmotion.y;
12898 if (x >= (int) windows->image.width)
12899 x=(int) (windows->image.width-1);
12900 windows->magnify.x=(int) windows->image.x+x;
12904 if (y >= (int) windows->image.height)
12905 y=(int) (windows->image.height-1);
12906 windows->magnify.y=windows->image.y+y;
12907 XMakeMagnifyImage(display,windows,exception);
12913 if (event->xunmap.window == windows->magnify.id)
12915 windows->magnify.mapped=MagickFalse;
12918 if (event->xunmap.window == windows->info.id)
12920 windows->info.mapped=MagickFalse;
12931 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12935 + X S e t C r o p G e o m e t r y %
12939 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12941 % XSetCropGeometry() accepts a cropping geometry relative to the Image window
12942 % and translates it to a cropping geometry relative to the image.
12944 % The format of the XSetCropGeometry method is:
12946 % void XSetCropGeometry(Display *display,XWindows *windows,
12947 % RectangleInfo *crop_info,Image *image)
12949 % A description of each parameter follows:
12951 % o display: Specifies a connection to an X server; returned from
12954 % o windows: Specifies a pointer to a XWindows structure.
12956 % o crop_info: A pointer to a RectangleInfo that defines a region of the
12957 % Image window to crop.
12959 % o image: the image.
12962 static void XSetCropGeometry(Display *display,XWindows *windows,
12963 RectangleInfo *crop_info,Image *image)
12966 text[MaxTextExtent];
12979 if( IfMagickTrue(windows->info.mapped) )
12982 Display info on cropping rectangle.
12984 (void) FormatLocaleString(text,MaxTextExtent," %.20gx%.20g%+.20g%+.20g",
12985 (double) crop_info->width,(double) crop_info->height,(double)
12986 crop_info->x,(double) crop_info->y);
12987 XInfoWidget(display,windows,text);
12990 Cropping geometry is relative to any previous crop geometry.
12994 width=(unsigned int) image->columns;
12995 height=(unsigned int) image->rows;
12996 if (windows->image.crop_geometry != (char *) NULL)
12997 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
12999 windows->image.crop_geometry=AcquireString((char *) NULL);
13001 Define the crop geometry string from the cropping rectangle.
13003 scale_factor=(double) width/windows->image.ximage->width;
13004 if (crop_info->x > 0)
13005 x+=(int) (scale_factor*crop_info->x+0.5);
13006 width=(unsigned int) (scale_factor*crop_info->width+0.5);
13009 scale_factor=(double) height/windows->image.ximage->height;
13010 if (crop_info->y > 0)
13011 y+=(int) (scale_factor*crop_info->y+0.5);
13012 height=(unsigned int) (scale_factor*crop_info->height+0.5);
13015 (void) FormatLocaleString(windows->image.crop_geometry,MaxTextExtent,
13016 "%ux%u%+d%+d",width,height,x,y);
13020 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13024 + X T i l e I m a g e %
13028 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13030 % XTileImage() loads or deletes a selected tile from a visual image directory.
13031 % The load or delete command is chosen from a menu.
13033 % The format of the XTileImage method is:
13035 % Image *XTileImage(Display *display,XResourceInfo *resource_info,
13036 % XWindows *windows,Image *image,XEvent *event,ExceptionInfo *exception)
13038 % A description of each parameter follows:
13040 % o tile_image: XTileImage reads or deletes the tile image
13041 % and returns it. A null image is returned if an error occurs.
13043 % o display: Specifies a connection to an X server; returned from
13046 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
13048 % o windows: Specifies a pointer to a XWindows structure.
13050 % o image: the image; returned from ReadImage.
13052 % o event: Specifies a pointer to a XEvent structure. If it is NULL,
13053 % the entire image is refreshed.
13055 % o exception: return any errors or warnings in this structure.
13058 static Image *XTileImage(Display *display,XResourceInfo *resource_info,
13059 XWindows *windows,Image *image,XEvent *event,ExceptionInfo *exception)
13072 static const ModeType
13083 command[MaxTextExtent],
13084 filename[MaxTextExtent];
13111 Tile image is relative to montage image configuration.
13115 width=(unsigned int) image->columns;
13116 height=(unsigned int) image->rows;
13117 if (windows->image.crop_geometry != (char *) NULL)
13118 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
13119 scale_factor=(double) width/windows->image.ximage->width;
13120 event->xbutton.x+=windows->image.x;
13121 event->xbutton.x=(int) (scale_factor*event->xbutton.x+x+0.5);
13122 scale_factor=(double) height/windows->image.ximage->height;
13123 event->xbutton.y+=windows->image.y;
13124 event->xbutton.y=(int) (scale_factor*event->xbutton.y+y+0.5);
13126 Determine size and location of each tile in the visual image directory.
13128 width=(unsigned int) image->columns;
13129 height=(unsigned int) image->rows;
13132 (void) XParseGeometry(image->montage,&x,&y,&width,&height);
13133 tile=((event->xbutton.y-y)/height)*(((int) image->columns-x)/width)+
13134 (event->xbutton.x-x)/width;
13138 Button press is outside any tile.
13140 (void) XBell(display,0);
13141 return((Image *) NULL);
13144 Determine file name from the tile directory.
13146 p=image->directory;
13147 for (i=tile; (i != 0) && (*p != '\0'); )
13156 Button press is outside any tile.
13158 (void) XBell(display,0);
13159 return((Image *) NULL);
13162 Select a command from the pop-up menu.
13164 id=XMenuWidget(display,windows,"Tile Verb",VerbMenu,command);
13166 return((Image *) NULL);
13168 while ((*q != '\n') && (*q != '\0'))
13170 (void) CopyMagickString(filename,p,(size_t) (q-p+1));
13172 Perform command for the selected tile.
13174 XSetCursorState(display,windows,MagickTrue);
13175 XCheckRefreshWindows(display,windows);
13176 tile_image=NewImageList();
13177 switch (TileCommands[id])
13179 case TileLoadCommand:
13184 XCheckRefreshWindows(display,windows);
13185 (void) CopyMagickString(resource_info->image_info->magick,"MIFF",
13187 (void) CopyMagickString(resource_info->image_info->filename,filename,
13189 tile_image=ReadImage(resource_info->image_info,exception);
13190 CatchException(exception);
13191 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
13194 case TileNextCommand:
13197 Display next image.
13199 XClientMessage(display,windows->image.id,windows->im_protocols,
13200 windows->im_next_image,CurrentTime);
13203 case TileFormerCommand:
13206 Display former image.
13208 XClientMessage(display,windows->image.id,windows->im_protocols,
13209 windows->im_former_image,CurrentTime);
13212 case TileDeleteCommand:
13217 if( IfMagickFalse(IsPathAccessible(filename)) )
13219 XNoticeWidget(display,windows,"Image file does not exist:",filename);
13222 status=XConfirmWidget(display,windows,"Really delete tile",filename);
13225 status=IsMagickTrue(remove_utf8(filename));
13226 if( IfMagickTrue(status) )
13228 XNoticeWidget(display,windows,"Unable to delete image file:",
13233 case TileUpdateCommand:
13249 Ensure all the images exist.
13252 GetPixelInfo(image,&pixel);
13253 for (p=image->directory; *p != '\0'; p++)
13259 while ((*q != '\n') && (*q != '\0'))
13261 (void) CopyMagickString(filename,p,(size_t) (q-p+1));
13263 if( IfMagickTrue(IsPathAccessible(filename)) )
13269 Overwrite tile with background color.
13271 x_offset=(int) (width*(tile % (((int) image->columns-x)/width))+x);
13272 y_offset=(int) (height*(tile/(((int) image->columns-x)/width))+y);
13273 image_view=AcquireAuthenticCacheView(image,exception);
13274 (void) GetOneCacheViewVirtualPixelInfo(image_view,0,0,&pixel,exception);
13275 for (i=0; i < (int) height; i++)
13277 s=GetCacheViewAuthenticPixels(image_view,(ssize_t) x_offset,(ssize_t)
13278 y_offset+i,width,1,exception);
13279 if (s == (Quantum *) NULL)
13281 for (j=0; j < (int) width; j++)
13283 SetPixelInfoPixel(image,&pixel,s);
13284 s+=GetPixelChannels(image);
13286 if( IfMagickFalse(SyncCacheViewAuthenticPixels(image_view,exception)) )
13289 image_view=DestroyCacheView(image_view);
13292 windows->image.window_changes.width=(int) image->columns;
13293 windows->image.window_changes.height=(int) image->rows;
13294 XConfigureImageColormap(display,resource_info,windows,image,exception);
13295 (void) XConfigureImage(display,resource_info,windows,image,exception);
13301 XSetCursorState(display,windows,MagickFalse);
13302 return(tile_image);
13306 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13310 + X T r a n s l a t e I m a g e %
13314 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13316 % XTranslateImage() translates the image within an Image window by one pixel
13317 % as specified by the key symbol. If the image has a montage string the
13318 % translation is respect to the width and height contained within the string.
13320 % The format of the XTranslateImage method is:
13322 % void XTranslateImage(Display *display,XWindows *windows,
13323 % Image *image,const KeySym key_symbol)
13325 % A description of each parameter follows:
13327 % o display: Specifies a connection to an X server; returned from
13330 % o windows: Specifies a pointer to a XWindows structure.
13332 % o image: the image.
13334 % o key_symbol: Specifies a KeySym which indicates which side of the image
13338 static void XTranslateImage(Display *display,XWindows *windows,
13339 Image *image,const KeySym key_symbol)
13342 text[MaxTextExtent];
13353 User specified a pan position offset.
13355 x_offset=windows->image.width;
13356 y_offset=windows->image.height;
13357 if (image->montage != (char *) NULL)
13358 (void) XParseGeometry(image->montage,&x,&y,&x_offset,&y_offset);
13359 switch ((int) key_symbol)
13364 windows->image.x=(int) windows->image.width/2;
13365 windows->image.y=(int) windows->image.height/2;
13371 windows->image.x-=x_offset;
13378 windows->image.y-=y_offset;
13384 windows->image.x+=x_offset;
13391 windows->image.y+=y_offset;
13398 Check boundary conditions.
13400 if (windows->image.x < 0)
13401 windows->image.x=0;
13403 if ((int) (windows->image.x+windows->image.width) >
13404 windows->image.ximage->width)
13405 windows->image.x=(int) windows->image.ximage->width-windows->image.width;
13406 if (windows->image.y < 0)
13407 windows->image.y=0;
13409 if ((int) (windows->image.y+windows->image.height) >
13410 windows->image.ximage->height)
13411 windows->image.y=(int) windows->image.ximage->height-windows->image.height;
13413 Refresh Image window.
13415 (void) FormatLocaleString(text,MaxTextExtent," %ux%u%+d%+d ",
13416 windows->image.width,windows->image.height,windows->image.x,
13418 XInfoWidget(display,windows,text);
13419 XCheckRefreshWindows(display,windows);
13420 XDrawPanRectangle(display,windows);
13421 XRefreshWindow(display,&windows->image,(XEvent *) NULL);
13422 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
13426 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13430 + X T r i m I m a g e %
13434 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13436 % XTrimImage() trims the edges from the Image window.
13438 % The format of the XTrimImage method is:
13440 % MagickBooleanType XTrimImage(Display *display,
13441 % XResourceInfo *resource_info,XWindows *windows,Image *image,
13442 % ExceptionInfo *exception)
13444 % A description of each parameter follows:
13446 % o display: Specifies a connection to an X server; returned from
13449 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
13451 % o windows: Specifies a pointer to a XWindows structure.
13453 % o image: the image.
13455 % o exception: return any errors or warnings in this structure.
13458 static MagickBooleanType XTrimImage(Display *display,
13459 XResourceInfo *resource_info,XWindows *windows,Image *image,
13460 ExceptionInfo *exception)
13474 Trim edges from image.
13476 XSetCursorState(display,windows,MagickTrue);
13477 XCheckRefreshWindows(display,windows);
13479 Crop the left edge.
13481 background=XGetPixel(windows->image.ximage,0,0);
13482 trim_info.width=(size_t) windows->image.ximage->width;
13483 for (x=0; x < windows->image.ximage->width; x++)
13485 for (y=0; y < windows->image.ximage->height; y++)
13487 pixel=XGetPixel(windows->image.ximage,x,y);
13488 if (pixel != background)
13491 if (y < windows->image.ximage->height)
13494 trim_info.x=(ssize_t) x;
13495 if (trim_info.x == (ssize_t) windows->image.ximage->width)
13497 XSetCursorState(display,windows,MagickFalse);
13498 return(MagickFalse);
13501 Crop the right edge.
13503 background=XGetPixel(windows->image.ximage,windows->image.ximage->width-1,0);
13504 for (x=windows->image.ximage->width-1; x != 0; x--)
13506 for (y=0; y < windows->image.ximage->height; y++)
13508 pixel=XGetPixel(windows->image.ximage,x,y);
13509 if (pixel != background)
13512 if (y < windows->image.ximage->height)
13515 trim_info.width=(size_t) (x-trim_info.x+1);
13519 background=XGetPixel(windows->image.ximage,0,0);
13520 trim_info.height=(size_t) windows->image.ximage->height;
13521 for (y=0; y < windows->image.ximage->height; y++)
13523 for (x=0; x < windows->image.ximage->width; x++)
13525 pixel=XGetPixel(windows->image.ximage,x,y);
13526 if (pixel != background)
13529 if (x < windows->image.ximage->width)
13532 trim_info.y=(ssize_t) y;
13534 Crop the bottom edge.
13536 background=XGetPixel(windows->image.ximage,0,windows->image.ximage->height-1);
13537 for (y=windows->image.ximage->height-1; y != 0; y--)
13539 for (x=0; x < windows->image.ximage->width; x++)
13541 pixel=XGetPixel(windows->image.ximage,x,y);
13542 if (pixel != background)
13545 if (x < windows->image.ximage->width)
13548 trim_info.height=(size_t) y-trim_info.y+1;
13549 if (((unsigned int) trim_info.width != windows->image.width) ||
13550 ((unsigned int) trim_info.height != windows->image.height))
13553 Reconfigure Image window as defined by the trimming rectangle.
13555 XSetCropGeometry(display,windows,&trim_info,image);
13556 windows->image.window_changes.width=(int) trim_info.width;
13557 windows->image.window_changes.height=(int) trim_info.height;
13558 (void) XConfigureImage(display,resource_info,windows,image,exception);
13560 XSetCursorState(display,windows,MagickFalse);
13561 return(MagickTrue);
13565 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13569 + X V i s u a l D i r e c t o r y I m a g e %
13573 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13575 % XVisualDirectoryImage() creates a Visual Image Directory.
13577 % The format of the XVisualDirectoryImage method is:
13579 % Image *XVisualDirectoryImage(Display *display,
13580 % XResourceInfo *resource_info,XWindows *windows,
13581 % ExceptionInfo *exception)
13583 % A description of each parameter follows:
13585 % o display: Specifies a connection to an X server; returned from
13588 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
13590 % o windows: Specifies a pointer to a XWindows structure.
13592 % o exception: return any errors or warnings in this structure.
13595 static Image *XVisualDirectoryImage(Display *display,
13596 XResourceInfo *resource_info,XWindows *windows,ExceptionInfo *exception)
13598 #define TileImageTag "Scale/Image"
13599 #define XClientName "montage"
13632 filename[MaxTextExtent] = "\0",
13633 filenames[MaxTextExtent] = "*";
13636 background_resources;
13639 Request file name from user.
13641 XFileBrowserWidget(display,windows,"Directory",filenames);
13642 if (*filenames == '\0')
13643 return((Image *) NULL);
13645 Expand the filenames.
13647 filelist=(char **) AcquireMagickMemory(sizeof(*filelist));
13648 if (filelist == (char **) NULL)
13650 ThrowXWindowFatalException(ResourceLimitError,"MemoryAllocationFailed",
13652 return((Image *) NULL);
13655 filelist[0]=filenames;
13656 status=ExpandFilenames(&number_files,&filelist);
13657 if( IfMagickFalse(status) || (number_files == 0))
13659 if (number_files == 0)
13660 ThrowXWindowFatalException(ImageError,"NoImagesWereFound",filenames)
13662 ThrowXWindowFatalException(ResourceLimitError,"MemoryAllocationFailed",
13664 return((Image *) NULL);
13667 Set image background resources.
13669 background_resources=(*resource_info);
13670 background_resources.window_id=AcquireString("");
13671 (void) FormatLocaleString(background_resources.window_id,MaxTextExtent,
13672 "0x%lx",windows->image.id);
13673 background_resources.backdrop=MagickTrue;
13675 Read each image and convert them to a tile.
13677 backdrop=IsMagickTrue( (windows->visual_info->klass == TrueColor) ||
13678 (windows->visual_info->klass == DirectColor) );
13679 read_info=CloneImageInfo(resource_info->image_info);
13680 (void) SetImageOption(read_info,"jpeg:size","120x120");
13681 (void) CloneString(&read_info->size,DefaultTileGeometry);
13682 (void) SetImageInfoProgressMonitor(read_info,(MagickProgressMonitor) NULL,
13684 images=NewImageList();
13685 XSetCursorState(display,windows,MagickTrue);
13686 XCheckRefreshWindows(display,windows);
13687 for (i=0; i < (int) number_files; i++)
13689 (void) CopyMagickString(read_info->filename,filelist[i],MaxTextExtent);
13690 filelist[i]=DestroyString(filelist[i]);
13691 *read_info->magick='\0';
13692 next_image=ReadImage(read_info,exception);
13693 CatchException(exception);
13694 if (next_image != (Image *) NULL)
13696 (void) DeleteImageProperty(next_image,"label");
13697 (void) SetImageProperty(next_image,"label",InterpretImageProperties(
13698 read_info,next_image,DefaultTileLabel,exception),exception);
13699 (void) ParseRegionGeometry(next_image,read_info->size,&geometry,
13701 thumbnail_image=ThumbnailImage(next_image,geometry.width,
13702 geometry.height,exception);
13703 if (thumbnail_image != (Image *) NULL)
13705 next_image=DestroyImage(next_image);
13706 next_image=thumbnail_image;
13710 (void) XDisplayBackgroundImage(display,&background_resources,
13711 next_image,exception);
13712 XSetCursorState(display,windows,MagickTrue);
13714 AppendImageToList(&images,next_image);
13715 if (images->progress_monitor != (MagickProgressMonitor) NULL)
13720 proceed=SetImageProgress(images,LoadImageTag,(MagickOffsetType) i,
13721 (MagickSizeType) number_files);
13722 if( IfMagickFalse(proceed) )
13727 filelist=(char **) RelinquishMagickMemory(filelist);
13728 if (images == (Image *) NULL)
13730 read_info=DestroyImageInfo(read_info);
13731 XSetCursorState(display,windows,MagickFalse);
13732 ThrowXWindowFatalException(ImageError,"NoImagesWereLoaded",filenames);
13733 return((Image *) NULL);
13736 Create the Visual Image Directory.
13738 montage_info=CloneMontageInfo(read_info,(MontageInfo *) NULL);
13739 montage_info->pointsize=10;
13740 if (resource_info->font != (char *) NULL)
13741 (void) CloneString(&montage_info->font,resource_info->font);
13742 (void) CopyMagickString(montage_info->filename,filename,MaxTextExtent);
13743 montage_image=MontageImageList(read_info,montage_info,GetFirstImageInList(
13744 images),exception);
13745 images=DestroyImageList(images);
13746 montage_info=DestroyMontageInfo(montage_info);
13747 read_info=DestroyImageInfo(read_info);
13748 XSetCursorState(display,windows,MagickFalse);
13749 if (montage_image == (Image *) NULL)
13750 return(montage_image);
13751 XClientMessage(display,windows->image.id,windows->im_protocols,
13752 windows->im_next_image,CurrentTime);
13753 return(montage_image);
13757 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13761 % X D i s p l a y B a c k g r o u n d I m a g e %
13765 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13767 % XDisplayBackgroundImage() displays an image in the background of a window.
13769 % The format of the XDisplayBackgroundImage method is:
13771 % MagickBooleanType XDisplayBackgroundImage(Display *display,
13772 % XResourceInfo *resource_info,Image *image,ExceptionInfo *exception)
13774 % A description of each parameter follows:
13776 % o display: Specifies a connection to an X server; returned from
13779 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
13781 % o image: the image.
13783 % o exception: return any errors or warnings in this structure.
13786 MagickExport MagickBooleanType XDisplayBackgroundImage(Display *display,
13787 XResourceInfo *resource_info,Image *image,ExceptionInfo *exception)
13790 geometry[MaxTextExtent],
13791 visual_type[MaxTextExtent];
13804 static XStandardColormap
13808 *visual_info = (XVisualInfo *) NULL;
13829 Determine target window.
13831 assert(image != (Image *) NULL);
13832 assert(image->signature == MagickSignature);
13833 if( IfMagickTrue(image->debug) )
13834 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
13835 resources=(*resource_info);
13836 window_info.id=(Window) NULL;
13837 root_window=XRootWindow(display,XDefaultScreen(display));
13838 if (LocaleCompare(resources.window_id,"root") == 0)
13839 window_info.id=root_window;
13842 if (isdigit((unsigned char) *resources.window_id) != 0)
13843 window_info.id=XWindowByID(display,root_window,
13844 (Window) strtol((char *) resources.window_id,(char **) NULL,0));
13845 if (window_info.id == (Window) NULL)
13846 window_info.id=XWindowByName(display,root_window,resources.window_id);
13848 if (window_info.id == (Window) NULL)
13850 ThrowXWindowFatalException(XServerError,"NoWindowWithSpecifiedIDExists",
13851 resources.window_id);
13852 return(MagickFalse);
13855 Determine window visual id.
13857 window_attributes.width=XDisplayWidth(display,XDefaultScreen(display));
13858 window_attributes.height=XDisplayHeight(display,XDefaultScreen(display));
13859 (void) CopyMagickString(visual_type,"default",MaxTextExtent);
13860 status=XGetWindowAttributes(display,window_info.id,&window_attributes);
13862 (void) FormatLocaleString(visual_type,MaxTextExtent,"0x%lx",
13863 XVisualIDFromVisual(window_attributes.visual));
13864 if (visual_info == (XVisualInfo *) NULL)
13867 Allocate standard colormap.
13869 map_info=XAllocStandardColormap();
13870 if (map_info == (XStandardColormap *) NULL)
13871 ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
13873 map_info->colormap=(Colormap) NULL;
13874 pixel.pixels=(unsigned long *) NULL;
13876 Initialize visual info.
13878 resources.map_type=(char *) NULL;
13879 resources.visual_type=visual_type;
13880 visual_info=XBestVisualInfo(display,map_info,&resources);
13881 if (visual_info == (XVisualInfo *) NULL)
13882 ThrowXWindowFatalException(XServerFatalError,"UnableToGetVisual",
13883 resources.visual_type);
13885 Initialize window info.
13887 window_info.ximage=(XImage *) NULL;
13888 window_info.matte_image=(XImage *) NULL;
13889 window_info.pixmap=(Pixmap) NULL;
13890 window_info.matte_pixmap=(Pixmap) NULL;
13893 Free previous root colors.
13895 if (window_info.id == root_window)
13896 (void) XDestroyWindowColors(display,root_window);
13898 Initialize Standard Colormap.
13900 resources.colormap=SharedColormap;
13901 XMakeStandardColormap(display,visual_info,&resources,image,map_info,&pixel,
13904 Graphic context superclass.
13906 context_values.background=pixel.background_color.pixel;
13907 context_values.foreground=pixel.foreground_color.pixel;
13908 pixel.annotate_context=XCreateGC(display,window_info.id,
13909 (size_t) (GCBackground | GCForeground),&context_values);
13910 if (pixel.annotate_context == (GC) NULL)
13911 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
13914 Initialize Image window attributes.
13916 window_info.name=AcquireString("\0");
13917 window_info.icon_name=AcquireString("\0");
13918 XGetWindowInfo(display,visual_info,map_info,&pixel,(XFontStruct *) NULL,
13919 &resources,&window_info);
13921 Create the X image.
13923 window_info.width=(unsigned int) image->columns;
13924 window_info.height=(unsigned int) image->rows;
13925 if ((image->columns != window_info.width) ||
13926 (image->rows != window_info.height))
13927 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
13929 (void) FormatLocaleString(geometry,MaxTextExtent,"%ux%u+0+0>",
13930 window_attributes.width,window_attributes.height);
13931 geometry_info.width=window_info.width;
13932 geometry_info.height=window_info.height;
13933 geometry_info.x=(ssize_t) window_info.x;
13934 geometry_info.y=(ssize_t) window_info.y;
13935 (void) ParseMetaGeometry(geometry,&geometry_info.x,&geometry_info.y,
13936 &geometry_info.width,&geometry_info.height);
13937 window_info.width=(unsigned int) geometry_info.width;
13938 window_info.height=(unsigned int) geometry_info.height;
13939 window_info.x=(int) geometry_info.x;
13940 window_info.y=(int) geometry_info.y;
13941 status=XMakeImage(display,&resources,&window_info,image,window_info.width,
13942 window_info.height,exception);
13943 if( IfMagickFalse(status) )
13944 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
13948 if( IfMagickTrue(image->debug) )
13950 (void) LogMagickEvent(X11Event,GetMagickModule(),
13951 "Image: %s[%.20g] %.20gx%.20g ",image->filename,(double) image->scene,
13952 (double) image->columns,(double) image->rows);
13953 if (image->colors != 0)
13954 (void) LogMagickEvent(X11Event,GetMagickModule(),"%.20gc ",(double)
13956 (void) LogMagickEvent(X11Event,GetMagickModule(),"%s",image->magick);
13959 Adjust image dimensions as specified by backdrop or geometry options.
13961 width=(int) window_info.width;
13962 height=(int) window_info.height;
13963 if( IfMagickTrue(resources.backdrop) )
13966 Center image on window.
13968 window_info.x=(window_attributes.width/2)-
13969 (window_info.ximage->width/2);
13970 window_info.y=(window_attributes.height/2)-
13971 (window_info.ximage->height/2);
13972 width=window_attributes.width;
13973 height=window_attributes.height;
13975 if ((resources.image_geometry != (char *) NULL) &&
13976 (*resources.image_geometry != '\0'))
13979 default_geometry[MaxTextExtent];
13989 User specified geometry.
13991 size_hints=XAllocSizeHints();
13992 if (size_hints == (XSizeHints *) NULL)
13993 ThrowXWindowFatalException(ResourceLimitFatalError,
13994 "MemoryAllocationFailed",image->filename);
13995 size_hints->flags=0L;
13996 (void) FormatLocaleString(default_geometry,MaxTextExtent,"%dx%d",
13998 flags=XWMGeometry(display,visual_info->screen,resources.image_geometry,
13999 default_geometry,window_info.border_width,size_hints,&window_info.x,
14000 &window_info.y,&width,&height,&gravity);
14001 if (flags & (XValue | YValue))
14003 width=window_attributes.width;
14004 height=window_attributes.height;
14006 (void) XFree((void *) size_hints);
14009 Create the X pixmap.
14011 window_info.pixmap=XCreatePixmap(display,window_info.id,(unsigned int) width,
14012 (unsigned int) height,window_info.depth);
14013 if (window_info.pixmap == (Pixmap) NULL)
14014 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXPixmap",
14017 Display pixmap on the window.
14019 if (((unsigned int) width > window_info.width) ||
14020 ((unsigned int) height > window_info.height))
14021 (void) XFillRectangle(display,window_info.pixmap,
14022 window_info.annotate_context,0,0,(unsigned int) width,
14023 (unsigned int) height);
14024 (void) XPutImage(display,window_info.pixmap,window_info.annotate_context,
14025 window_info.ximage,0,0,window_info.x,window_info.y,(unsigned int)
14026 window_info.width,(unsigned int) window_info.height);
14027 (void) XSetWindowBackgroundPixmap(display,window_info.id,window_info.pixmap);
14028 (void) XClearWindow(display,window_info.id);
14029 delay=1000*image->delay/MagickMax(image->ticks_per_second,1L);
14030 XDelay(display,delay == 0UL ? 10UL : delay);
14031 (void) XSync(display,MagickFalse);
14032 return(IsMagickTrue(window_info.id == root_window));
14036 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
14040 + X D i s p l a y I m a g e %
14044 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
14046 % XDisplayImage() displays an image via X11. A new image is created and
14047 % returned if the user interactively transforms the displayed image.
14049 % The format of the XDisplayImage method is:
14051 % Image *XDisplayImage(Display *display,XResourceInfo *resource_info,
14052 % char **argv,int argc,Image **image,size_t *state,
14053 % ExceptionInfo *exception)
14055 % A description of each parameter follows:
14057 % o nexus: Method XDisplayImage returns an image when the
14058 % user chooses 'Open Image' from the command menu or picks a tile
14059 % from the image directory. Otherwise a null image is returned.
14061 % o display: Specifies a connection to an X server; returned from
14064 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
14066 % o argv: Specifies the application's argument list.
14068 % o argc: Specifies the number of arguments.
14070 % o image: Specifies an address to an address of an Image structure;
14072 % o exception: return any errors or warnings in this structure.
14075 MagickExport Image *XDisplayImage(Display *display,XResourceInfo *resource_info,
14076 char **argv,int argc,Image **image,size_t *state,ExceptionInfo *exception)
14078 #define MagnifySize 256 /* must be a power of 2 */
14079 #define MagickMenus 10
14080 #define MagickTitle "Commands"
14107 "Visual Directory...",
14153 "Contrast Stretch...",
14154 "Sigmoidal Contrast...",
14188 "Charcoal Draw...",
14202 "Region of Interest...",
14205 *MiscellanyMenu[] =
14220 "Browse Documentation",
14247 **Menus[MagickMenus] =
14285 VisualDirectoryCommand,
14299 OriginalSizeCommand,
14306 TransformCommands[] =
14312 RotateRightCommand,
14319 EnhanceCommands[] =
14327 ContrastStretchCommand,
14328 SigmoidalContrastCommand,
14336 EffectsCommands[] =
14340 ReduceNoiseCommand,
14360 CharcoalDrawCommand
14362 ImageEditCommands[] =
14373 RegionofInterestCommand
14375 MiscellanyCommands[] =
14379 ShowPreviewCommand,
14380 ShowHistogramCommand,
14389 BrowseDocumentationCommand,
14392 ShortCutsCommands[] =
14404 VirtualCommands[] =
14413 *Commands[MagickMenus] =
14423 MiscellanyCommands,
14428 command[MaxTextExtent],
14430 geometry[MaxTextExtent],
14431 resource_name[MaxTextExtent];
14458 working_directory[MaxTextExtent];
14464 *magick_windows[MaxXWindows];
14466 static unsigned int
14526 assert(image != (Image **) NULL);
14527 assert((*image)->signature == MagickSignature);
14528 if( IfMagickTrue((*image)->debug) )
14529 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",(*image)->filename);
14530 display_image=(*image);
14531 warning_handler=(WarningHandler) NULL;
14532 windows=XSetWindows((XWindows *) ~0);
14533 if (windows != (XWindows *) NULL)
14538 if (*working_directory == '\0')
14539 (void) CopyMagickString(working_directory,".",MaxTextExtent);
14540 status=chdir(working_directory);
14542 (void) ThrowMagickException(exception,GetMagickModule(),FileOpenError,
14543 "UnableToOpenFile","%s",working_directory);
14544 warning_handler=resource_info->display_warnings ?
14545 SetErrorHandler(XWarning) : SetErrorHandler((ErrorHandler) NULL);
14546 warning_handler=resource_info->display_warnings ?
14547 SetWarningHandler(XWarning) : SetWarningHandler((WarningHandler) NULL);
14552 Allocate windows structure.
14554 resource_info->colors=display_image->colors;
14555 windows=XSetWindows(XInitializeWindows(display,resource_info));
14556 if (windows == (XWindows *) NULL)
14557 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateWindow",
14558 (*image)->filename);
14560 Initialize window id's.
14563 magick_windows[number_windows++]=(&windows->icon);
14564 magick_windows[number_windows++]=(&windows->backdrop);
14565 magick_windows[number_windows++]=(&windows->image);
14566 magick_windows[number_windows++]=(&windows->info);
14567 magick_windows[number_windows++]=(&windows->command);
14568 magick_windows[number_windows++]=(&windows->widget);
14569 magick_windows[number_windows++]=(&windows->popup);
14570 magick_windows[number_windows++]=(&windows->magnify);
14571 magick_windows[number_windows++]=(&windows->pan);
14572 for (i=0; i < (int) number_windows; i++)
14573 magick_windows[i]->id=(Window) NULL;
14578 Initialize font info.
14580 if (windows->font_info != (XFontStruct *) NULL)
14581 (void) XFreeFont(display,windows->font_info);
14582 windows->font_info=XBestFont(display,resource_info,MagickFalse);
14583 if (windows->font_info == (XFontStruct *) NULL)
14584 ThrowXWindowFatalException(XServerFatalError,"UnableToLoadFont",
14585 resource_info->font);
14587 Initialize Standard Colormap.
14589 map_info=windows->map_info;
14590 icon_map=windows->icon_map;
14591 visual_info=windows->visual_info;
14592 icon_visual=windows->icon_visual;
14593 pixel=windows->pixel_info;
14594 icon_pixel=windows->icon_pixel;
14595 font_info=windows->font_info;
14596 icon_resources=windows->icon_resources;
14597 class_hints=windows->class_hints;
14598 manager_hints=windows->manager_hints;
14599 root_window=XRootWindow(display,visual_info->screen);
14600 nexus=NewImageList();
14601 if( IfMagickTrue(display_image->debug) )
14603 (void) LogMagickEvent(X11Event,GetMagickModule(),
14604 "Image: %s[%.20g] %.20gx%.20g ",display_image->filename,
14605 (double) display_image->scene,(double) display_image->columns,
14606 (double) display_image->rows);
14607 if (display_image->colors != 0)
14608 (void) LogMagickEvent(X11Event,GetMagickModule(),"%.20gc ",(double)
14609 display_image->colors);
14610 (void) LogMagickEvent(X11Event,GetMagickModule(),"%s",
14611 display_image->magick);
14613 XMakeStandardColormap(display,visual_info,resource_info,display_image,
14614 map_info,pixel,exception);
14615 display_image->taint=MagickFalse;
14617 Initialize graphic context.
14619 windows->context.id=(Window) NULL;
14620 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
14621 resource_info,&windows->context);
14622 (void) CloneString(&class_hints->res_name,resource_info->client_name);
14623 (void) CloneString(&class_hints->res_class,resource_info->client_name);
14624 class_hints->res_class[0]=(char) toupper((int) class_hints->res_class[0]);
14625 manager_hints->flags=InputHint | StateHint;
14626 manager_hints->input=MagickFalse;
14627 manager_hints->initial_state=WithdrawnState;
14628 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14629 &windows->context);
14630 if( IfMagickTrue(display_image->debug) )
14631 (void) LogMagickEvent(X11Event,GetMagickModule(),
14632 "Window id: 0x%lx (context)",windows->context.id);
14633 context_values.background=pixel->background_color.pixel;
14634 context_values.font=font_info->fid;
14635 context_values.foreground=pixel->foreground_color.pixel;
14636 context_values.graphics_exposures=MagickFalse;
14637 context_mask=(MagickStatusType)
14638 (GCBackground | GCFont | GCForeground | GCGraphicsExposures);
14639 if (pixel->annotate_context != (GC) NULL)
14640 (void) XFreeGC(display,pixel->annotate_context);
14641 pixel->annotate_context=XCreateGC(display,windows->context.id,
14642 context_mask,&context_values);
14643 if (pixel->annotate_context == (GC) NULL)
14644 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
14645 display_image->filename);
14646 context_values.background=pixel->depth_color.pixel;
14647 if (pixel->widget_context != (GC) NULL)
14648 (void) XFreeGC(display,pixel->widget_context);
14649 pixel->widget_context=XCreateGC(display,windows->context.id,context_mask,
14651 if (pixel->widget_context == (GC) NULL)
14652 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
14653 display_image->filename);
14654 context_values.background=pixel->foreground_color.pixel;
14655 context_values.foreground=pixel->background_color.pixel;
14656 context_values.plane_mask=context_values.background ^
14657 context_values.foreground;
14658 if (pixel->highlight_context != (GC) NULL)
14659 (void) XFreeGC(display,pixel->highlight_context);
14660 pixel->highlight_context=XCreateGC(display,windows->context.id,
14661 (size_t) (context_mask | GCPlaneMask),&context_values);
14662 if (pixel->highlight_context == (GC) NULL)
14663 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
14664 display_image->filename);
14665 (void) XDestroyWindow(display,windows->context.id);
14667 Initialize icon window.
14669 XGetWindowInfo(display,icon_visual,icon_map,icon_pixel,(XFontStruct *) NULL,
14670 icon_resources,&windows->icon);
14671 windows->icon.geometry=resource_info->icon_geometry;
14672 XBestIconSize(display,&windows->icon,display_image);
14673 windows->icon.attributes.colormap=XDefaultColormap(display,
14674 icon_visual->screen);
14675 windows->icon.attributes.event_mask=ExposureMask | StructureNotifyMask;
14676 manager_hints->flags=InputHint | StateHint;
14677 manager_hints->input=MagickFalse;
14678 manager_hints->initial_state=IconicState;
14679 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14681 if( IfMagickTrue(display_image->debug) )
14682 (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (icon)",
14685 Initialize graphic context for icon window.
14687 if (icon_pixel->annotate_context != (GC) NULL)
14688 (void) XFreeGC(display,icon_pixel->annotate_context);
14689 context_values.background=icon_pixel->background_color.pixel;
14690 context_values.foreground=icon_pixel->foreground_color.pixel;
14691 icon_pixel->annotate_context=XCreateGC(display,windows->icon.id,
14692 (size_t) (GCBackground | GCForeground),&context_values);
14693 if (icon_pixel->annotate_context == (GC) NULL)
14694 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
14695 display_image->filename);
14696 windows->icon.annotate_context=icon_pixel->annotate_context;
14698 Initialize Image window.
14700 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,resource_info,
14702 windows->image.shape=MagickTrue; /* non-rectangular shape hint */
14703 if( IfMagickFalse(resource_info->use_shared_memory) )
14704 windows->image.shared_memory=MagickFalse;
14705 if ((resource_info->title != (char *) NULL) && !(*state & MontageImageState))
14710 title=InterpretImageProperties(resource_info->image_info,display_image,
14711 resource_info->title,exception);
14712 (void) CopyMagickString(windows->image.name,title,MaxTextExtent);
14713 (void) CopyMagickString(windows->image.icon_name,title,MaxTextExtent);
14714 title=DestroyString(title);
14719 filename[MaxTextExtent];
14722 Window name is the base of the filename.
14724 GetPathComponent(display_image->magick_filename,TailPath,filename);
14725 if (display_image->scene == 0)
14726 (void) FormatLocaleString(windows->image.name,MaxTextExtent,
14727 "%s: %s",MagickPackageName,filename);
14729 (void) FormatLocaleString(windows->image.name,MaxTextExtent,
14730 "%s: %s[scene: %.20g frames: %.20g]",MagickPackageName,filename,
14731 (double) display_image->scene,(double) GetImageListLength(
14733 (void) CopyMagickString(windows->image.icon_name,filename,MaxTextExtent);
14735 if (resource_info->immutable)
14736 windows->image.immutable=MagickTrue;
14737 windows->image.use_pixmap=resource_info->use_pixmap;
14738 windows->image.geometry=resource_info->image_geometry;
14739 (void) FormatLocaleString(geometry,MaxTextExtent,"%ux%u+0+0>!",
14740 XDisplayWidth(display,visual_info->screen),
14741 XDisplayHeight(display,visual_info->screen));
14742 geometry_info.width=display_image->columns;
14743 geometry_info.height=display_image->rows;
14746 (void) ParseMetaGeometry(geometry,&geometry_info.x,&geometry_info.y,
14747 &geometry_info.width,&geometry_info.height);
14748 windows->image.width=(unsigned int) geometry_info.width;
14749 windows->image.height=(unsigned int) geometry_info.height;
14750 windows->image.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
14751 ButtonReleaseMask | EnterWindowMask | ExposureMask | KeyPressMask |
14752 KeyReleaseMask | LeaveWindowMask | OwnerGrabButtonMask |
14753 PropertyChangeMask | StructureNotifyMask | SubstructureNotifyMask;
14754 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
14755 resource_info,&windows->backdrop);
14756 if ((resource_info->backdrop) || (windows->backdrop.id != (Window) NULL))
14759 Initialize backdrop window.
14761 windows->backdrop.x=0;
14762 windows->backdrop.y=0;
14763 (void) CloneString(&windows->backdrop.name,"Backdrop");
14764 windows->backdrop.flags=(size_t) (USSize | USPosition);
14765 windows->backdrop.width=(unsigned int)
14766 XDisplayWidth(display,visual_info->screen);
14767 windows->backdrop.height=(unsigned int)
14768 XDisplayHeight(display,visual_info->screen);
14769 windows->backdrop.border_width=0;
14770 windows->backdrop.immutable=MagickTrue;
14771 windows->backdrop.attributes.do_not_propagate_mask=ButtonPressMask |
14773 windows->backdrop.attributes.event_mask=ButtonPressMask | KeyPressMask |
14774 StructureNotifyMask;
14775 manager_hints->flags=IconWindowHint | InputHint | StateHint;
14776 manager_hints->icon_window=windows->icon.id;
14777 manager_hints->input=MagickTrue;
14778 manager_hints->initial_state=resource_info->iconic ? IconicState :
14780 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14781 &windows->backdrop);
14782 if( IfMagickTrue(display_image->debug) )
14783 (void) LogMagickEvent(X11Event,GetMagickModule(),
14784 "Window id: 0x%lx (backdrop)",windows->backdrop.id);
14785 (void) XMapWindow(display,windows->backdrop.id);
14786 (void) XClearWindow(display,windows->backdrop.id);
14787 if (windows->image.id != (Window) NULL)
14789 (void) XDestroyWindow(display,windows->image.id);
14790 windows->image.id=(Window) NULL;
14793 Position image in the center the backdrop.
14795 windows->image.flags|=USPosition;
14796 windows->image.x=(XDisplayWidth(display,visual_info->screen)/2)-
14797 (windows->image.width/2);
14798 windows->image.y=(XDisplayHeight(display,visual_info->screen)/2)-
14799 (windows->image.height/2);
14801 manager_hints->flags=IconWindowHint | InputHint | StateHint;
14802 manager_hints->icon_window=windows->icon.id;
14803 manager_hints->input=MagickTrue;
14804 manager_hints->initial_state=resource_info->iconic ? IconicState :
14806 if (windows->group_leader.id != (Window) NULL)
14811 manager_hints->flags|=WindowGroupHint;
14812 manager_hints->window_group=windows->group_leader.id;
14813 (void) XSelectInput(display,windows->group_leader.id,StructureNotifyMask);
14814 if( IfMagickTrue(display_image->debug) )
14815 (void) LogMagickEvent(X11Event,GetMagickModule(),
14816 "Window id: 0x%lx (group leader)",windows->group_leader.id);
14818 XMakeWindow(display,
14819 (Window) (resource_info->backdrop ? windows->backdrop.id : root_window),
14820 argv,argc,class_hints,manager_hints,&windows->image);
14821 (void) XChangeProperty(display,windows->image.id,windows->im_protocols,
14822 XA_STRING,8,PropModeReplace,(unsigned char *) NULL,0);
14823 if (windows->group_leader.id != (Window) NULL)
14824 (void) XSetTransientForHint(display,windows->image.id,
14825 windows->group_leader.id);
14826 if( IfMagickTrue(display_image->debug) )
14827 (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (image)",
14828 windows->image.id);
14830 Initialize Info widget.
14832 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,resource_info,
14834 (void) CloneString(&windows->info.name,"Info");
14835 (void) CloneString(&windows->info.icon_name,"Info");
14836 windows->info.border_width=1;
14839 windows->info.flags|=PPosition;
14840 windows->info.attributes.win_gravity=UnmapGravity;
14841 windows->info.attributes.event_mask=ButtonPressMask | ExposureMask |
14842 StructureNotifyMask;
14843 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
14844 manager_hints->input=MagickFalse;
14845 manager_hints->initial_state=NormalState;
14846 manager_hints->window_group=windows->image.id;
14847 XMakeWindow(display,windows->image.id,argv,argc,class_hints,manager_hints,
14849 windows->info.highlight_stipple=XCreateBitmapFromData(display,
14850 windows->info.id,(char *) HighlightBitmap,HighlightWidth,HighlightHeight);
14851 windows->info.shadow_stipple=XCreateBitmapFromData(display,
14852 windows->info.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
14853 (void) XSetTransientForHint(display,windows->info.id,windows->image.id);
14854 if( IfMagickTrue(windows->image.mapped) )
14855 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
14856 if( IfMagickTrue(display_image->debug) )
14857 (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (info)",
14860 Initialize Command widget.
14862 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
14863 resource_info,&windows->command);
14864 windows->command.data=MagickMenus;
14865 (void) XCommandWidget(display,windows,CommandMenu,(XEvent *) NULL);
14866 (void) FormatLocaleString(resource_name,MaxTextExtent,"%s.command",
14867 resource_info->client_name);
14868 windows->command.geometry=XGetResourceClass(resource_info->resource_database,
14869 resource_name,"geometry",(char *) NULL);
14870 (void) CloneString(&windows->command.name,MagickTitle);
14871 windows->command.border_width=0;
14872 windows->command.flags|=PPosition;
14873 windows->command.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
14874 ButtonReleaseMask | EnterWindowMask | ExposureMask | LeaveWindowMask |
14875 OwnerGrabButtonMask | StructureNotifyMask;
14876 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
14877 manager_hints->input=MagickTrue;
14878 manager_hints->initial_state=NormalState;
14879 manager_hints->window_group=windows->image.id;
14880 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14881 &windows->command);
14882 windows->command.highlight_stipple=XCreateBitmapFromData(display,
14883 windows->command.id,(char *) HighlightBitmap,HighlightWidth,
14885 windows->command.shadow_stipple=XCreateBitmapFromData(display,
14886 windows->command.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
14887 (void) XSetTransientForHint(display,windows->command.id,windows->image.id);
14888 if( IfMagickTrue(windows->command.mapped) )
14889 (void) XMapRaised(display,windows->command.id);
14890 if( IfMagickTrue(display_image->debug) )
14891 (void) LogMagickEvent(X11Event,GetMagickModule(),
14892 "Window id: 0x%lx (command)",windows->command.id);
14894 Initialize Widget window.
14896 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
14897 resource_info,&windows->widget);
14898 (void) FormatLocaleString(resource_name,MaxTextExtent,"%s.widget",
14899 resource_info->client_name);
14900 windows->widget.geometry=XGetResourceClass(resource_info->resource_database,
14901 resource_name,"geometry",(char *) NULL);
14902 windows->widget.border_width=0;
14903 windows->widget.flags|=PPosition;
14904 windows->widget.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
14905 ButtonReleaseMask | EnterWindowMask | ExposureMask | KeyPressMask |
14906 KeyReleaseMask | LeaveWindowMask | OwnerGrabButtonMask |
14907 StructureNotifyMask;
14908 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
14909 manager_hints->input=MagickTrue;
14910 manager_hints->initial_state=NormalState;
14911 manager_hints->window_group=windows->image.id;
14912 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14914 windows->widget.highlight_stipple=XCreateBitmapFromData(display,
14915 windows->widget.id,(char *) HighlightBitmap,HighlightWidth,HighlightHeight);
14916 windows->widget.shadow_stipple=XCreateBitmapFromData(display,
14917 windows->widget.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
14918 (void) XSetTransientForHint(display,windows->widget.id,windows->image.id);
14919 if( IfMagickTrue(display_image->debug) )
14920 (void) LogMagickEvent(X11Event,GetMagickModule(),
14921 "Window id: 0x%lx (widget)",windows->widget.id);
14923 Initialize popup window.
14925 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
14926 resource_info,&windows->popup);
14927 windows->popup.border_width=0;
14928 windows->popup.flags|=PPosition;
14929 windows->popup.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
14930 ButtonReleaseMask | EnterWindowMask | ExposureMask | KeyPressMask |
14931 KeyReleaseMask | LeaveWindowMask | StructureNotifyMask;
14932 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
14933 manager_hints->input=MagickTrue;
14934 manager_hints->initial_state=NormalState;
14935 manager_hints->window_group=windows->image.id;
14936 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14938 windows->popup.highlight_stipple=XCreateBitmapFromData(display,
14939 windows->popup.id,(char *) HighlightBitmap,HighlightWidth,HighlightHeight);
14940 windows->popup.shadow_stipple=XCreateBitmapFromData(display,
14941 windows->popup.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
14942 (void) XSetTransientForHint(display,windows->popup.id,windows->image.id);
14943 if( IfMagickTrue(display_image->debug) )
14944 (void) LogMagickEvent(X11Event,GetMagickModule(),
14945 "Window id: 0x%lx (pop up)",windows->popup.id);
14947 Initialize Magnify window and cursor.
14949 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
14950 resource_info,&windows->magnify);
14951 if( IfMagickFalse(resource_info->use_shared_memory) )
14952 windows->magnify.shared_memory=MagickFalse;
14953 (void) FormatLocaleString(resource_name,MaxTextExtent,"%s.magnify",
14954 resource_info->client_name);
14955 windows->magnify.geometry=XGetResourceClass(resource_info->resource_database,
14956 resource_name,"geometry",(char *) NULL);
14957 (void) FormatLocaleString(windows->magnify.name,MaxTextExtent,"Magnify %uX",
14958 resource_info->magnify);
14959 if (windows->magnify.cursor != (Cursor) NULL)
14960 (void) XFreeCursor(display,windows->magnify.cursor);
14961 windows->magnify.cursor=XMakeCursor(display,windows->image.id,
14962 map_info->colormap,resource_info->background_color,
14963 resource_info->foreground_color);
14964 if (windows->magnify.cursor == (Cursor) NULL)
14965 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateCursor",
14966 display_image->filename);
14967 windows->magnify.width=MagnifySize;
14968 windows->magnify.height=MagnifySize;
14969 windows->magnify.flags|=PPosition;
14970 windows->magnify.min_width=MagnifySize;
14971 windows->magnify.min_height=MagnifySize;
14972 windows->magnify.width_inc=MagnifySize;
14973 windows->magnify.height_inc=MagnifySize;
14974 windows->magnify.data=resource_info->magnify;
14975 windows->magnify.attributes.cursor=windows->magnify.cursor;
14976 windows->magnify.attributes.event_mask=ButtonPressMask | ButtonReleaseMask |
14977 ExposureMask | KeyPressMask | KeyReleaseMask | OwnerGrabButtonMask |
14978 StructureNotifyMask;
14979 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
14980 manager_hints->input=MagickTrue;
14981 manager_hints->initial_state=NormalState;
14982 manager_hints->window_group=windows->image.id;
14983 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14984 &windows->magnify);
14985 if( IfMagickTrue(display_image->debug) )
14986 (void) LogMagickEvent(X11Event,GetMagickModule(),
14987 "Window id: 0x%lx (magnify)",windows->magnify.id);
14988 (void) XSetTransientForHint(display,windows->magnify.id,windows->image.id);
14990 Initialize panning window.
14992 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
14993 resource_info,&windows->pan);
14994 (void) CloneString(&windows->pan.name,"Pan Icon");
14995 windows->pan.width=windows->icon.width;
14996 windows->pan.height=windows->icon.height;
14997 (void) FormatLocaleString(resource_name,MaxTextExtent,"%s.pan",
14998 resource_info->client_name);
14999 windows->pan.geometry=XGetResourceClass(resource_info->resource_database,
15000 resource_name,"geometry",(char *) NULL);
15001 (void) XParseGeometry(windows->pan.geometry,&windows->pan.x,&windows->pan.y,
15002 &windows->pan.width,&windows->pan.height);
15003 windows->pan.flags|=PPosition;
15004 windows->pan.immutable=MagickTrue;
15005 windows->pan.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
15006 ButtonReleaseMask | ExposureMask | KeyPressMask | KeyReleaseMask |
15007 StructureNotifyMask;
15008 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
15009 manager_hints->input=MagickFalse;
15010 manager_hints->initial_state=NormalState;
15011 manager_hints->window_group=windows->image.id;
15012 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
15014 if( IfMagickTrue(display_image->debug) )
15015 (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (pan)",
15017 (void) XSetTransientForHint(display,windows->pan.id,windows->image.id);
15018 if( IfMagickTrue(windows->info.mapped) )
15019 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
15020 if( IfMagickFalse(windows->image.mapped) ||
15021 (windows->backdrop.id != (Window) NULL))
15022 (void) XMapWindow(display,windows->image.id);
15024 Set our progress monitor and warning handlers.
15026 if (warning_handler == (WarningHandler) NULL)
15028 warning_handler=resource_info->display_warnings ?
15029 SetErrorHandler(XWarning) : SetErrorHandler((ErrorHandler) NULL);
15030 warning_handler=resource_info->display_warnings ?
15031 SetWarningHandler(XWarning) : SetWarningHandler((WarningHandler) NULL);
15034 Initialize Image and Magnify X images.
15036 windows->image.x=0;
15037 windows->image.y=0;
15038 windows->magnify.shape=MagickFalse;
15039 width=(unsigned int) display_image->columns;
15040 height=(unsigned int) display_image->rows;
15041 if ((display_image->columns != width) || (display_image->rows != height))
15042 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
15043 display_image->filename);
15044 status=XMakeImage(display,resource_info,&windows->image,display_image,
15045 width,height,exception);
15046 if( IfMagickFalse(status) )
15047 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
15048 display_image->filename);
15049 status=XMakeImage(display,resource_info,&windows->magnify,(Image *) NULL,
15050 windows->magnify.width,windows->magnify.height,exception);
15051 if( IfMagickFalse(status) )
15052 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
15053 display_image->filename);
15054 if( IfMagickTrue(windows->magnify.mapped) )
15055 (void) XMapRaised(display,windows->magnify.id);
15056 if( IfMagickTrue(windows->pan.mapped) )
15057 (void) XMapRaised(display,windows->pan.id);
15058 windows->image.window_changes.width=(int) display_image->columns;
15059 windows->image.window_changes.height=(int) display_image->rows;
15060 (void) XConfigureImage(display,resource_info,windows,display_image,exception);
15061 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
15062 (void) XSync(display,MagickFalse);
15066 delay=display_image->delay/MagickMax(display_image->ticks_per_second,1L);
15067 timer=time((time_t *) NULL)+(delay == 0 ? 1 : delay)+1;
15069 if( IfMagickTrue(resource_info->update) )
15075 Determine when file data was last modified.
15077 status=GetPathAttributes(display_image->filename,&attributes);
15078 if( IfMagickTrue(status) )
15079 update_time=attributes.st_mtime;
15081 *state&=(~FormerImageState);
15082 *state&=(~MontageImageState);
15083 *state&=(~NextImageState);
15087 Handle a window event.
15089 if( IfMagickTrue(windows->image.mapped) )
15090 if ((display_image->delay != 0) || (resource_info->update != 0))
15092 if (timer < time((time_t *) NULL))
15094 if( IfMagickFalse(resource_info->update) )
15095 *state|=NextImageState | ExitState;
15102 Determine if image file was modified.
15104 status=GetPathAttributes(display_image->filename,&attributes);
15105 if( IfMagickTrue(status) )
15106 if (update_time != attributes.st_mtime)
15111 (void) FormatLocaleString(
15112 resource_info->image_info->filename,MaxTextExtent,
15113 "%s:%s",display_image->magick,
15114 display_image->filename);
15115 nexus=ReadImage(resource_info->image_info,exception);
15116 if (nexus != (Image *) NULL)
15118 nexus=DestroyImage(nexus);
15119 *state|=NextImageState | ExitState;
15122 delay=display_image->delay/MagickMax(
15123 display_image->ticks_per_second,1L);
15124 timer=time((time_t *) NULL)+(delay == 0 ? 1 : delay)+1;
15127 if (XEventsQueued(display,QueuedAfterFlush) == 0)
15130 Do not block if delay > 0.
15132 XDelay(display,SuspendTime << 2);
15136 timestamp=time((time_t *) NULL);
15137 (void) XNextEvent(display,&event);
15138 if( IfMagickFalse(windows->image.stasis) )
15139 windows->image.stasis=IsMagickTrue((time((time_t *) NULL)-timestamp) > 0);
15140 if( IfMagickFalse(windows->magnify.stasis) )
15141 windows->magnify.stasis=IsMagickTrue((time((time_t *) NULL)-timestamp) > 0);
15142 if (event.xany.window == windows->command.id)
15145 Select a command from the Command widget.
15147 id=XCommandWidget(display,windows,CommandMenu,&event);
15150 (void) CopyMagickString(command,CommandMenu[id],MaxTextExtent);
15151 command_type=CommandMenus[id];
15152 if (id < MagickMenus)
15155 Select a command from a pop-up menu.
15157 entry=XMenuWidget(display,windows,CommandMenu[id],Menus[id],
15161 (void) CopyMagickString(command,Menus[id][entry],MaxTextExtent);
15162 command_type=Commands[id][entry];
15164 if (command_type != NullCommand)
15165 nexus=XMagickCommand(display,resource_info,windows,command_type,
15166 &display_image,exception);
15169 switch (event.type)
15173 if( IfMagickTrue(display_image->debug) )
15174 (void) LogMagickEvent(X11Event,GetMagickModule(),
15175 "Button Press: 0x%lx %u +%d+%d",event.xbutton.window,
15176 event.xbutton.button,event.xbutton.x,event.xbutton.y);
15177 if ((event.xbutton.button == Button3) &&
15178 (event.xbutton.state & Mod1Mask))
15181 Convert Alt-Button3 to Button2.
15183 event.xbutton.button=Button2;
15184 event.xbutton.state&=(~Mod1Mask);
15186 if (event.xbutton.window == windows->backdrop.id)
15188 (void) XSetInputFocus(display,event.xbutton.window,RevertToParent,
15189 event.xbutton.time);
15192 if (event.xbutton.window == windows->image.id)
15194 switch (event.xbutton.button)
15198 if (resource_info->immutable)
15201 Select a command from the Virtual menu.
15203 entry=XMenuWidget(display,windows,"Commands",VirtualMenu,
15206 nexus=XMagickCommand(display,resource_info,windows,
15207 VirtualCommands[entry],&display_image,exception);
15211 Map/unmap Command widget.
15213 if( IfMagickTrue(windows->command.mapped) )
15214 (void) XWithdrawWindow(display,windows->command.id,
15215 windows->command.screen);
15218 (void) XCommandWidget(display,windows,CommandMenu,
15220 (void) XMapRaised(display,windows->command.id);
15227 User pressed the image magnify button.
15229 (void) XMagickCommand(display,resource_info,windows,ZoomCommand,
15230 &display_image,exception);
15231 XMagnifyImage(display,windows,&event,exception);
15236 if (resource_info->immutable)
15239 Select a command from the Virtual menu.
15241 entry=XMenuWidget(display,windows,"Commands",VirtualMenu,
15244 nexus=XMagickCommand(display,resource_info,windows,
15245 VirtualCommands[entry],&display_image,exception);
15248 if (display_image->montage != (char *) NULL)
15251 Open or delete a tile from a visual image directory.
15253 nexus=XTileImage(display,resource_info,windows,
15254 display_image,&event,exception);
15255 if (nexus != (Image *) NULL)
15256 *state|=MontageImageState | NextImageState | ExitState;
15257 vid_info.x=(short int) windows->image.x;
15258 vid_info.y=(short int) windows->image.y;
15262 Select a command from the Short Cuts menu.
15264 entry=XMenuWidget(display,windows,"Short Cuts",ShortCutsMenu,
15267 nexus=XMagickCommand(display,resource_info,windows,
15268 ShortCutsCommands[entry],&display_image,exception);
15276 XTranslateImage(display,windows,*image,XK_Up);
15284 XTranslateImage(display,windows,*image,XK_Down);
15292 if (event.xbutton.window == windows->magnify.id)
15312 MagnifyCommands[] =
15325 Select a magnify factor from the pop-up menu.
15327 factor=XMenuWidget(display,windows,"Magnify",MagnifyMenu,command);
15329 XMagnifyWindowCommand(display,windows,0,MagnifyCommands[factor],
15333 if (event.xbutton.window == windows->pan.id)
15335 switch (event.xbutton.button)
15342 XTranslateImage(display,windows,*image,XK_Up);
15350 XTranslateImage(display,windows,*image,XK_Down);
15355 XPanImage(display,windows,&event,exception);
15361 delay=display_image->delay/MagickMax(display_image->ticks_per_second,
15363 timer=time((time_t *) NULL)+(delay == 0 ? 1 : delay)+1;
15366 case ButtonRelease:
15368 if( IfMagickTrue(display_image->debug) )
15369 (void) LogMagickEvent(X11Event,GetMagickModule(),
15370 "Button Release: 0x%lx %u +%d+%d",event.xbutton.window,
15371 event.xbutton.button,event.xbutton.x,event.xbutton.y);
15374 case ClientMessage:
15376 if( IfMagickTrue(display_image->debug) )
15377 (void) LogMagickEvent(X11Event,GetMagickModule(),
15378 "Client Message: 0x%lx 0x%lx %d 0x%lx",event.xclient.window,
15379 event.xclient.message_type,event.xclient.format,(unsigned long)
15380 event.xclient.data.l[0]);
15381 if (event.xclient.message_type == windows->im_protocols)
15383 if (*event.xclient.data.l == (long) windows->im_update_widget)
15385 (void) CloneString(&windows->command.name,MagickTitle);
15386 windows->command.data=MagickMenus;
15387 (void) XCommandWidget(display,windows,CommandMenu,
15391 if (*event.xclient.data.l == (long) windows->im_update_colormap)
15394 Update graphic context and window colormap.
15396 for (i=0; i < (int) number_windows; i++)
15398 if (magick_windows[i]->id == windows->icon.id)
15400 context_values.background=pixel->background_color.pixel;
15401 context_values.foreground=pixel->foreground_color.pixel;
15402 (void) XChangeGC(display,magick_windows[i]->annotate_context,
15403 context_mask,&context_values);
15404 (void) XChangeGC(display,magick_windows[i]->widget_context,
15405 context_mask,&context_values);
15406 context_values.background=pixel->foreground_color.pixel;
15407 context_values.foreground=pixel->background_color.pixel;
15408 context_values.plane_mask=context_values.background ^
15409 context_values.foreground;
15410 (void) XChangeGC(display,magick_windows[i]->highlight_context,
15411 (size_t) (context_mask | GCPlaneMask),
15413 magick_windows[i]->attributes.background_pixel=
15414 pixel->background_color.pixel;
15415 magick_windows[i]->attributes.border_pixel=
15416 pixel->border_color.pixel;
15417 magick_windows[i]->attributes.colormap=map_info->colormap;
15418 (void) XChangeWindowAttributes(display,magick_windows[i]->id,
15419 (unsigned long) magick_windows[i]->mask,
15420 &magick_windows[i]->attributes);
15422 if( IfMagickTrue(windows->pan.mapped) )
15424 (void) XSetWindowBackgroundPixmap(display,windows->pan.id,
15425 windows->pan.pixmap);
15426 (void) XClearWindow(display,windows->pan.id);
15427 XDrawPanRectangle(display,windows);
15429 if (windows->backdrop.id != (Window) NULL)
15430 (void) XInstallColormap(display,map_info->colormap);
15433 if (*event.xclient.data.l == (long) windows->im_former_image)
15435 *state|=FormerImageState | ExitState;
15438 if (*event.xclient.data.l == (long) windows->im_next_image)
15440 *state|=NextImageState | ExitState;
15443 if (*event.xclient.data.l == (long) windows->im_retain_colors)
15445 *state|=RetainColorsState;
15448 if (*event.xclient.data.l == (long) windows->im_exit)
15455 if (event.xclient.message_type == windows->dnd_protocols)
15473 Display image named by the Drag-and-Drop selection.
15475 if ((*event.xclient.data.l != 2) && (*event.xclient.data.l != 128))
15477 selection=XInternAtom(display,"DndSelection",MagickFalse);
15478 status=XGetWindowProperty(display,root_window,selection,0L,(long)
15479 MaxTextExtent,MagickFalse,(Atom) AnyPropertyType,&type,&format,
15480 &length,&after,&data);
15481 if ((status != Success) || (length == 0))
15483 if (*event.xclient.data.l == 2)
15488 (void) CopyMagickString(resource_info->image_info->filename,
15489 (char *) data,MaxTextExtent);
15496 if (strncmp((char *) data, "file:", 5) != 0)
15498 (void) XFree((void *) data);
15501 (void) CopyMagickString(resource_info->image_info->filename,
15502 ((char *) data)+5,MaxTextExtent);
15504 nexus=ReadImage(resource_info->image_info,exception);
15505 CatchException(exception);
15506 if (nexus != (Image *) NULL)
15507 *state|=NextImageState | ExitState;
15508 (void) XFree((void *) data);
15512 If client window delete message, exit.
15514 if (event.xclient.message_type != windows->wm_protocols)
15516 if (*event.xclient.data.l != (long) windows->wm_delete_window)
15518 (void) XWithdrawWindow(display,event.xclient.window,
15519 visual_info->screen);
15520 if (event.xclient.window == windows->image.id)
15525 if (event.xclient.window == windows->pan.id)
15528 Restore original image size when pan window is deleted.
15530 windows->image.window_changes.width=windows->image.ximage->width;
15531 windows->image.window_changes.height=windows->image.ximage->height;
15532 (void) XConfigureImage(display,resource_info,windows,
15533 display_image,exception);
15537 case ConfigureNotify:
15539 if( IfMagickTrue(display_image->debug) )
15540 (void) LogMagickEvent(X11Event,GetMagickModule(),
15541 "Configure Notify: 0x%lx %dx%d+%d+%d %d",event.xconfigure.window,
15542 event.xconfigure.width,event.xconfigure.height,event.xconfigure.x,
15543 event.xconfigure.y,event.xconfigure.send_event);
15544 if (event.xconfigure.window == windows->image.id)
15547 Image window has a new configuration.
15549 if (event.xconfigure.send_event != 0)
15555 Position the transient windows relative of the Image window.
15557 if (windows->command.geometry == (char *) NULL)
15558 if( IfMagickFalse(windows->command.mapped) )
15560 windows->command.x=event.xconfigure.x-
15561 windows->command.width-25;
15562 windows->command.y=event.xconfigure.y;
15563 XConstrainWindowPosition(display,&windows->command);
15564 window_changes.x=windows->command.x;
15565 window_changes.y=windows->command.y;
15566 (void) XReconfigureWMWindow(display,windows->command.id,
15567 windows->command.screen,(unsigned int) (CWX | CWY),
15570 if (windows->widget.geometry == (char *) NULL)
15571 if( IfMagickFalse(windows->widget.mapped) )
15573 windows->widget.x=event.xconfigure.x+
15574 event.xconfigure.width/10;
15575 windows->widget.y=event.xconfigure.y+
15576 event.xconfigure.height/10;
15577 XConstrainWindowPosition(display,&windows->widget);
15578 window_changes.x=windows->widget.x;
15579 window_changes.y=windows->widget.y;
15580 (void) XReconfigureWMWindow(display,windows->widget.id,
15581 windows->widget.screen,(unsigned int) (CWX | CWY),
15584 if (windows->magnify.geometry == (char *) NULL)
15585 if( IfMagickFalse(windows->magnify.mapped) )
15587 windows->magnify.x=event.xconfigure.x+
15588 event.xconfigure.width+25;
15589 windows->magnify.y=event.xconfigure.y;
15590 XConstrainWindowPosition(display,&windows->magnify);
15591 window_changes.x=windows->magnify.x;
15592 window_changes.y=windows->magnify.y;
15593 (void) XReconfigureWMWindow(display,windows->magnify.id,
15594 windows->magnify.screen,(unsigned int) (CWX | CWY),
15597 if (windows->pan.geometry == (char *) NULL)
15598 if( IfMagickFalse(windows->pan.mapped) )
15600 windows->pan.x=event.xconfigure.x+
15601 event.xconfigure.width+25;
15602 windows->pan.y=event.xconfigure.y+
15603 windows->magnify.height+50;
15604 XConstrainWindowPosition(display,&windows->pan);
15605 window_changes.x=windows->pan.x;
15606 window_changes.y=windows->pan.y;
15607 (void) XReconfigureWMWindow(display,windows->pan.id,
15608 windows->pan.screen,(unsigned int) (CWX | CWY),
15612 if ((event.xconfigure.width == (int) windows->image.width) &&
15613 (event.xconfigure.height == (int) windows->image.height))
15615 windows->image.width=(unsigned int) event.xconfigure.width;
15616 windows->image.height=(unsigned int) event.xconfigure.height;
15617 windows->image.x=0;
15618 windows->image.y=0;
15619 if (display_image->montage != (char *) NULL)
15621 windows->image.x=vid_info.x;
15622 windows->image.y=vid_info.y;
15624 if( IfMagickTrue(windows->image.mapped) &&
15625 IfMagickTrue(windows->image.stasis) )
15628 Update image window configuration.
15630 windows->image.window_changes.width=event.xconfigure.width;
15631 windows->image.window_changes.height=event.xconfigure.height;
15632 (void) XConfigureImage(display,resource_info,windows,
15633 display_image,exception);
15636 Update pan window configuration.
15638 if ((event.xconfigure.width < windows->image.ximage->width) ||
15639 (event.xconfigure.height < windows->image.ximage->height))
15641 (void) XMapRaised(display,windows->pan.id);
15642 XDrawPanRectangle(display,windows);
15645 if( IfMagickTrue(windows->pan.mapped) )
15646 (void) XWithdrawWindow(display,windows->pan.id,
15647 windows->pan.screen);
15650 if (event.xconfigure.window == windows->magnify.id)
15656 Magnify window has a new configuration.
15658 windows->magnify.width=(unsigned int) event.xconfigure.width;
15659 windows->magnify.height=(unsigned int) event.xconfigure.height;
15660 if( IfMagickFalse(windows->magnify.mapped) )
15663 while ((int) magnify <= event.xconfigure.width)
15665 while ((int) magnify <= event.xconfigure.height)
15668 if (((int) magnify != event.xconfigure.width) ||
15669 ((int) magnify != event.xconfigure.height))
15671 window_changes.width=(int) magnify;
15672 window_changes.height=(int) magnify;
15673 (void) XReconfigureWMWindow(display,windows->magnify.id,
15674 windows->magnify.screen,(unsigned int) (CWWidth | CWHeight),
15678 if( IfMagickTrue(windows->magnify.mapped) &&
15679 IfMagickTrue(windows->magnify.stasis) )
15681 status=XMakeImage(display,resource_info,&windows->magnify,
15682 display_image,windows->magnify.width,windows->magnify.height,
15684 XMakeMagnifyImage(display,windows,exception);
15688 if( IfMagickTrue(windows->magnify.mapped) &&
15689 (event.xconfigure.window == windows->pan.id))
15692 Pan icon window has a new configuration.
15694 if (event.xconfigure.send_event != 0)
15696 windows->pan.x=event.xconfigure.x;
15697 windows->pan.y=event.xconfigure.y;
15699 windows->pan.width=(unsigned int) event.xconfigure.width;
15700 windows->pan.height=(unsigned int) event.xconfigure.height;
15703 if (event.xconfigure.window == windows->icon.id)
15706 Icon window has a new configuration.
15708 windows->icon.width=(unsigned int) event.xconfigure.width;
15709 windows->icon.height=(unsigned int) event.xconfigure.height;
15714 case DestroyNotify:
15717 Group leader has exited.
15719 if( IfMagickTrue(display_image->debug) )
15720 (void) LogMagickEvent(X11Event,GetMagickModule(),
15721 "Destroy Notify: 0x%lx",event.xdestroywindow.window);
15722 if (event.xdestroywindow.window == windows->group_leader.id)
15732 Selectively install colormap.
15734 if (map_info->colormap != XDefaultColormap(display,visual_info->screen))
15735 if (event.xcrossing.mode != NotifyUngrab)
15736 XInstallColormap(display,map_info->colormap);
15741 if( IfMagickTrue(display_image->debug) )
15742 (void) LogMagickEvent(X11Event,GetMagickModule(),
15743 "Expose: 0x%lx %dx%d+%d+%d",event.xexpose.window,
15744 event.xexpose.width,event.xexpose.height,event.xexpose.x,
15747 Refresh windows that are now exposed.
15749 if ((event.xexpose.window == windows->image.id) &&
15750 IfMagickTrue(windows->image.mapped) )
15752 XRefreshWindow(display,&windows->image,&event);
15753 delay=display_image->delay/MagickMax(
15754 display_image->ticks_per_second,1L);
15755 timer=time((time_t *) NULL)+(delay == 0 ? 1 : delay)+1;
15758 if ((event.xexpose.window == windows->magnify.id) &&
15759 IfMagickTrue(windows->magnify.mapped))
15761 XMakeMagnifyImage(display,windows,exception);
15764 if (event.xexpose.window == windows->pan.id)
15766 XDrawPanRectangle(display,windows);
15769 if (event.xexpose.window == windows->icon.id)
15771 XRefreshWindow(display,&windows->icon,&event);
15782 Respond to a user key press.
15784 length=XLookupString((XKeyEvent *) &event.xkey,command,(int)
15785 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
15786 *(command+length)='\0';
15787 if( IfMagickTrue(display_image->debug) )
15788 (void) LogMagickEvent(X11Event,GetMagickModule(),
15789 "Key press: %d 0x%lx (%s)",event.xkey.state,(unsigned long)
15790 key_symbol,command);
15791 if (event.xkey.window == windows->image.id)
15793 command_type=XImageWindowCommand(display,resource_info,windows,
15794 event.xkey.state,key_symbol,&display_image,exception);
15795 if (command_type != NullCommand)
15796 nexus=XMagickCommand(display,resource_info,windows,command_type,
15797 &display_image,exception);
15799 if (event.xkey.window == windows->magnify.id)
15800 XMagnifyWindowCommand(display,windows,event.xkey.state,key_symbol,
15802 if (event.xkey.window == windows->pan.id)
15804 if ((key_symbol == XK_q) || (key_symbol == XK_Escape))
15805 (void) XWithdrawWindow(display,windows->pan.id,
15806 windows->pan.screen);
15808 if ((key_symbol == XK_F1) || (key_symbol == XK_Help))
15809 XTextViewWidget(display,resource_info,windows,MagickFalse,
15810 "Help Viewer - Image Pan",ImagePanHelp);
15812 XTranslateImage(display,windows,*image,key_symbol);
15814 delay=display_image->delay/MagickMax(
15815 display_image->ticks_per_second,1L);
15816 timer=time((time_t *) NULL)+(delay == 0 ? 1 : delay)+1;
15822 Respond to a user key release.
15824 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
15825 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
15826 if( IfMagickTrue(display_image->debug) )
15827 (void) LogMagickEvent(X11Event,GetMagickModule(),
15828 "Key release: 0x%lx (%c)",(unsigned long) key_symbol,*command);
15834 Selectively uninstall colormap.
15836 if (map_info->colormap != XDefaultColormap(display,visual_info->screen))
15837 if (event.xcrossing.mode != NotifyUngrab)
15838 XUninstallColormap(display,map_info->colormap);
15843 if( IfMagickTrue(display_image->debug) )
15844 (void) LogMagickEvent(X11Event,GetMagickModule(),"Map Notify: 0x%lx",
15845 event.xmap.window);
15846 if (event.xmap.window == windows->backdrop.id)
15848 (void) XSetInputFocus(display,event.xmap.window,RevertToParent,
15850 windows->backdrop.mapped=MagickTrue;
15853 if (event.xmap.window == windows->image.id)
15855 if (windows->backdrop.id != (Window) NULL)
15856 (void) XInstallColormap(display,map_info->colormap);
15857 if (LocaleCompare(display_image->magick,"LOGO") == 0)
15859 if (LocaleCompare(display_image->filename,"LOGO") == 0)
15860 nexus=XOpenImage(display,resource_info,windows,MagickFalse);
15862 if (((int) windows->image.width < windows->image.ximage->width) ||
15863 ((int) windows->image.height < windows->image.ximage->height))
15864 (void) XMapRaised(display,windows->pan.id);
15865 windows->image.mapped=MagickTrue;
15868 if (event.xmap.window == windows->magnify.id)
15870 XMakeMagnifyImage(display,windows,exception);
15871 windows->magnify.mapped=MagickTrue;
15872 (void) XWithdrawWindow(display,windows->info.id,
15873 windows->info.screen);
15876 if (event.xmap.window == windows->pan.id)
15878 XMakePanImage(display,resource_info,windows,display_image,
15880 windows->pan.mapped=MagickTrue;
15883 if (event.xmap.window == windows->info.id)
15885 windows->info.mapped=MagickTrue;
15888 if (event.xmap.window == windows->icon.id)
15894 Create an icon image.
15896 taint=display_image->taint;
15897 XMakeStandardColormap(display,icon_visual,icon_resources,
15898 display_image,icon_map,icon_pixel,exception);
15899 (void) XMakeImage(display,icon_resources,&windows->icon,
15900 display_image,windows->icon.width,windows->icon.height,
15902 display_image->taint=taint;
15903 (void) XSetWindowBackgroundPixmap(display,windows->icon.id,
15904 windows->icon.pixmap);
15905 (void) XClearWindow(display,windows->icon.id);
15906 (void) XWithdrawWindow(display,windows->info.id,
15907 windows->info.screen);
15908 windows->icon.mapped=MagickTrue;
15911 if (event.xmap.window == windows->command.id)
15913 windows->command.mapped=MagickTrue;
15916 if (event.xmap.window == windows->popup.id)
15918 windows->popup.mapped=MagickTrue;
15921 if (event.xmap.window == windows->widget.id)
15923 windows->widget.mapped=MagickTrue;
15928 case MappingNotify:
15930 (void) XRefreshKeyboardMapping(&event.xmapping);
15935 case PropertyNotify:
15951 if( IfMagickTrue(display_image->debug) )
15952 (void) LogMagickEvent(X11Event,GetMagickModule(),
15953 "Property Notify: 0x%lx 0x%lx %d",event.xproperty.window,
15954 event.xproperty.atom,event.xproperty.state);
15955 if (event.xproperty.atom != windows->im_remote_command)
15958 Display image named by the remote command protocol.
15960 status=XGetWindowProperty(display,event.xproperty.window,
15961 event.xproperty.atom,0L,(long) MaxTextExtent,MagickFalse,(Atom)
15962 AnyPropertyType,&type,&format,&length,&after,&data);
15963 if ((status != Success) || (length == 0))
15965 if (LocaleCompare((char *) data,"-quit") == 0)
15967 XClientMessage(display,windows->image.id,windows->im_protocols,
15968 windows->im_exit,CurrentTime);
15969 (void) XFree((void *) data);
15972 (void) CopyMagickString(resource_info->image_info->filename,
15973 (char *) data,MaxTextExtent);
15974 (void) XFree((void *) data);
15975 nexus=ReadImage(resource_info->image_info,exception);
15976 CatchException(exception);
15977 if (nexus != (Image *) NULL)
15978 *state|=NextImageState | ExitState;
15981 case ReparentNotify:
15983 if( IfMagickTrue(display_image->debug) )
15984 (void) LogMagickEvent(X11Event,GetMagickModule(),
15985 "Reparent Notify: 0x%lx=>0x%lx",event.xreparent.parent,
15986 event.xreparent.window);
15991 if( IfMagickTrue(display_image->debug) )
15992 (void) LogMagickEvent(X11Event,GetMagickModule(),
15993 "Unmap Notify: 0x%lx",event.xunmap.window);
15994 if (event.xunmap.window == windows->backdrop.id)
15996 windows->backdrop.mapped=MagickFalse;
15999 if (event.xunmap.window == windows->image.id)
16001 windows->image.mapped=MagickFalse;
16004 if (event.xunmap.window == windows->magnify.id)
16006 windows->magnify.mapped=MagickFalse;
16009 if (event.xunmap.window == windows->pan.id)
16011 windows->pan.mapped=MagickFalse;
16014 if (event.xunmap.window == windows->info.id)
16016 windows->info.mapped=MagickFalse;
16019 if (event.xunmap.window == windows->icon.id)
16021 if (map_info->colormap == icon_map->colormap)
16022 XConfigureImageColormap(display,resource_info,windows,
16023 display_image,exception);
16024 (void) XFreeStandardColormap(display,icon_visual,icon_map,
16026 windows->icon.mapped=MagickFalse;
16029 if (event.xunmap.window == windows->command.id)
16031 windows->command.mapped=MagickFalse;
16034 if (event.xunmap.window == windows->popup.id)
16036 if (windows->backdrop.id != (Window) NULL)
16037 (void) XSetInputFocus(display,windows->image.id,RevertToParent,
16039 windows->popup.mapped=MagickFalse;
16042 if (event.xunmap.window == windows->widget.id)
16044 if (windows->backdrop.id != (Window) NULL)
16045 (void) XSetInputFocus(display,windows->image.id,RevertToParent,
16047 windows->widget.mapped=MagickFalse;
16054 if( IfMagickTrue(display_image->debug) )
16055 (void) LogMagickEvent(X11Event,GetMagickModule(),"Event type: %d",
16060 } while (!(*state & ExitState));
16061 if ((*state & ExitState) == 0)
16062 (void) XMagickCommand(display,resource_info,windows,FreeBuffersCommand,
16063 &display_image,exception);
16065 if( IfMagickTrue(resource_info->confirm_edit) )
16068 Query user if image has changed.
16070 if( IfMagickFalse(resource_info->immutable) &&
16071 IfMagickTrue(display_image->taint))
16076 status=XConfirmWidget(display,windows,"Your image changed.",
16077 "Do you want to save it");
16079 *state&=(~ExitState);
16082 (void) XMagickCommand(display,resource_info,windows,SaveCommand,
16083 &display_image,exception);
16086 if ((windows->visual_info->klass == GrayScale) ||
16087 (windows->visual_info->klass == PseudoColor) ||
16088 (windows->visual_info->klass == DirectColor))
16091 Withdraw pan and Magnify window.
16093 if( IfMagickTrue(windows->info.mapped) )
16094 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
16095 if( IfMagickTrue(windows->magnify.mapped) )
16096 (void) XWithdrawWindow(display,windows->magnify.id,
16097 windows->magnify.screen);
16098 if( IfMagickTrue(windows->command.mapped) )
16099 (void) XWithdrawWindow(display,windows->command.id,
16100 windows->command.screen);
16102 if( IfMagickTrue(windows->pan.mapped) )
16103 (void) XWithdrawWindow(display,windows->pan.id,windows->pan.screen);
16104 if( IfMagickFalse(resource_info->backdrop) )
16105 if (windows->backdrop.mapped)
16107 (void) XWithdrawWindow(display,windows->backdrop.id,
16108 windows->backdrop.screen);
16109 (void) XDestroyWindow(display,windows->backdrop.id);
16110 windows->backdrop.id=(Window) NULL;
16111 (void) XWithdrawWindow(display,windows->image.id,
16112 windows->image.screen);
16113 (void) XDestroyWindow(display,windows->image.id);
16114 windows->image.id=(Window) NULL;
16116 XSetCursorState(display,windows,MagickTrue);
16117 XCheckRefreshWindows(display,windows);
16118 if (((*state & FormerImageState) != 0) || ((*state & NextImageState) != 0))
16119 *state&=(~ExitState);
16120 if (*state & ExitState)
16123 Free Standard Colormap.
16125 (void) XFreeStandardColormap(display,icon_visual,icon_map,icon_pixel);
16126 if (resource_info->map_type == (char *) NULL)
16127 (void) XFreeStandardColormap(display,visual_info,map_info,pixel);
16131 if (resource_info->copy_image != (Image *) NULL)
16133 resource_info->copy_image=DestroyImage(resource_info->copy_image);
16134 resource_info->copy_image=NewImageList();
16136 DestroyXResources();
16138 (void) XSync(display,MagickFalse);
16140 Restore our progress monitor and warning handlers.
16142 (void) SetErrorHandler(warning_handler);
16143 (void) SetWarningHandler(warning_handler);
16145 Change to home directory.
16147 directory=getcwd(working_directory,MaxTextExtent);
16153 if (*resource_info->home_directory == '\0')
16154 (void) CopyMagickString(resource_info->home_directory,".",MaxTextExtent);
16155 status=chdir(resource_info->home_directory);
16157 (void) ThrowMagickException(exception,GetMagickModule(),FileOpenError,
16158 "UnableToOpenFile","%s",resource_info->home_directory);
16160 *image=display_image;
16166 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
16170 + D i s p l a y I m a g e s %
16174 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
16176 % DisplayImages() displays an image sequence to any X window screen. It
16177 % returns a value other than 0 if successful. Check the exception member
16178 % of image to determine the reason for any failure.
16180 % The format of the DisplayImages method is:
16182 % MagickBooleanType DisplayImages(const ImageInfo *image_info,
16183 % Image *images,ExceptionInfo *exception)
16185 % A description of each parameter follows:
16187 % o image_info: the image info.
16189 % o image: the image.
16191 % o exception: return any errors or warnings in this structure.
16194 MagickExport MagickBooleanType DisplayImages(const ImageInfo *image_info,
16195 Image *image,ExceptionInfo *exception)
16197 assert(image_info != (const ImageInfo *) NULL);
16198 assert(image_info->signature == MagickSignature);
16199 assert(image != (Image *) NULL);
16200 assert(image->signature == MagickSignature);
16201 if( IfMagickTrue(image->debug) )
16202 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
16203 (void) ThrowMagickException(exception,GetMagickModule(),MissingDelegateError,
16204 "DelegateLibrarySupportNotBuiltIn","'%s' (X11)",image->filename);
16205 return(MagickFalse);
16209 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
16213 + R e m o t e D i s p l a y C o m m a n d %
16217 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
16219 % RemoteDisplayCommand() encourages a remote display program to display the
16220 % specified image filename.
16222 % The format of the RemoteDisplayCommand method is:
16224 % MagickBooleanType RemoteDisplayCommand(const ImageInfo *image,
16225 % const char *window,const char *filename,ExceptionInfo *exception)
16227 % A description of each parameter follows:
16229 % o image_info: the image info.
16231 % o window: Specifies the name or id of an X window.
16233 % o filename: the name of the image filename to display.
16235 % o exception: return any errors or warnings in this structure.
16238 MagickExport MagickBooleanType RemoteDisplayCommand(const ImageInfo *image_info,
16239 const char *window,const char *filename,ExceptionInfo *exception)
16241 assert(image_info != (const ImageInfo *) NULL);
16242 assert(image_info->signature == MagickSignature);
16243 assert(filename != (char *) NULL);
16245 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
16246 (void) ThrowMagickException(exception,GetMagickModule(),MissingDelegateError,
16247 "DelegateLibrarySupportNotBuiltIn","'%s' (X11)",image_info->filename);
16248 return(MagickFalse);