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-2012 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 (images->debug != MagickFalse)
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(status != 0 ? MagickTrue : MagickFalse);
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 (windows->info.mapped != MagickFalse)
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 (transparent_pen != MagickFalse)
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 (transparent_box != MagickFalse)
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 (windows->info.mapped != MagickFalse)
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 ((transparent_box == MagickFalse) && (transparent_pen == MagickFalse))
2275 annotate_info->stencil=OpaqueStencil;
2277 if (transparent_box == MagickFalse)
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=status != 0 ? MagickTrue : MagickFalse;
2827 status=XDisplayBackgroundImage(display,&background_resources,*image,
2829 if (status != MagickFalse)
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 (windows->info.mapped != MagickFalse)
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 (windows->info.mapped != MagickFalse)
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 (windows->info.mapped == MagickFalse)
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 (windows->info.mapped != MagickFalse)
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 (windows->info.mapped != MagickFalse)
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 (windows->info.mapped != MagickFalse)
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 (SetImageStorageClass(*image,DirectClass,exception) == MagickFalse)
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 (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
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,(ssize_t)
3840 x_offset,(ssize_t) y_offset,method == FloodfillMethod ?
3841 MagickFalse : MagickTrue,exception);
3842 draw_info=DestroyDrawInfo(draw_info);
3848 Update color information using reset algorithm.
3850 if (SetImageStorageClass(*image,DirectClass,exception) == MagickFalse)
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 (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
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 (windows->info.mapped != MagickFalse)
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 (image->debug != MagickFalse)
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 (image->debug != MagickFalse)
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 (image->debug != MagickFalse)
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 (windows->info.mapped != MagickFalse)
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 (image->debug != MagickFalse)
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 (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
4337 return(MagickFalse);
4338 image->matte=MagickTrue;
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 (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
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 (image->debug != MagickFalse)
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 (status == MagickFalse)
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 (windows->magnify.mapped != MagickFalse)
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(status != 0 ? MagickTrue : MagickFalse);
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 (windows->info.mapped != MagickFalse)
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 (windows->info.mapped != MagickFalse)
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 (windows->info.mapped == MagickFalse)
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 (windows->info.mapped != MagickFalse)
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 (windows->info.mapped != MagickFalse)
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 (windows->info.mapped != MagickFalse)
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 (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
5358 return(MagickFalse);
5359 image->matte=MagickTrue;
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 (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
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 (windows->info.mapped != MagickFalse)
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 (transparent != MagickFalse)
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 (windows->info.mapped != MagickFalse)
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 (windows->info.mapped != MagickFalse)
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 (windows->info.mapped != MagickFalse)
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 (windows->info.mapped != MagickFalse)
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 (windows->info.mapped != MagickFalse)
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(status != 0 ? MagickTrue : MagickFalse);
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 (windows->image.orphan != MagickFalse)
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 (windows->image.orphan != MagickFalse)
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 status=chdir(resource_info->home_directory);
7206 (void) ThrowMagickException(exception,GetMagickModule(),FileOpenError,
7207 "UnableToOpenFile","%s",resource_info->home_directory);
7208 nexus=XOpenImage(display,resource_info,windows,MagickTrue);
7216 status=XSaveImage(display,resource_info,windows,*image,exception);
7217 if (status == MagickFalse)
7220 message[MaxTextExtent];
7222 (void) FormatLocaleString(message,MaxTextExtent,"%s:%s",
7223 exception->reason != (char *) NULL ? exception->reason : "",
7224 exception->description != (char *) NULL ? exception->description :
7226 XNoticeWidget(display,windows,"Unable to save file:",message);
7236 status=XPrintImage(display,resource_info,windows,*image,exception);
7237 if (status == MagickFalse)
7240 message[MaxTextExtent];
7242 (void) FormatLocaleString(message,MaxTextExtent,"%s:%s",
7243 exception->reason != (char *) NULL ? exception->reason : "",
7244 exception->description != (char *) NULL ? exception->description :
7246 XNoticeWidget(display,windows,"Unable to print file:",message);
7254 filename[MaxTextExtent] = "\0";
7259 XFileBrowserWidget(display,windows,"Delete",filename);
7260 if (*filename == '\0')
7262 status=remove_utf8(filename) != 0 ? MagickTrue : MagickFalse;
7263 if (status != MagickFalse)
7264 XNoticeWidget(display,windows,"Unable to delete image file:",filename);
7273 color[MaxTextExtent] = "gray",
7274 geometry[MaxTextExtent] = "640x480";
7277 *format = "gradient";
7280 Query user for canvas geometry.
7282 status=XDialogWidget(display,windows,"New","Enter image geometry:",
7284 if (*geometry == '\0')
7288 XColorBrowserWidget(display,windows,"Select",color);
7294 (void) FormatLocaleString(image_info->filename,MaxTextExtent,
7295 "%s:%s",format,color);
7296 (void) CloneString(&image_info->size,geometry);
7297 nexus=ReadImage(image_info,exception);
7298 CatchException(exception);
7299 XClientMessage(display,windows->image.id,windows->im_protocols,
7300 windows->im_next_image,CurrentTime);
7303 case VisualDirectoryCommand:
7306 Visual Image directory.
7308 nexus=XVisualDirectoryImage(display,resource_info,windows,exception);
7316 if (resource_info->confirm_exit == MagickFalse)
7317 XClientMessage(display,windows->image.id,windows->im_protocols,
7318 windows->im_exit,CurrentTime);
7325 Confirm program exit.
7327 status=XConfirmWidget(display,windows,"Do you really want to exit",
7328 resource_info->client_name);
7330 XClientMessage(display,windows->image.id,windows->im_protocols,
7331 windows->im_exit,CurrentTime);
7340 (void) XCropImage(display,resource_info,windows,*image,CutMode,exception);
7348 (void) XCropImage(display,resource_info,windows,*image,CopyMode,
7357 status=XPasteImage(display,resource_info,windows,*image,exception);
7358 if (status == MagickFalse)
7360 XNoticeWidget(display,windows,"Unable to paste X image",
7361 (*image)->filename);
7366 case HalfSizeCommand:
7371 windows->image.window_changes.width=windows->image.ximage->width/2;
7372 windows->image.window_changes.height=windows->image.ximage->height/2;
7373 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7376 case OriginalSizeCommand:
7379 Original image size.
7381 windows->image.window_changes.width=(int) (*image)->columns;
7382 windows->image.window_changes.height=(int) (*image)->rows;
7383 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7386 case DoubleSizeCommand:
7389 Double the image size.
7391 windows->image.window_changes.width=windows->image.ximage->width << 1;
7392 windows->image.window_changes.height=windows->image.ximage->height << 1;
7393 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7412 width=(size_t) windows->image.ximage->width;
7413 height=(size_t) windows->image.ximage->height;
7416 (void) FormatLocaleString(geometry,MaxTextExtent,"%.20gx%.20g+0+0",
7417 (double) width,(double) height);
7418 status=XDialogWidget(display,windows,"Resize",
7419 "Enter resize geometry (e.g. 640x480, 200%):",geometry);
7420 if (*geometry == '\0')
7423 (void) ConcatenateMagickString(geometry,"!",MaxTextExtent);
7424 (void) ParseMetaGeometry(geometry,&x,&y,&width,&height);
7425 windows->image.window_changes.width=(int) width;
7426 windows->image.window_changes.height=(int) height;
7427 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7433 image_geometry[MaxTextExtent];
7435 if ((windows->image.crop_geometry == (char *) NULL) &&
7436 ((int) (*image)->columns == windows->image.ximage->width) &&
7437 ((int) (*image)->rows == windows->image.ximage->height))
7440 Apply size transforms to image.
7442 XSetCursorState(display,windows,MagickTrue);
7443 XCheckRefreshWindows(display,windows);
7445 Crop and/or scale displayed image.
7447 (void) FormatLocaleString(image_geometry,MaxTextExtent,"%dx%d!",
7448 windows->image.ximage->width,windows->image.ximage->height);
7449 (void) TransformImage(image,windows->image.crop_geometry,image_geometry,
7451 if (windows->image.crop_geometry != (char *) NULL)
7452 windows->image.crop_geometry=(char *) RelinquishMagickMemory(
7453 windows->image.crop_geometry);
7456 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7457 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7460 case RefreshCommand:
7462 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7465 case RestoreCommand:
7468 Restore Image window to its original size.
7470 if ((windows->image.width == (unsigned int) (*image)->columns) &&
7471 (windows->image.height == (unsigned int) (*image)->rows) &&
7472 (windows->image.crop_geometry == (char *) NULL))
7474 (void) XBell(display,0);
7477 windows->image.window_changes.width=(int) (*image)->columns;
7478 windows->image.window_changes.height=(int) (*image)->rows;
7479 if (windows->image.crop_geometry != (char *) NULL)
7481 windows->image.crop_geometry=(char *)
7482 RelinquishMagickMemory(windows->image.crop_geometry);
7483 windows->image.crop_geometry=(char *) NULL;
7487 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7488 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7496 (void) XCropImage(display,resource_info,windows,*image,CropMode,
7505 status=XChopImage(display,resource_info,windows,image,exception);
7506 if (status == MagickFalse)
7508 XNoticeWidget(display,windows,"Unable to cut X image",
7509 (*image)->filename);
7520 Flop image scanlines.
7522 XSetCursorState(display,windows,MagickTrue);
7523 XCheckRefreshWindows(display,windows);
7524 flop_image=FlopImage(*image,exception);
7525 if (flop_image != (Image *) NULL)
7527 *image=DestroyImage(*image);
7530 CatchException(exception);
7531 XSetCursorState(display,windows,MagickFalse);
7532 if (windows->image.crop_geometry != (char *) NULL)
7537 width=(unsigned int) (*image)->columns;
7538 height=(unsigned int) (*image)->rows;
7539 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,
7541 (void) FormatLocaleString(windows->image.crop_geometry,MaxTextExtent,
7542 "%ux%u%+d%+d",width,height,(int) (*image)->columns-(int) width-x,y);
7544 if (windows->image.orphan != MagickFalse)
7546 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7555 Flip image scanlines.
7557 XSetCursorState(display,windows,MagickTrue);
7558 XCheckRefreshWindows(display,windows);
7559 flip_image=FlipImage(*image,exception);
7560 if (flip_image != (Image *) NULL)
7562 *image=DestroyImage(*image);
7565 CatchException(exception);
7566 XSetCursorState(display,windows,MagickFalse);
7567 if (windows->image.crop_geometry != (char *) NULL)
7572 width=(unsigned int) (*image)->columns;
7573 height=(unsigned int) (*image)->rows;
7574 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,
7576 (void) FormatLocaleString(windows->image.crop_geometry,MaxTextExtent,
7577 "%ux%u%+d%+d",width,height,x,(int) (*image)->rows-(int) height-y);
7579 if (windows->image.orphan != MagickFalse)
7581 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7584 case RotateRightCommand:
7587 Rotate image 90 degrees clockwise.
7589 status=XRotateImage(display,resource_info,windows,90.0,image,exception);
7590 if (status == MagickFalse)
7592 XNoticeWidget(display,windows,"Unable to rotate X image",
7593 (*image)->filename);
7598 case RotateLeftCommand:
7601 Rotate image 90 degrees counter-clockwise.
7603 status=XRotateImage(display,resource_info,windows,-90.0,image,exception);
7604 if (status == MagickFalse)
7606 XNoticeWidget(display,windows,"Unable to rotate X image",
7607 (*image)->filename);
7617 status=XRotateImage(display,resource_info,windows,0.0,image,exception);
7618 if (status == MagickFalse)
7620 XNoticeWidget(display,windows,"Unable to rotate X image",
7621 (*image)->filename);
7632 geometry[MaxTextExtent] = "45.0x45.0";
7635 Query user for shear color and geometry.
7637 XColorBrowserWidget(display,windows,"Select",color);
7640 (void) XDialogWidget(display,windows,"Shear","Enter shear geometry:",
7642 if (*geometry == '\0')
7647 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image,
7649 XSetCursorState(display,windows,MagickTrue);
7650 XCheckRefreshWindows(display,windows);
7651 (void) QueryColorCompliance(color,AllCompliance,
7652 &(*image)->background_color,exception);
7653 flags=ParseGeometry(geometry,&geometry_info);
7654 if ((flags & SigmaValue) == 0)
7655 geometry_info.sigma=geometry_info.rho;
7656 shear_image=ShearImage(*image,geometry_info.rho,geometry_info.sigma,
7658 if (shear_image != (Image *) NULL)
7660 *image=DestroyImage(*image);
7663 CatchException(exception);
7664 XSetCursorState(display,windows,MagickFalse);
7665 if (windows->image.orphan != MagickFalse)
7667 windows->image.window_changes.width=(int) (*image)->columns;
7668 windows->image.window_changes.height=(int) (*image)->rows;
7669 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7670 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7679 geometry[MaxTextExtent] = "+2+2";
7682 Query user for the roll geometry.
7684 (void) XDialogWidget(display,windows,"Roll","Enter roll geometry:",
7686 if (*geometry == '\0')
7691 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image,
7693 XSetCursorState(display,windows,MagickTrue);
7694 XCheckRefreshWindows(display,windows);
7695 (void) ParsePageGeometry(*image,geometry,&page_geometry,
7697 roll_image=RollImage(*image,page_geometry.x,page_geometry.y,
7699 if (roll_image != (Image *) NULL)
7701 *image=DestroyImage(*image);
7704 CatchException(exception);
7705 XSetCursorState(display,windows,MagickFalse);
7706 if (windows->image.orphan != MagickFalse)
7708 windows->image.window_changes.width=(int) (*image)->columns;
7709 windows->image.window_changes.height=(int) (*image)->rows;
7710 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7711 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7717 fuzz[MaxTextExtent];
7720 Query user for the fuzz factor.
7722 (void) FormatLocaleString(fuzz,MaxTextExtent,"%g%%",100.0*
7723 (*image)->fuzz/(QuantumRange+1.0));
7724 (void) XDialogWidget(display,windows,"Trim","Enter fuzz factor:",fuzz);
7727 (*image)->fuzz=StringToDoubleInterval(fuzz,(double) QuantumRange+1.0);
7731 status=XTrimImage(display,resource_info,windows,*image,exception);
7732 if (status == MagickFalse)
7734 XNoticeWidget(display,windows,"Unable to trim X image",
7735 (*image)->filename);
7743 hue_percent[MaxTextExtent] = "110";
7746 Query user for percent hue change.
7748 (void) XDialogWidget(display,windows,"Apply",
7749 "Enter percent change in image hue (0-200):",hue_percent);
7750 if (*hue_percent == '\0')
7755 XSetCursorState(display,windows,MagickTrue);
7756 XCheckRefreshWindows(display,windows);
7757 (void) CopyMagickString(modulate_factors,"100.0/100.0/",MaxTextExtent);
7758 (void) ConcatenateMagickString(modulate_factors,hue_percent,
7760 (void) ModulateImage(*image,modulate_factors,exception);
7761 XSetCursorState(display,windows,MagickFalse);
7762 if (windows->image.orphan != MagickFalse)
7764 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7765 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7768 case SaturationCommand:
7771 saturation_percent[MaxTextExtent] = "110";
7774 Query user for percent saturation change.
7776 (void) XDialogWidget(display,windows,"Apply",
7777 "Enter percent change in color saturation (0-200):",saturation_percent);
7778 if (*saturation_percent == '\0')
7781 Vary color saturation.
7783 XSetCursorState(display,windows,MagickTrue);
7784 XCheckRefreshWindows(display,windows);
7785 (void) CopyMagickString(modulate_factors,"100.0/",MaxTextExtent);
7786 (void) ConcatenateMagickString(modulate_factors,saturation_percent,
7788 (void) ModulateImage(*image,modulate_factors,exception);
7789 XSetCursorState(display,windows,MagickFalse);
7790 if (windows->image.orphan != MagickFalse)
7792 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7793 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7796 case BrightnessCommand:
7799 brightness_percent[MaxTextExtent] = "110";
7802 Query user for percent brightness change.
7804 (void) XDialogWidget(display,windows,"Apply",
7805 "Enter percent change in color brightness (0-200):",brightness_percent);
7806 if (*brightness_percent == '\0')
7809 Vary the color brightness.
7811 XSetCursorState(display,windows,MagickTrue);
7812 XCheckRefreshWindows(display,windows);
7813 (void) CopyMagickString(modulate_factors,brightness_percent,
7815 (void) ModulateImage(*image,modulate_factors,exception);
7816 XSetCursorState(display,windows,MagickFalse);
7817 if (windows->image.orphan != MagickFalse)
7819 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7820 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7826 factor[MaxTextExtent] = "1.6";
7829 Query user for gamma value.
7831 (void) XDialogWidget(display,windows,"Gamma",
7832 "Enter gamma value (e.g. 1.2):",factor);
7833 if (*factor == '\0')
7836 Gamma correct image.
7838 XSetCursorState(display,windows,MagickTrue);
7839 XCheckRefreshWindows(display,windows);
7840 (void) GammaImage(*image,atof(factor),exception);
7841 XSetCursorState(display,windows,MagickFalse);
7842 if (windows->image.orphan != MagickFalse)
7844 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7845 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7851 Sharpen the image contrast.
7853 XSetCursorState(display,windows,MagickTrue);
7854 XCheckRefreshWindows(display,windows);
7855 (void) ContrastImage(*image,MagickTrue,exception);
7856 XSetCursorState(display,windows,MagickFalse);
7857 if (windows->image.orphan != MagickFalse)
7859 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7860 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7866 Dull the image contrast.
7868 XSetCursorState(display,windows,MagickTrue);
7869 XCheckRefreshWindows(display,windows);
7870 (void) ContrastImage(*image,MagickFalse,exception);
7871 XSetCursorState(display,windows,MagickFalse);
7872 if (windows->image.orphan != MagickFalse)
7874 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7875 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7878 case ContrastStretchCommand:
7885 levels[MaxTextExtent] = "1%";
7888 Query user for gamma value.
7890 (void) XDialogWidget(display,windows,"Contrast Stretch",
7891 "Enter black and white points:",levels);
7892 if (*levels == '\0')
7895 Contrast stretch image.
7897 XSetCursorState(display,windows,MagickTrue);
7898 XCheckRefreshWindows(display,windows);
7899 flags=ParseGeometry(levels,&geometry_info);
7900 black_point=geometry_info.rho;
7901 white_point=(flags & SigmaValue) != 0 ? geometry_info.sigma : black_point;
7902 if ((flags & PercentValue) != 0)
7904 black_point*=(double) (*image)->columns*(*image)->rows/100.0;
7905 white_point*=(double) (*image)->columns*(*image)->rows/100.0;
7907 white_point=(double) (*image)->columns*(*image)->rows-white_point;
7908 (void) ContrastStretchImage(*image,black_point,white_point,
7910 XSetCursorState(display,windows,MagickFalse);
7911 if (windows->image.orphan != MagickFalse)
7913 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7914 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7917 case SigmoidalContrastCommand:
7926 levels[MaxTextExtent] = "3x50%";
7929 Query user for gamma value.
7931 (void) XDialogWidget(display,windows,"Sigmoidal Contrast",
7932 "Enter contrast and midpoint:",levels);
7933 if (*levels == '\0')
7936 Contrast stretch image.
7938 XSetCursorState(display,windows,MagickTrue);
7939 XCheckRefreshWindows(display,windows);
7940 flags=ParseGeometry(levels,&geometry_info);
7941 if ((flags & SigmaValue) == 0)
7942 geometry_info.sigma=1.0*QuantumRange/2.0;
7943 if ((flags & PercentValue) != 0)
7944 geometry_info.sigma=1.0*QuantumRange*geometry_info.sigma/100.0;
7945 (void) SigmoidalContrastImage(*image,MagickTrue,geometry_info.rho,
7946 geometry_info.sigma,exception);
7947 XSetCursorState(display,windows,MagickFalse);
7948 if (windows->image.orphan != MagickFalse)
7950 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7951 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7954 case NormalizeCommand:
7957 Perform histogram normalization on the image.
7959 XSetCursorState(display,windows,MagickTrue);
7960 XCheckRefreshWindows(display,windows);
7961 (void) NormalizeImage(*image,exception);
7962 XSetCursorState(display,windows,MagickFalse);
7963 if (windows->image.orphan != MagickFalse)
7965 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7966 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7969 case EqualizeCommand:
7972 Perform histogram equalization on the image.
7974 XSetCursorState(display,windows,MagickTrue);
7975 XCheckRefreshWindows(display,windows);
7976 (void) EqualizeImage(*image,exception);
7977 XSetCursorState(display,windows,MagickFalse);
7978 if (windows->image.orphan != MagickFalse)
7980 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7981 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7987 Negate colors in image.
7989 XSetCursorState(display,windows,MagickTrue);
7990 XCheckRefreshWindows(display,windows);
7991 (void) NegateImage(*image,MagickFalse,exception);
7992 XSetCursorState(display,windows,MagickFalse);
7993 if (windows->image.orphan != MagickFalse)
7995 XConfigureImageColormap(display,resource_info,windows,*image,exception);
7996 (void) XConfigureImage(display,resource_info,windows,*image,exception);
7999 case GrayscaleCommand:
8002 Convert image to grayscale.
8004 XSetCursorState(display,windows,MagickTrue);
8005 XCheckRefreshWindows(display,windows);
8006 (void) SetImageType(*image,(*image)->matte == MagickFalse ?
8007 GrayscaleType : GrayscaleMatteType,exception);
8008 XSetCursorState(display,windows,MagickFalse);
8009 if (windows->image.orphan != MagickFalse)
8011 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8012 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8021 filename[MaxTextExtent] = "\0";
8024 Request image file name from user.
8026 XFileBrowserWidget(display,windows,"Map",filename);
8027 if (*filename == '\0')
8032 XSetCursorState(display,windows,MagickTrue);
8033 XCheckRefreshWindows(display,windows);
8034 (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
8035 affinity_image=ReadImage(image_info,exception);
8036 if (affinity_image != (Image *) NULL)
8038 (void) RemapImage(&quantize_info,*image,affinity_image,exception);
8039 affinity_image=DestroyImage(affinity_image);
8041 CatchException(exception);
8042 XSetCursorState(display,windows,MagickFalse);
8043 if (windows->image.orphan != MagickFalse)
8045 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8046 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8049 case QuantizeCommand:
8055 colors[MaxTextExtent] = "256";
8058 Query user for maximum number of colors.
8060 status=XDialogWidget(display,windows,"Quantize",
8061 "Maximum number of colors:",colors);
8062 if (*colors == '\0')
8065 Color reduce the image.
8067 XSetCursorState(display,windows,MagickTrue);
8068 XCheckRefreshWindows(display,windows);
8069 quantize_info.number_colors=StringToUnsignedLong(colors);
8070 quantize_info.dither_method=status != 0 ? RiemersmaDitherMethod :
8072 (void) QuantizeImage(&quantize_info,*image,exception);
8073 XSetCursorState(display,windows,MagickFalse);
8074 if (windows->image.orphan != MagickFalse)
8076 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8077 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8080 case DespeckleCommand:
8088 XSetCursorState(display,windows,MagickTrue);
8089 XCheckRefreshWindows(display,windows);
8090 despeckle_image=DespeckleImage(*image,exception);
8091 if (despeckle_image != (Image *) NULL)
8093 *image=DestroyImage(*image);
8094 *image=despeckle_image;
8096 CatchException(exception);
8097 XSetCursorState(display,windows,MagickFalse);
8098 if (windows->image.orphan != MagickFalse)
8100 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8101 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8110 radius[MaxTextExtent] = "0.0x1.0";
8113 Query user for emboss radius.
8115 (void) XDialogWidget(display,windows,"Emboss",
8116 "Enter the emboss radius and standard deviation:",radius);
8117 if (*radius == '\0')
8120 Reduce noise in the image.
8122 XSetCursorState(display,windows,MagickTrue);
8123 XCheckRefreshWindows(display,windows);
8124 flags=ParseGeometry(radius,&geometry_info);
8125 if ((flags & SigmaValue) == 0)
8126 geometry_info.sigma=1.0;
8127 emboss_image=EmbossImage(*image,geometry_info.rho,geometry_info.sigma,
8129 if (emboss_image != (Image *) NULL)
8131 *image=DestroyImage(*image);
8132 *image=emboss_image;
8134 CatchException(exception);
8135 XSetCursorState(display,windows,MagickFalse);
8136 if (windows->image.orphan != MagickFalse)
8138 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8139 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8142 case ReduceNoiseCommand:
8148 radius[MaxTextExtent] = "0";
8151 Query user for noise radius.
8153 (void) XDialogWidget(display,windows,"Reduce Noise",
8154 "Enter the noise radius:",radius);
8155 if (*radius == '\0')
8158 Reduce noise in the image.
8160 XSetCursorState(display,windows,MagickTrue);
8161 XCheckRefreshWindows(display,windows);
8162 flags=ParseGeometry(radius,&geometry_info);
8163 noise_image=StatisticImage(*image,NonpeakStatistic,(size_t)
8164 geometry_info.rho,(size_t) geometry_info.rho,exception);
8165 if (noise_image != (Image *) NULL)
8167 *image=DestroyImage(*image);
8170 CatchException(exception);
8171 XSetCursorState(display,windows,MagickFalse);
8172 if (windows->image.orphan != MagickFalse)
8174 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8175 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8178 case AddNoiseCommand:
8187 noise_type[MaxTextExtent] = "Gaussian";
8190 Add noise to the image.
8192 noises=GetCommandOptions(MagickNoiseOptions);
8193 if (noises == (char **) NULL)
8195 XListBrowserWidget(display,windows,&windows->widget,
8196 (const char **) noises,"Add Noise",
8197 "Select a type of noise to add to your image:",noise_type);
8198 noises=DestroyStringList(noises);
8199 if (*noise_type == '\0')
8201 XSetCursorState(display,windows,MagickTrue);
8202 XCheckRefreshWindows(display,windows);
8203 noise_image=AddNoiseImage(*image,(NoiseType) ParseCommandOption(
8204 MagickNoiseOptions,MagickFalse,noise_type),1.0,exception);
8205 if (noise_image != (Image *) NULL)
8207 *image=DestroyImage(*image);
8210 CatchException(exception);
8211 XSetCursorState(display,windows,MagickFalse);
8212 if (windows->image.orphan != MagickFalse)
8214 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8215 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8218 case SharpenCommand:
8224 radius[MaxTextExtent] = "0.0x1.0";
8227 Query user for sharpen radius.
8229 (void) XDialogWidget(display,windows,"Sharpen",
8230 "Enter the sharpen radius and standard deviation:",radius);
8231 if (*radius == '\0')
8234 Sharpen image scanlines.
8236 XSetCursorState(display,windows,MagickTrue);
8237 XCheckRefreshWindows(display,windows);
8238 flags=ParseGeometry(radius,&geometry_info);
8239 sharp_image=SharpenImage(*image,geometry_info.rho,geometry_info.sigma,
8241 if (sharp_image != (Image *) NULL)
8243 *image=DestroyImage(*image);
8246 CatchException(exception);
8247 XSetCursorState(display,windows,MagickFalse);
8248 if (windows->image.orphan != MagickFalse)
8250 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8251 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8260 radius[MaxTextExtent] = "0.0x1.0";
8263 Query user for blur radius.
8265 (void) XDialogWidget(display,windows,"Blur",
8266 "Enter the blur radius and standard deviation:",radius);
8267 if (*radius == '\0')
8272 XSetCursorState(display,windows,MagickTrue);
8273 XCheckRefreshWindows(display,windows);
8274 flags=ParseGeometry(radius,&geometry_info);
8275 blur_image=BlurImage(*image,geometry_info.rho,geometry_info.sigma,
8277 if (blur_image != (Image *) NULL)
8279 *image=DestroyImage(*image);
8282 CatchException(exception);
8283 XSetCursorState(display,windows,MagickFalse);
8284 if (windows->image.orphan != MagickFalse)
8286 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8287 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8290 case ThresholdCommand:
8296 factor[MaxTextExtent] = "128";
8299 Query user for threshold value.
8301 (void) XDialogWidget(display,windows,"Threshold",
8302 "Enter threshold value:",factor);
8303 if (*factor == '\0')
8306 Gamma correct image.
8308 XSetCursorState(display,windows,MagickTrue);
8309 XCheckRefreshWindows(display,windows);
8310 threshold=StringToDoubleInterval(factor,(double) QuantumRange+1.0);
8311 (void) BilevelImage(*image,threshold,exception);
8312 XSetCursorState(display,windows,MagickFalse);
8313 if (windows->image.orphan != MagickFalse)
8315 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8316 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8319 case EdgeDetectCommand:
8325 radius[MaxTextExtent] = "0";
8328 Query user for edge factor.
8330 (void) XDialogWidget(display,windows,"Detect Edges",
8331 "Enter the edge detect radius:",radius);
8332 if (*radius == '\0')
8335 Detect edge in image.
8337 XSetCursorState(display,windows,MagickTrue);
8338 XCheckRefreshWindows(display,windows);
8339 flags=ParseGeometry(radius,&geometry_info);
8340 edge_image=EdgeImage(*image,geometry_info.rho,geometry_info.sigma,
8342 if (edge_image != (Image *) NULL)
8344 *image=DestroyImage(*image);
8347 CatchException(exception);
8348 XSetCursorState(display,windows,MagickFalse);
8349 if (windows->image.orphan != MagickFalse)
8351 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8352 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8361 amount[MaxTextExtent] = "2";
8364 Query user for spread amount.
8366 (void) XDialogWidget(display,windows,"Spread",
8367 "Enter the displacement amount:",amount);
8368 if (*amount == '\0')
8371 Displace image pixels by a random amount.
8373 XSetCursorState(display,windows,MagickTrue);
8374 XCheckRefreshWindows(display,windows);
8375 flags=ParseGeometry(amount,&geometry_info);
8376 spread_image=EdgeImage(*image,geometry_info.rho,geometry_info.sigma,
8378 if (spread_image != (Image *) NULL)
8380 *image=DestroyImage(*image);
8381 *image=spread_image;
8383 CatchException(exception);
8384 XSetCursorState(display,windows,MagickFalse);
8385 if (windows->image.orphan != MagickFalse)
8387 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8388 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8400 geometry[MaxTextExtent] = "30x30";
8403 Query user for the shade geometry.
8405 status=XDialogWidget(display,windows,"Shade",
8406 "Enter the azimuth and elevation of the light source:",geometry);
8407 if (*geometry == '\0')
8412 XSetCursorState(display,windows,MagickTrue);
8413 XCheckRefreshWindows(display,windows);
8414 flags=ParseGeometry(geometry,&geometry_info);
8415 if ((flags & SigmaValue) == 0)
8416 geometry_info.sigma=1.0;
8417 shade_image=ShadeImage(*image,status != 0 ? MagickFalse : MagickTrue,
8418 geometry_info.rho,geometry_info.sigma,exception);
8419 if (shade_image != (Image *) NULL)
8421 *image=DestroyImage(*image);
8424 CatchException(exception);
8425 XSetCursorState(display,windows,MagickFalse);
8426 if (windows->image.orphan != MagickFalse)
8428 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8429 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8435 bevel_width[MaxTextExtent] = "10";
8438 Query user for bevel width.
8440 (void) XDialogWidget(display,windows,"Raise","Bevel width:",bevel_width);
8441 if (*bevel_width == '\0')
8446 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image,
8448 XSetCursorState(display,windows,MagickTrue);
8449 XCheckRefreshWindows(display,windows);
8450 (void) ParsePageGeometry(*image,bevel_width,&page_geometry,
8452 (void) RaiseImage(*image,&page_geometry,MagickTrue,exception);
8453 XSetCursorState(display,windows,MagickFalse);
8454 if (windows->image.orphan != MagickFalse)
8456 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8457 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8460 case SegmentCommand:
8463 threshold[MaxTextExtent] = "1.0x1.5";
8466 Query user for smoothing threshold.
8468 (void) XDialogWidget(display,windows,"Segment","Smooth threshold:",
8470 if (*threshold == '\0')
8475 XSetCursorState(display,windows,MagickTrue);
8476 XCheckRefreshWindows(display,windows);
8477 flags=ParseGeometry(threshold,&geometry_info);
8478 if ((flags & SigmaValue) == 0)
8479 geometry_info.sigma=1.0;
8480 (void) SegmentImage(*image,sRGBColorspace,MagickFalse,geometry_info.rho,
8481 geometry_info.sigma,exception);
8482 XSetCursorState(display,windows,MagickFalse);
8483 if (windows->image.orphan != MagickFalse)
8485 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8486 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8489 case SepiaToneCommand:
8498 factor[MaxTextExtent] = "80%";
8501 Query user for sepia-tone factor.
8503 (void) XDialogWidget(display,windows,"Sepia Tone",
8504 "Enter the sepia tone factor (0 - 99.9%):",factor);
8505 if (*factor == '\0')
8508 Sepia tone image pixels.
8510 XSetCursorState(display,windows,MagickTrue);
8511 XCheckRefreshWindows(display,windows);
8512 threshold=StringToDoubleInterval(factor,(double) QuantumRange+1.0);
8513 sepia_image=SepiaToneImage(*image,threshold,exception);
8514 if (sepia_image != (Image *) NULL)
8516 *image=DestroyImage(*image);
8519 CatchException(exception);
8520 XSetCursorState(display,windows,MagickFalse);
8521 if (windows->image.orphan != MagickFalse)
8523 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8524 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8527 case SolarizeCommand:
8533 factor[MaxTextExtent] = "60%";
8536 Query user for solarize factor.
8538 (void) XDialogWidget(display,windows,"Solarize",
8539 "Enter the solarize factor (0 - 99.9%):",factor);
8540 if (*factor == '\0')
8543 Solarize image pixels.
8545 XSetCursorState(display,windows,MagickTrue);
8546 XCheckRefreshWindows(display,windows);
8547 threshold=StringToDoubleInterval(factor,(double) QuantumRange+1.0);
8548 (void) SolarizeImage(*image,threshold,exception);
8549 XSetCursorState(display,windows,MagickFalse);
8550 if (windows->image.orphan != MagickFalse)
8552 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8553 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8562 degrees[MaxTextExtent] = "60";
8565 Query user for swirl angle.
8567 (void) XDialogWidget(display,windows,"Swirl","Enter the swirl angle:",
8569 if (*degrees == '\0')
8572 Swirl image pixels about the center.
8574 XSetCursorState(display,windows,MagickTrue);
8575 XCheckRefreshWindows(display,windows);
8576 flags=ParseGeometry(degrees,&geometry_info);
8577 swirl_image=SwirlImage(*image,geometry_info.rho,(*image)->interpolate,
8579 if (swirl_image != (Image *) NULL)
8581 *image=DestroyImage(*image);
8584 CatchException(exception);
8585 XSetCursorState(display,windows,MagickFalse);
8586 if (windows->image.orphan != MagickFalse)
8588 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8589 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8592 case ImplodeCommand:
8598 factor[MaxTextExtent] = "0.3";
8601 Query user for implode factor.
8603 (void) XDialogWidget(display,windows,"Implode",
8604 "Enter the implosion/explosion factor (-1.0 - 1.0):",factor);
8605 if (*factor == '\0')
8608 Implode image pixels about the center.
8610 XSetCursorState(display,windows,MagickTrue);
8611 XCheckRefreshWindows(display,windows);
8612 flags=ParseGeometry(factor,&geometry_info);
8613 implode_image=ImplodeImage(*image,geometry_info.rho,(*image)->interpolate,
8615 if (implode_image != (Image *) NULL)
8617 *image=DestroyImage(*image);
8618 *image=implode_image;
8620 CatchException(exception);
8621 XSetCursorState(display,windows,MagickFalse);
8622 if (windows->image.orphan != MagickFalse)
8624 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8625 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8628 case VignetteCommand:
8634 geometry[MaxTextExtent] = "0x20";
8637 Query user for the vignette geometry.
8639 (void) XDialogWidget(display,windows,"Vignette",
8640 "Enter the radius, sigma, and x and y offsets:",geometry);
8641 if (*geometry == '\0')
8644 Soften the edges of the image in vignette style
8646 XSetCursorState(display,windows,MagickTrue);
8647 XCheckRefreshWindows(display,windows);
8648 flags=ParseGeometry(geometry,&geometry_info);
8649 if ((flags & SigmaValue) == 0)
8650 geometry_info.sigma=1.0;
8651 if ((flags & XiValue) == 0)
8652 geometry_info.xi=0.1*(*image)->columns;
8653 if ((flags & PsiValue) == 0)
8654 geometry_info.psi=0.1*(*image)->rows;
8655 vignette_image=VignetteImage(*image,geometry_info.rho,0.0,(ssize_t)
8656 ceil(geometry_info.xi-0.5),(ssize_t) ceil(geometry_info.psi-0.5),
8658 if (vignette_image != (Image *) NULL)
8660 *image=DestroyImage(*image);
8661 *image=vignette_image;
8663 CatchException(exception);
8664 XSetCursorState(display,windows,MagickFalse);
8665 if (windows->image.orphan != MagickFalse)
8667 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8668 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8677 geometry[MaxTextExtent] = "25x150";
8680 Query user for the wave geometry.
8682 (void) XDialogWidget(display,windows,"Wave",
8683 "Enter the amplitude and length of the wave:",geometry);
8684 if (*geometry == '\0')
8687 Alter an image along a sine wave.
8689 XSetCursorState(display,windows,MagickTrue);
8690 XCheckRefreshWindows(display,windows);
8691 flags=ParseGeometry(geometry,&geometry_info);
8692 if ((flags & SigmaValue) == 0)
8693 geometry_info.sigma=1.0;
8694 wave_image=WaveImage(*image,geometry_info.rho,geometry_info.sigma,
8695 (*image)->interpolate,exception);
8696 if (wave_image != (Image *) NULL)
8698 *image=DestroyImage(*image);
8701 CatchException(exception);
8702 XSetCursorState(display,windows,MagickFalse);
8703 if (windows->image.orphan != MagickFalse)
8705 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8706 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8709 case OilPaintCommand:
8715 radius[MaxTextExtent] = "0";
8718 Query user for circular neighborhood radius.
8720 (void) XDialogWidget(display,windows,"Oil Paint",
8721 "Enter the mask radius:",radius);
8722 if (*radius == '\0')
8725 OilPaint image scanlines.
8727 XSetCursorState(display,windows,MagickTrue);
8728 XCheckRefreshWindows(display,windows);
8729 flags=ParseGeometry(radius,&geometry_info);
8730 paint_image=OilPaintImage(*image,geometry_info.rho,geometry_info.sigma,
8732 if (paint_image != (Image *) NULL)
8734 *image=DestroyImage(*image);
8737 CatchException(exception);
8738 XSetCursorState(display,windows,MagickFalse);
8739 if (windows->image.orphan != MagickFalse)
8741 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8742 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8745 case CharcoalDrawCommand:
8751 radius[MaxTextExtent] = "0x1";
8754 Query user for charcoal radius.
8756 (void) XDialogWidget(display,windows,"Charcoal Draw",
8757 "Enter the charcoal radius and sigma:",radius);
8758 if (*radius == '\0')
8763 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image,
8765 XSetCursorState(display,windows,MagickTrue);
8766 XCheckRefreshWindows(display,windows);
8767 flags=ParseGeometry(radius,&geometry_info);
8768 if ((flags & SigmaValue) == 0)
8769 geometry_info.sigma=geometry_info.rho;
8770 charcoal_image=CharcoalImage(*image,geometry_info.rho,geometry_info.sigma,
8772 if (charcoal_image != (Image *) NULL)
8774 *image=DestroyImage(*image);
8775 *image=charcoal_image;
8777 CatchException(exception);
8778 XSetCursorState(display,windows,MagickFalse);
8779 if (windows->image.orphan != MagickFalse)
8781 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8782 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8785 case AnnotateCommand:
8788 Annotate the image with text.
8790 status=XAnnotateEditImage(display,resource_info,windows,*image,exception);
8791 if (status == MagickFalse)
8793 XNoticeWidget(display,windows,"Unable to annotate X image",
8794 (*image)->filename);
8804 status=XDrawEditImage(display,resource_info,windows,image,exception);
8805 if (status == MagickFalse)
8807 XNoticeWidget(display,windows,"Unable to draw on the X image",
8808 (*image)->filename);
8818 status=XColorEditImage(display,resource_info,windows,image,exception);
8819 if (status == MagickFalse)
8821 XNoticeWidget(display,windows,"Unable to pixel edit X image",
8822 (*image)->filename);
8832 status=XMatteEditImage(display,resource_info,windows,image,exception);
8833 if (status == MagickFalse)
8835 XNoticeWidget(display,windows,"Unable to matte edit X image",
8836 (*image)->filename);
8841 case CompositeCommand:
8846 status=XCompositeImage(display,resource_info,windows,*image,
8848 if (status == MagickFalse)
8850 XNoticeWidget(display,windows,"Unable to composite X image",
8851 (*image)->filename);
8856 case AddBorderCommand:
8862 geometry[MaxTextExtent] = "6x6";
8865 Query user for border color and geometry.
8867 XColorBrowserWidget(display,windows,"Select",color);
8870 (void) XDialogWidget(display,windows,"Add Border",
8871 "Enter border geometry:",geometry);
8872 if (*geometry == '\0')
8875 Add a border to the image.
8877 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image,
8879 XSetCursorState(display,windows,MagickTrue);
8880 XCheckRefreshWindows(display,windows);
8881 (void) QueryColorCompliance(color,AllCompliance,&(*image)->border_color,
8883 (void) ParsePageGeometry(*image,geometry,&page_geometry,
8885 border_image=BorderImage(*image,&page_geometry,(*image)->compose,
8887 if (border_image != (Image *) NULL)
8889 *image=DestroyImage(*image);
8890 *image=border_image;
8892 CatchException(exception);
8893 XSetCursorState(display,windows,MagickFalse);
8894 if (windows->image.orphan != MagickFalse)
8896 windows->image.window_changes.width=(int) (*image)->columns;
8897 windows->image.window_changes.height=(int) (*image)->rows;
8898 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8899 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8902 case AddFrameCommand:
8911 geometry[MaxTextExtent] = "6x6";
8914 Query user for frame color and geometry.
8916 XColorBrowserWidget(display,windows,"Select",color);
8919 (void) XDialogWidget(display,windows,"Add Frame","Enter frame geometry:",
8921 if (*geometry == '\0')
8924 Surround image with an ornamental border.
8926 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image,
8928 XSetCursorState(display,windows,MagickTrue);
8929 XCheckRefreshWindows(display,windows);
8930 (void) QueryColorCompliance(color,AllCompliance,&(*image)->matte_color,
8932 (void) ParsePageGeometry(*image,geometry,&page_geometry,
8934 frame_info.width=page_geometry.width;
8935 frame_info.height=page_geometry.height;
8936 frame_info.outer_bevel=page_geometry.x;
8937 frame_info.inner_bevel=page_geometry.y;
8938 frame_info.x=(ssize_t) frame_info.width;
8939 frame_info.y=(ssize_t) frame_info.height;
8940 frame_info.width=(*image)->columns+2*frame_info.width;
8941 frame_info.height=(*image)->rows+2*frame_info.height;
8942 frame_image=FrameImage(*image,&frame_info,(*image)->compose,exception);
8943 if (frame_image != (Image *) NULL)
8945 *image=DestroyImage(*image);
8948 CatchException(exception);
8949 XSetCursorState(display,windows,MagickFalse);
8950 if (windows->image.orphan != MagickFalse)
8952 windows->image.window_changes.width=(int) (*image)->columns;
8953 windows->image.window_changes.height=(int) (*image)->rows;
8954 XConfigureImageColormap(display,resource_info,windows,*image,exception);
8955 (void) XConfigureImage(display,resource_info,windows,*image,exception);
8958 case CommentCommand:
8972 unique_file=AcquireUniqueFileResource(image_info->filename);
8973 if (unique_file == -1)
8974 XNoticeWidget(display,windows,"Unable to edit image comment",
8975 image_info->filename);
8976 value=GetImageProperty(*image,"comment",exception);
8977 if (value == (char *) NULL)
8978 unique_file=close(unique_file)-1;
8984 file=fdopen(unique_file,"w");
8985 if (file == (FILE *) NULL)
8987 XNoticeWidget(display,windows,"Unable to edit image comment",
8988 image_info->filename);
8991 for (p=value; *p != '\0'; p++)
8992 (void) fputc((int) *p,file);
8993 (void) fputc('\n',file);
8994 (void) fclose(file);
8996 XSetCursorState(display,windows,MagickTrue);
8997 XCheckRefreshWindows(display,windows);
8998 status=InvokeDelegate(image_info,*image,"edit",(char *) NULL,
9000 if (status == MagickFalse)
9001 XNoticeWidget(display,windows,"Unable to edit image comment",
9008 comment=FileToString(image_info->filename,~0UL,exception);
9009 if (comment != (char *) NULL)
9011 (void) SetImageProperty(*image,"comment",comment,exception);
9012 (*image)->taint=MagickTrue;
9015 (void) RelinquishUniqueFileResource(image_info->filename);
9016 XSetCursorState(display,windows,MagickFalse);
9024 XSetCursorState(display,windows,MagickTrue);
9025 XCheckRefreshWindows(display,windows);
9026 (void) AcquireUniqueFilename(filename);
9027 (void) FormatLocaleString((*image)->filename,MaxTextExtent,"launch:%s",
9029 status=WriteImage(image_info,*image,exception);
9030 if (status == MagickFalse)
9031 XNoticeWidget(display,windows,"Unable to launch image editor",
9035 nexus=ReadImage(resource_info->image_info,exception);
9036 CatchException(exception);
9037 XClientMessage(display,windows->image.id,windows->im_protocols,
9038 windows->im_next_image,CurrentTime);
9040 (void) RelinquishUniqueFileResource(filename);
9041 XSetCursorState(display,windows,MagickFalse);
9044 case RegionofInterestCommand:
9047 Apply an image processing technique to a region of interest.
9049 (void) XROIImage(display,resource_info,windows,image,exception);
9059 if (windows->magnify.mapped != MagickFalse)
9060 (void) XRaiseWindow(display,windows->magnify.id);
9066 XSetCursorState(display,windows,MagickTrue);
9067 (void) XMapRaised(display,windows->magnify.id);
9068 XSetCursorState(display,windows,MagickFalse);
9072 case ShowPreviewCommand:
9081 preview_type[MaxTextExtent] = "Gamma";
9084 Select preview type from menu.
9086 previews=GetCommandOptions(MagickPreviewOptions);
9087 if (previews == (char **) NULL)
9089 XListBrowserWidget(display,windows,&windows->widget,
9090 (const char **) previews,"Preview",
9091 "Select an enhancement, effect, or F/X:",preview_type);
9092 previews=DestroyStringList(previews);
9093 if (*preview_type == '\0')
9098 XSetCursorState(display,windows,MagickTrue);
9099 XCheckRefreshWindows(display,windows);
9100 image_info->preview_type=(PreviewType)
9101 ParseCommandOption(MagickPreviewOptions,MagickFalse,preview_type);
9102 image_info->group=(ssize_t) windows->image.id;
9103 (void) DeleteImageProperty(*image,"label");
9104 (void) SetImageProperty(*image,"label","Preview",exception);
9105 (void) AcquireUniqueFilename(filename);
9106 (void) FormatLocaleString((*image)->filename,MaxTextExtent,"preview:%s",
9108 status=WriteImage(image_info,*image,exception);
9109 (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
9110 preview_image=ReadImage(image_info,exception);
9111 (void) RelinquishUniqueFileResource(filename);
9112 if (preview_image == (Image *) NULL)
9114 (void) FormatLocaleString(preview_image->filename,MaxTextExtent,"show:%s",
9116 status=WriteImage(image_info,preview_image,exception);
9117 preview_image=DestroyImage(preview_image);
9118 if (status == MagickFalse)
9119 XNoticeWidget(display,windows,"Unable to show image preview",
9120 (*image)->filename);
9121 XDelay(display,1500);
9122 XSetCursorState(display,windows,MagickFalse);
9125 case ShowHistogramCommand:
9131 Show image histogram.
9133 XSetCursorState(display,windows,MagickTrue);
9134 XCheckRefreshWindows(display,windows);
9135 image_info->group=(ssize_t) windows->image.id;
9136 (void) DeleteImageProperty(*image,"label");
9137 (void) SetImageProperty(*image,"label","Histogram",exception);
9138 (void) AcquireUniqueFilename(filename);
9139 (void) FormatLocaleString((*image)->filename,MaxTextExtent,"histogram:%s",
9141 status=WriteImage(image_info,*image,exception);
9142 (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
9143 histogram_image=ReadImage(image_info,exception);
9144 (void) RelinquishUniqueFileResource(filename);
9145 if (histogram_image == (Image *) NULL)
9147 (void) FormatLocaleString(histogram_image->filename,MaxTextExtent,
9148 "show:%s",filename);
9149 status=WriteImage(image_info,histogram_image,exception);
9150 histogram_image=DestroyImage(histogram_image);
9151 if (status == MagickFalse)
9152 XNoticeWidget(display,windows,"Unable to show histogram",
9153 (*image)->filename);
9154 XDelay(display,1500);
9155 XSetCursorState(display,windows,MagickFalse);
9158 case ShowMatteCommand:
9163 if ((*image)->matte == MagickFalse)
9165 XNoticeWidget(display,windows,
9166 "Image does not have any matte information",(*image)->filename);
9172 XSetCursorState(display,windows,MagickTrue);
9173 XCheckRefreshWindows(display,windows);
9174 image_info->group=(ssize_t) windows->image.id;
9175 (void) DeleteImageProperty(*image,"label");
9176 (void) SetImageProperty(*image,"label","Matte",exception);
9177 (void) AcquireUniqueFilename(filename);
9178 (void) FormatLocaleString((*image)->filename,MaxTextExtent,"matte:%s",
9180 status=WriteImage(image_info,*image,exception);
9181 (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
9182 matte_image=ReadImage(image_info,exception);
9183 (void) RelinquishUniqueFileResource(filename);
9184 if (matte_image == (Image *) NULL)
9186 (void) FormatLocaleString(matte_image->filename,MaxTextExtent,"show:%s",
9188 status=WriteImage(image_info,matte_image,exception);
9189 matte_image=DestroyImage(matte_image);
9190 if (status == MagickFalse)
9191 XNoticeWidget(display,windows,"Unable to show matte",
9192 (*image)->filename);
9193 XDelay(display,1500);
9194 XSetCursorState(display,windows,MagickFalse);
9197 case BackgroundCommand:
9202 status=XBackgroundImage(display,resource_info,windows,image,exception);
9203 if (status == MagickFalse)
9205 nexus=CloneImage(*image,0,0,MagickTrue,exception);
9206 if (nexus != (Image *) NULL)
9207 XClientMessage(display,windows->image.id,windows->im_protocols,
9208 windows->im_next_image,CurrentTime);
9211 case SlideShowCommand:
9214 delay[MaxTextExtent] = "5";
9217 Display next image after pausing.
9219 (void) XDialogWidget(display,windows,"Slide Show",
9220 "Pause how many 1/100ths of a second between images:",delay);
9223 resource_info->delay=StringToUnsignedLong(delay);
9224 XClientMessage(display,windows->image.id,windows->im_protocols,
9225 windows->im_next_image,CurrentTime);
9228 case PreferencesCommand:
9231 Set user preferences.
9233 status=XPreferencesWidget(display,resource_info,windows);
9234 if (status == MagickFalse)
9236 nexus=CloneImage(*image,0,0,MagickTrue,exception);
9237 if (nexus != (Image *) NULL)
9238 XClientMessage(display,windows->image.id,windows->im_protocols,
9239 windows->im_next_image,CurrentTime);
9245 User requested help.
9247 XTextViewWidget(display,resource_info,windows,MagickFalse,
9248 "Help Viewer - Display",DisplayHelp);
9251 case BrowseDocumentationCommand:
9261 Browse the ImageMagick documentation.
9263 root_window=XRootWindow(display,XDefaultScreen(display));
9264 mozilla_atom=XInternAtom(display,"_MOZILLA_VERSION",MagickFalse);
9265 mozilla_window=XWindowByProperty(display,root_window,mozilla_atom);
9266 if (mozilla_window != (Window) NULL)
9269 command[MaxTextExtent],
9273 Display documentation using Netscape remote control.
9275 url=GetMagickHomeURL();
9276 (void) FormatLocaleString(command,MaxTextExtent,
9277 "openurl(%s,new-tab)",url);
9278 url=DestroyString(url);
9279 mozilla_atom=XInternAtom(display,"_MOZILLA_COMMAND",MagickFalse);
9280 (void) XChangeProperty(display,mozilla_window,mozilla_atom,XA_STRING,
9281 8,PropModeReplace,(unsigned char *) command,(int) strlen(command));
9282 XSetCursorState(display,windows,MagickFalse);
9285 XSetCursorState(display,windows,MagickTrue);
9286 XCheckRefreshWindows(display,windows);
9287 status=InvokeDelegate(image_info,*image,"browse",(char *) NULL,
9289 if (status == MagickFalse)
9290 XNoticeWidget(display,windows,"Unable to browse documentation",
9292 XDelay(display,1500);
9293 XSetCursorState(display,windows,MagickFalse);
9296 case VersionCommand:
9298 XNoticeWidget(display,windows,GetMagickVersion((size_t *) NULL),
9299 GetMagickCopyright());
9302 case SaveToUndoBufferCommand:
9306 (void) XBell(display,0);
9310 image_info=DestroyImageInfo(image_info);
9315 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9319 + X M a g n i f y I m a g e %
9323 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9325 % XMagnifyImage() magnifies portions of the image as indicated by the pointer.
9326 % The magnified portion is displayed in a separate window.
9328 % The format of the XMagnifyImage method is:
9330 % void XMagnifyImage(Display *display,XWindows *windows,XEvent *event,
9331 % ExceptionInfo *exception)
9333 % A description of each parameter follows:
9335 % o display: Specifies a connection to an X server; returned from
9338 % o windows: Specifies a pointer to a XWindows structure.
9340 % o event: Specifies a pointer to a XEvent structure. If it is NULL,
9341 % the entire image is refreshed.
9343 % o exception: return any errors or warnings in this structure.
9346 static void XMagnifyImage(Display *display,XWindows *windows,XEvent *event,
9347 ExceptionInfo *exception)
9350 text[MaxTextExtent];
9360 Update magnified image until the mouse button is released.
9362 (void) XCheckDefineCursor(display,windows->image.id,windows->magnify.cursor);
9366 windows->magnify.x=(int) windows->image.x+x;
9367 windows->magnify.y=(int) windows->image.y+y;
9371 Map and unmap Info widget as text cursor crosses its boundaries.
9373 if (windows->info.mapped != MagickFalse)
9375 if ((x < (int) (windows->info.x+windows->info.width)) &&
9376 (y < (int) (windows->info.y+windows->info.height)))
9377 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
9380 if ((x > (int) (windows->info.x+windows->info.width)) ||
9381 (y > (int) (windows->info.y+windows->info.height)))
9382 (void) XMapWindow(display,windows->info.id);
9383 if (windows->info.mapped != MagickFalse)
9386 Display pointer position.
9388 (void) FormatLocaleString(text,MaxTextExtent," %+d%+d ",
9389 windows->magnify.x,windows->magnify.y);
9390 XInfoWidget(display,windows,text);
9393 Wait for next event.
9395 XScreenEvent(display,windows,event,exception);
9396 switch (event->type)
9403 User has finished magnifying image.
9422 Check boundary conditions.
9427 if (x >= (int) windows->image.width)
9428 x=(int) windows->image.width-1;
9432 if (y >= (int) windows->image.height)
9433 y=(int) windows->image.height-1;
9434 } while ((state & ExitState) == 0);
9436 Display magnified image.
9438 XSetCursorState(display,windows,MagickFalse);
9442 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9446 + X M a g n i f y W i n d o w C o m m a n d %
9450 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9452 % XMagnifyWindowCommand() moves the image within an Magnify window by one
9453 % pixel as specified by the key symbol.
9455 % The format of the XMagnifyWindowCommand method is:
9457 % void XMagnifyWindowCommand(Display *display,XWindows *windows,
9458 % const MagickStatusType state,const KeySym key_symbol,
9459 % ExceptionInfo *exception)
9461 % A description of each parameter follows:
9463 % o display: Specifies a connection to an X server; returned from
9466 % o windows: Specifies a pointer to a XWindows structure.
9468 % o state: key mask.
9470 % o key_symbol: Specifies a KeySym which indicates which side of the image
9473 % o exception: return any errors or warnings in this structure.
9476 static void XMagnifyWindowCommand(Display *display,XWindows *windows,
9477 const MagickStatusType state,const KeySym key_symbol,ExceptionInfo *exception)
9483 User specified a magnify factor or position.
9486 if ((state & Mod1Mask) != 0)
9488 switch ((int) key_symbol)
9492 (void) XWithdrawWindow(display,windows->magnify.id,
9493 windows->magnify.screen);
9499 windows->magnify.x=(int) windows->image.width/2;
9500 windows->magnify.y=(int) windows->image.height/2;
9506 if (windows->magnify.x > 0)
9507 windows->magnify.x-=quantum;
9513 if (windows->magnify.y > 0)
9514 windows->magnify.y-=quantum;
9520 if (windows->magnify.x < (int) (windows->image.ximage->width-1))
9521 windows->magnify.x+=quantum;
9527 if (windows->magnify.y < (int) (windows->image.ximage->height-1))
9528 windows->magnify.y+=quantum;
9542 windows->magnify.data=(key_symbol-XK_0);
9556 windows->magnify.data=(key_symbol-XK_KP_0);
9562 XMakeMagnifyImage(display,windows,exception);
9566 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9570 + X M a k e P a n I m a g e %
9574 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9576 % XMakePanImage() creates a thumbnail of the image and displays it in the Pan
9579 % The format of the XMakePanImage method is:
9581 % void XMakePanImage(Display *display,XResourceInfo *resource_info,
9582 % XWindows *windows,Image *image,ExceptionInfo *exception)
9584 % A description of each parameter follows:
9586 % o display: Specifies a connection to an X server; returned from
9589 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
9591 % o windows: Specifies a pointer to a XWindows structure.
9593 % o image: the image.
9595 % o exception: return any errors or warnings in this structure.
9598 static void XMakePanImage(Display *display,XResourceInfo *resource_info,
9599 XWindows *windows,Image *image,ExceptionInfo *exception)
9605 Create and display image for panning icon.
9607 XSetCursorState(display,windows,MagickTrue);
9608 XCheckRefreshWindows(display,windows);
9609 windows->pan.x=(int) windows->image.x;
9610 windows->pan.y=(int) windows->image.y;
9611 status=XMakeImage(display,resource_info,&windows->pan,image,
9612 windows->pan.width,windows->pan.height,exception);
9613 if (status == MagickFalse)
9614 ThrowXWindowFatalException(ResourceLimitError,
9615 "MemoryAllocationFailed",image->filename);
9616 (void) XSetWindowBackgroundPixmap(display,windows->pan.id,
9617 windows->pan.pixmap);
9618 (void) XClearWindow(display,windows->pan.id);
9619 XDrawPanRectangle(display,windows);
9620 XSetCursorState(display,windows,MagickFalse);
9624 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9628 + X M a t t a E d i t I m a g e %
9632 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9634 % XMatteEditImage() allows the user to interactively change the Matte channel
9635 % of an image. If the image is PseudoClass it is promoted to DirectClass
9636 % before the matte information is stored.
9638 % The format of the XMatteEditImage method is:
9640 % MagickBooleanType XMatteEditImage(Display *display,
9641 % XResourceInfo *resource_info,XWindows *windows,Image **image,
9642 % ExceptionInfo *exception)
9644 % A description of each parameter follows:
9646 % o display: Specifies a connection to an X server; returned from
9649 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
9651 % o windows: Specifies a pointer to a XWindows structure.
9653 % o image: the image; returned from ReadImage.
9655 % o exception: return any errors or warnings in this structure.
9658 static MagickBooleanType XMatteEditImage(Display *display,
9659 XResourceInfo *resource_info,XWindows *windows,Image **image,
9660 ExceptionInfo *exception)
9663 matte[MaxTextExtent] = "0";
9678 static const ModeType
9679 MatteEditCommands[] =
9682 MatteEditBorderCommand,
9683 MatteEditFuzzCommand,
9684 MatteEditValueCommand,
9685 MatteEditUndoCommand,
9686 MatteEditHelpCommand,
9687 MatteEditDismissCommand
9691 method = PointMethod;
9694 border_color = { 0, 0, 0, 0, 0, 0 };
9697 command[MaxTextExtent],
9698 text[MaxTextExtent];
9730 (void) CloneString(&windows->command.name,"Matte Edit");
9731 windows->command.data=4;
9732 (void) XCommandWidget(display,windows,MatteEditMenu,(XEvent *) NULL);
9733 (void) XMapRaised(display,windows->command.id);
9734 XClientMessage(display,windows->image.id,windows->im_protocols,
9735 windows->im_update_widget,CurrentTime);
9739 cursor=XMakeCursor(display,windows->image.id,windows->map_info->colormap,
9740 resource_info->background_color,resource_info->foreground_color);
9741 (void) XCheckDefineCursor(display,windows->image.id,cursor);
9743 Track pointer until button 1 is pressed.
9745 XQueryPosition(display,windows->image.id,&x,&y);
9746 (void) XSelectInput(display,windows->image.id,
9747 windows->image.attributes.event_mask | PointerMotionMask);
9751 if (windows->info.mapped != MagickFalse)
9754 Display pointer position.
9756 (void) FormatLocaleString(text,MaxTextExtent," %+d%+d ",
9757 x+windows->image.x,y+windows->image.y);
9758 XInfoWidget(display,windows,text);
9761 Wait for next event.
9763 XScreenEvent(display,windows,&event,exception);
9764 if (event.xany.window == windows->command.id)
9767 Select a command from the Command widget.
9769 id=XCommandWidget(display,windows,MatteEditMenu,&event);
9772 (void) XCheckDefineCursor(display,windows->image.id,cursor);
9775 switch (MatteEditCommands[id])
9777 case MatteEditMethod:
9783 Select a method from the pop-up menu.
9785 methods=GetCommandOptions(MagickMethodOptions);
9786 if (methods == (char **) NULL)
9788 entry=XMenuWidget(display,windows,MatteEditMenu[id],
9789 (const char **) methods,command);
9791 method=(PaintMethod) ParseCommandOption(MagickMethodOptions,
9792 MagickFalse,methods[entry]);
9793 methods=DestroyStringList(methods);
9796 case MatteEditBorderCommand:
9799 *ColorMenu[MaxNumberPens];
9805 Initialize menu selections.
9807 for (i=0; i < (int) (MaxNumberPens-2); i++)
9808 ColorMenu[i]=resource_info->pen_colors[i];
9809 ColorMenu[MaxNumberPens-2]="Browser...";
9810 ColorMenu[MaxNumberPens-1]=(const char *) NULL;
9812 Select a pen color from the pop-up menu.
9814 pen_number=XMenuWidget(display,windows,MatteEditMenu[id],
9815 (const char **) ColorMenu,command);
9818 if (pen_number == (MaxNumberPens-2))
9821 color_name[MaxTextExtent] = "gray";
9824 Select a pen color from a dialog.
9826 resource_info->pen_colors[pen_number]=color_name;
9827 XColorBrowserWidget(display,windows,"Select",color_name);
9828 if (*color_name == '\0')
9834 (void) XParseColor(display,windows->map_info->colormap,
9835 resource_info->pen_colors[pen_number],&border_color);
9838 case MatteEditFuzzCommand:
9841 fuzz[MaxTextExtent];
9856 Select a command from the pop-up menu.
9858 entry=XMenuWidget(display,windows,MatteEditMenu[id],FuzzMenu,
9864 (*image)->fuzz=StringToDoubleInterval(FuzzMenu[entry],(double)
9868 (void) CopyMagickString(fuzz,"20%",MaxTextExtent);
9869 (void) XDialogWidget(display,windows,"Ok",
9870 "Enter fuzz factor (0.0 - 99.9%):",fuzz);
9873 (void) ConcatenateMagickString(fuzz,"%",MaxTextExtent);
9874 (*image)->fuzz=StringToDoubleInterval(fuzz,(double) QuantumRange+
9878 case MatteEditValueCommand:
9881 message[MaxTextExtent];
9893 Select a command from the pop-up menu.
9895 entry=XMenuWidget(display,windows,MatteEditMenu[id],MatteMenu,
9901 (void) FormatLocaleString(matte,MaxTextExtent,QuantumFormat,
9903 if (LocaleCompare(MatteMenu[entry],"Transparent") == 0)
9904 (void) FormatLocaleString(matte,MaxTextExtent,QuantumFormat,
9905 (Quantum) TransparentAlpha);
9908 (void) FormatLocaleString(message,MaxTextExtent,
9909 "Enter matte value (0 - " QuantumFormat "):",(Quantum)
9911 (void) XDialogWidget(display,windows,"Matte",message,matte);
9916 case MatteEditUndoCommand:
9918 (void) XMagickCommand(display,resource_info,windows,UndoCommand,
9922 case MatteEditHelpCommand:
9924 XTextViewWidget(display,resource_info,windows,MagickFalse,
9925 "Help Viewer - Matte Edit",ImageMatteEditHelp);
9928 case MatteEditDismissCommand:
9940 (void) XCheckDefineCursor(display,windows->image.id,cursor);
9947 if (event.xbutton.button != Button1)
9949 if ((event.xbutton.window != windows->image.id) &&
9950 (event.xbutton.window != windows->magnify.id))
9957 (void) XMagickCommand(display,resource_info,windows,
9958 SaveToUndoBufferCommand,image,exception);
9959 state|=UpdateConfigurationState;
9964 if (event.xbutton.button != Button1)
9966 if ((event.xbutton.window != windows->image.id) &&
9967 (event.xbutton.window != windows->magnify.id))
9970 Update colormap information.
9974 XConfigureImageColormap(display,resource_info,windows,*image,exception);
9975 (void) XConfigureImage(display,resource_info,windows,*image,exception);
9976 XInfoWidget(display,windows,text);
9977 (void) XCheckDefineCursor(display,windows->image.id,cursor);
9978 state&=(~UpdateConfigurationState);
9986 command[MaxTextExtent];
9991 if (event.xkey.window == windows->magnify.id)
9996 window=windows->magnify.id;
9997 while (XCheckWindowEvent(display,window,KeyPressMask,&event)) ;
9999 if (event.xkey.window != windows->image.id)
10002 Respond to a user key press.
10004 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
10005 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
10006 switch ((int) key_symbol)
10020 XTextViewWidget(display,resource_info,windows,MagickFalse,
10021 "Help Viewer - Matte Edit",ImageMatteEditHelp);
10026 (void) XBell(display,0);
10035 Map and unmap Info widget as cursor crosses its boundaries.
10039 if (windows->info.mapped != MagickFalse)
10041 if ((x < (int) (windows->info.x+windows->info.width)) &&
10042 (y < (int) (windows->info.y+windows->info.height)))
10043 (void) XWithdrawWindow(display,windows->info.id,
10044 windows->info.screen);
10047 if ((x > (int) (windows->info.x+windows->info.width)) ||
10048 (y > (int) (windows->info.y+windows->info.height)))
10049 (void) XMapWindow(display,windows->info.id);
10055 if (event.xany.window == windows->magnify.id)
10057 x=windows->magnify.x-windows->image.x;
10058 y=windows->magnify.y-windows->image.y;
10062 if ((state & UpdateConfigurationState) != 0)
10072 Matte edit is relative to image configuration.
10074 (void) XClearArea(display,windows->image.id,x_offset,y_offset,1,1,
10076 XPutPixel(windows->image.ximage,x_offset,y_offset,
10077 windows->pixel_info->background_color.pixel);
10078 width=(unsigned int) (*image)->columns;
10079 height=(unsigned int) (*image)->rows;
10082 if (windows->image.crop_geometry != (char *) NULL)
10083 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,
10085 x_offset=(int) (width*(windows->image.x+x_offset)/
10086 windows->image.ximage->width+x);
10087 y_offset=(int) (height*(windows->image.y+y_offset)/
10088 windows->image.ximage->height+y);
10089 if ((x_offset < 0) || (y_offset < 0))
10091 if ((x_offset >= (int) (*image)->columns) ||
10092 (y_offset >= (int) (*image)->rows))
10094 if (SetImageStorageClass(*image,DirectClass,exception) == MagickFalse)
10095 return(MagickFalse);
10096 if ((*image)->matte == MagickFalse)
10097 (void) SetImageAlphaChannel(*image,OpaqueAlphaChannel,exception);
10098 image_view=AcquireAuthenticCacheView(*image,exception);
10105 Update matte information using point algorithm.
10107 q=GetCacheViewAuthenticPixels(image_view,(ssize_t) x_offset,
10108 (ssize_t) y_offset,1,1,exception);
10109 if (q == (Quantum *) NULL)
10111 SetPixelAlpha(*image,(Quantum) StringToLong(matte),q);
10112 (void) SyncCacheViewAuthenticPixels(image_view,exception);
10115 case ReplaceMethod:
10122 Update matte information using replace algorithm.
10124 (void) GetOneCacheViewVirtualPixelInfo(image_view,(ssize_t)
10125 x_offset,(ssize_t) y_offset,&target,exception);
10126 for (y=0; y < (int) (*image)->rows; y++)
10128 q=GetCacheViewAuthenticPixels(image_view,0,(ssize_t) y,
10129 (*image)->columns,1,exception);
10130 if (q == (Quantum *) NULL)
10132 for (x=0; x < (int) (*image)->columns; x++)
10134 GetPixelInfoPixel(*image,q,&pixel);
10135 if (IsFuzzyEquivalencePixelInfo(&pixel,&target))
10136 SetPixelAlpha(*image,(Quantum) StringToLong(matte),q);
10137 q+=GetPixelChannels(*image);
10139 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
10144 case FloodfillMethod:
10145 case FillToBorderMethod:
10157 Update matte information using floodfill algorithm.
10159 (void) GetOneVirtualPixelInfo(*image,
10160 GetPixelCacheVirtualMethod(*image),(ssize_t) x_offset,(ssize_t)
10161 y_offset,&target,exception);
10162 if (method == FillToBorderMethod)
10164 target.red=(double) ScaleShortToQuantum(
10166 target.green=(double) ScaleShortToQuantum(
10167 border_color.green);
10168 target.blue=(double) ScaleShortToQuantum(
10169 border_color.blue);
10171 draw_info=CloneDrawInfo(resource_info->image_info,
10172 (DrawInfo *) NULL);
10173 draw_info->fill.alpha=(double) ClampToQuantum(
10174 StringToDouble(matte,(char **) NULL));
10175 channel_mask=SetPixelChannelMask(*image,AlphaChannel);
10176 (void) FloodfillPaintImage(*image,draw_info,&target,(ssize_t)
10177 x_offset,(ssize_t) y_offset,method == FloodfillMethod ?
10178 MagickFalse : MagickTrue,exception);
10179 (void) SetPixelChannelMapMask(*image,channel_mask);
10180 draw_info=DestroyDrawInfo(draw_info);
10186 Update matte information using reset algorithm.
10188 if (SetImageStorageClass(*image,DirectClass,exception) == MagickFalse)
10189 return(MagickFalse);
10190 for (y=0; y < (int) (*image)->rows; y++)
10192 q=QueueCacheViewAuthenticPixels(image_view,0,(ssize_t) y,
10193 (*image)->columns,1,exception);
10194 if (q == (Quantum *) NULL)
10196 for (x=0; x < (int) (*image)->columns; x++)
10198 SetPixelAlpha(*image,(Quantum) StringToLong(matte),q);
10199 q+=GetPixelChannels(*image);
10201 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
10204 if (StringToLong(matte) == (long) OpaqueAlpha)
10205 (*image)->matte=MagickFalse;
10209 image_view=DestroyCacheView(image_view);
10210 state&=(~UpdateConfigurationState);
10212 } while ((state & ExitState) == 0);
10213 (void) XSelectInput(display,windows->image.id,
10214 windows->image.attributes.event_mask);
10215 XSetCursorState(display,windows,MagickFalse);
10216 (void) XFreeCursor(display,cursor);
10217 return(MagickTrue);
10221 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10225 + X O p e n I m a g e %
10229 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10231 % XOpenImage() loads an image from a file.
10233 % The format of the XOpenImage method is:
10235 % Image *XOpenImage(Display *display,XResourceInfo *resource_info,
10236 % XWindows *windows,const unsigned int command)
10238 % A description of each parameter follows:
10240 % o display: Specifies a connection to an X server; returned from
10243 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
10245 % o windows: Specifies a pointer to a XWindows structure.
10247 % o command: A value other than zero indicates that the file is selected
10248 % from the command line argument list.
10251 static Image *XOpenImage(Display *display,XResourceInfo *resource_info,
10252 XWindows *windows,const MagickBooleanType command)
10267 filename[MaxTextExtent] = "\0";
10270 Request file name from user.
10272 if (command == MagickFalse)
10273 XFileBrowserWidget(display,windows,"Open",filename);
10289 Select next image from the command line.
10291 status=XGetCommand(display,windows->image.id,&files,&count);
10294 ThrowXWindowFatalException(XServerError,"UnableToGetProperty","...");
10295 return((Image *) NULL);
10297 filelist=(char **) AcquireQuantumMemory((size_t) count,sizeof(*filelist));
10298 if (filelist == (char **) NULL)
10300 ThrowXWindowFatalException(ResourceLimitError,
10301 "MemoryAllocationFailed","...");
10302 (void) XFreeStringList(files);
10303 return((Image *) NULL);
10306 for (i=1; i < count; i++)
10307 if (*files[i] != '-')
10308 filelist[j++]=files[i];
10309 filelist[j]=(char *) NULL;
10310 XListBrowserWidget(display,windows,&windows->widget,
10311 (const char **) filelist,"Load","Select Image to Load:",filename);
10312 filelist=(char **) RelinquishMagickMemory(filelist);
10313 (void) XFreeStringList(files);
10315 if (*filename == '\0')
10316 return((Image *) NULL);
10317 image_info=CloneImageInfo(resource_info->image_info);
10318 (void) SetImageInfoProgressMonitor(image_info,(MagickProgressMonitor) NULL,
10320 (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
10321 exception=AcquireExceptionInfo();
10322 (void) SetImageInfo(image_info,0,exception);
10323 if (LocaleCompare(image_info->magick,"X") == 0)
10326 seconds[MaxTextExtent];
10329 User may want to delay the X server screen grab.
10331 (void) CopyMagickString(seconds,"0",MaxTextExtent);
10332 (void) XDialogWidget(display,windows,"Grab","Enter any delay in seconds:",
10334 if (*seconds == '\0')
10335 return((Image *) NULL);
10336 XDelay(display,(size_t) (1000*StringToLong(seconds)));
10338 magick_info=GetMagickInfo(image_info->magick,exception);
10339 if ((magick_info != (const MagickInfo *) NULL) &&
10340 (magick_info->raw != MagickFalse))
10343 geometry[MaxTextExtent];
10346 Request image size from the user.
10348 (void) CopyMagickString(geometry,"512x512",MaxTextExtent);
10349 if (image_info->size != (char *) NULL)
10350 (void) CopyMagickString(geometry,image_info->size,MaxTextExtent);
10351 (void) XDialogWidget(display,windows,"Load","Enter the image geometry:",
10353 (void) CloneString(&image_info->size,geometry);
10358 XSetCursorState(display,windows,MagickTrue);
10359 XCheckRefreshWindows(display,windows);
10360 (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
10361 nexus=ReadImage(image_info,exception);
10362 CatchException(exception);
10363 XSetCursorState(display,windows,MagickFalse);
10364 if (nexus != (Image *) NULL)
10365 XClientMessage(display,windows->image.id,windows->im_protocols,
10366 windows->im_next_image,CurrentTime);
10374 Unknown image format.
10376 text=FileToString(filename,~0,exception);
10377 if (text == (char *) NULL)
10378 return((Image *) NULL);
10379 textlist=StringToList(text);
10380 if (textlist != (char **) NULL)
10383 title[MaxTextExtent];
10388 (void) FormatLocaleString(title,MaxTextExtent,
10389 "Unknown format: %s",filename);
10390 XTextViewWidget(display,resource_info,windows,MagickTrue,title,
10391 (const char **) textlist);
10392 for (i=0; textlist[i] != (char *) NULL; i++)
10393 textlist[i]=DestroyString(textlist[i]);
10394 textlist=(char **) RelinquishMagickMemory(textlist);
10396 text=DestroyString(text);
10398 exception=DestroyExceptionInfo(exception);
10399 image_info=DestroyImageInfo(image_info);
10404 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10408 + X P a n I m a g e %
10412 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10414 % XPanImage() pans the image until the mouse button is released.
10416 % The format of the XPanImage method is:
10418 % void XPanImage(Display *display,XWindows *windows,XEvent *event,
10419 % ExceptionInfo *exception)
10421 % A description of each parameter follows:
10423 % o display: Specifies a connection to an X server; returned from
10426 % o windows: Specifies a pointer to a XWindows structure.
10428 % o event: Specifies a pointer to a XEvent structure. If it is NULL,
10429 % the entire image is refreshed.
10431 % o exception: return any errors or warnings in this structure.
10434 static void XPanImage(Display *display,XWindows *windows,XEvent *event,
10435 ExceptionInfo *exception)
10438 text[MaxTextExtent];
10456 if ((windows->image.ximage->width > (int) windows->image.width) &&
10457 (windows->image.ximage->height > (int) windows->image.height))
10458 cursor=XCreateFontCursor(display,XC_fleur);
10460 if (windows->image.ximage->width > (int) windows->image.width)
10461 cursor=XCreateFontCursor(display,XC_sb_h_double_arrow);
10463 if (windows->image.ximage->height > (int) windows->image.height)
10464 cursor=XCreateFontCursor(display,XC_sb_v_double_arrow);
10466 cursor=XCreateFontCursor(display,XC_arrow);
10467 (void) XCheckDefineCursor(display,windows->pan.id,cursor);
10469 Pan image as pointer moves until the mouse button is released.
10471 x_factor=(double) windows->image.ximage->width/windows->pan.width;
10472 y_factor=(double) windows->image.ximage->height/windows->pan.height;
10473 pan_info.width=windows->pan.width*windows->image.width/
10474 windows->image.ximage->width;
10475 pan_info.height=windows->pan.height*windows->image.height/
10476 windows->image.ximage->height;
10479 state=UpdateConfigurationState;
10482 switch (event->type)
10487 User choose an initial pan location.
10489 pan_info.x=(ssize_t) event->xbutton.x;
10490 pan_info.y=(ssize_t) event->xbutton.y;
10491 state|=UpdateConfigurationState;
10494 case ButtonRelease:
10497 User has finished panning the image.
10499 pan_info.x=(ssize_t) event->xbutton.x;
10500 pan_info.y=(ssize_t) event->xbutton.y;
10501 state|=UpdateConfigurationState | ExitState;
10506 pan_info.x=(ssize_t) event->xmotion.x;
10507 pan_info.y=(ssize_t) event->xmotion.y;
10508 state|=UpdateConfigurationState;
10513 if ((state & UpdateConfigurationState) != 0)
10516 Check boundary conditions.
10518 if (pan_info.x < (ssize_t) (pan_info.width/2))
10521 pan_info.x=(ssize_t) (x_factor*(pan_info.x-(pan_info.width/2)));
10522 if (pan_info.x < 0)
10525 if ((int) (pan_info.x+windows->image.width) >
10526 windows->image.ximage->width)
10527 pan_info.x=(ssize_t)
10528 (windows->image.ximage->width-windows->image.width);
10529 if (pan_info.y < (ssize_t) (pan_info.height/2))
10532 pan_info.y=(ssize_t) (y_factor*(pan_info.y-(pan_info.height/2)));
10533 if (pan_info.y < 0)
10536 if ((int) (pan_info.y+windows->image.height) >
10537 windows->image.ximage->height)
10538 pan_info.y=(ssize_t)
10539 (windows->image.ximage->height-windows->image.height);
10540 if ((windows->image.x != (int) pan_info.x) ||
10541 (windows->image.y != (int) pan_info.y))
10544 Display image pan offset.
10546 windows->image.x=(int) pan_info.x;
10547 windows->image.y=(int) pan_info.y;
10548 (void) FormatLocaleString(text,MaxTextExtent," %ux%u%+d%+d ",
10549 windows->image.width,windows->image.height,windows->image.x,
10551 XInfoWidget(display,windows,text);
10553 Refresh Image window.
10555 XDrawPanRectangle(display,windows);
10556 XRefreshWindow(display,&windows->image,(XEvent *) NULL);
10558 state&=(~UpdateConfigurationState);
10561 Wait for next event.
10563 if ((state & ExitState) == 0)
10564 XScreenEvent(display,windows,event,exception);
10565 } while ((state & ExitState) == 0);
10569 (void) XCheckDefineCursor(display,windows->pan.id,windows->pan.cursor);
10570 (void) XFreeCursor(display,cursor);
10571 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
10575 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10579 + X P a s t e I m a g e %
10583 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10585 % XPasteImage() pastes an image previously saved with XCropImage in the X
10586 % window image at a location the user chooses with the pointer.
10588 % The format of the XPasteImage method is:
10590 % MagickBooleanType XPasteImage(Display *display,
10591 % XResourceInfo *resource_info,XWindows *windows,Image *image,
10592 % ExceptionInfo *exception)
10594 % A description of each parameter follows:
10596 % o display: Specifies a connection to an X server; returned from
10599 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
10601 % o windows: Specifies a pointer to a XWindows structure.
10603 % o image: the image; returned from ReadImage.
10605 % o exception: return any errors or warnings in this structure.
10608 static MagickBooleanType XPasteImage(Display *display,
10609 XResourceInfo *resource_info,XWindows *windows,Image *image,
10610 ExceptionInfo *exception)
10621 static const ModeType
10624 PasteOperatorsCommand,
10626 PasteDismissCommand
10629 static CompositeOperator
10630 compose = CopyCompositeOp;
10633 text[MaxTextExtent];
10667 if (resource_info->copy_image == (Image *) NULL)
10668 return(MagickFalse);
10669 paste_image=CloneImage(resource_info->copy_image,0,0,MagickTrue,exception);
10671 Map Command widget.
10673 (void) CloneString(&windows->command.name,"Paste");
10674 windows->command.data=1;
10675 (void) XCommandWidget(display,windows,PasteMenu,(XEvent *) NULL);
10676 (void) XMapRaised(display,windows->command.id);
10677 XClientMessage(display,windows->image.id,windows->im_protocols,
10678 windows->im_update_widget,CurrentTime);
10680 Track pointer until button 1 is pressed.
10682 XSetCursorState(display,windows,MagickFalse);
10683 XQueryPosition(display,windows->image.id,&x,&y);
10684 (void) XSelectInput(display,windows->image.id,
10685 windows->image.attributes.event_mask | PointerMotionMask);
10686 paste_info.x=(ssize_t) windows->image.x+x;
10687 paste_info.y=(ssize_t) windows->image.y+y;
10688 paste_info.width=0;
10689 paste_info.height=0;
10690 cursor=XCreateFontCursor(display,XC_ul_angle);
10691 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
10692 state=DefaultState;
10695 if (windows->info.mapped != MagickFalse)
10698 Display pointer position.
10700 (void) FormatLocaleString(text,MaxTextExtent," %+ld%+ld ",
10701 (long) paste_info.x,(long) paste_info.y);
10702 XInfoWidget(display,windows,text);
10704 highlight_info=paste_info;
10705 highlight_info.x=paste_info.x-windows->image.x;
10706 highlight_info.y=paste_info.y-windows->image.y;
10707 XHighlightRectangle(display,windows->image.id,
10708 windows->image.highlight_context,&highlight_info);
10710 Wait for next event.
10712 XScreenEvent(display,windows,&event,exception);
10713 XHighlightRectangle(display,windows->image.id,
10714 windows->image.highlight_context,&highlight_info);
10715 if (event.xany.window == windows->command.id)
10718 Select a command from the Command widget.
10720 id=XCommandWidget(display,windows,PasteMenu,&event);
10723 switch (PasteCommands[id])
10725 case PasteOperatorsCommand:
10728 command[MaxTextExtent],
10732 Select a command from the pop-up menu.
10734 operators=GetCommandOptions(MagickComposeOptions);
10735 if (operators == (char **) NULL)
10737 entry=XMenuWidget(display,windows,PasteMenu[id],
10738 (const char **) operators,command);
10740 compose=(CompositeOperator) ParseCommandOption(
10741 MagickComposeOptions,MagickFalse,operators[entry]);
10742 operators=DestroyStringList(operators);
10745 case PasteHelpCommand:
10747 XTextViewWidget(display,resource_info,windows,MagickFalse,
10748 "Help Viewer - Image Composite",ImagePasteHelp);
10751 case PasteDismissCommand:
10756 state|=EscapeState;
10765 switch (event.type)
10769 if (image->debug != MagickFalse)
10770 (void) LogMagickEvent(X11Event,GetMagickModule(),
10771 "Button Press: 0x%lx %u +%d+%d",event.xbutton.window,
10772 event.xbutton.button,event.xbutton.x,event.xbutton.y);
10773 if (event.xbutton.button != Button1)
10775 if (event.xbutton.window != windows->image.id)
10778 Paste rectangle is relative to image configuration.
10780 width=(unsigned int) image->columns;
10781 height=(unsigned int) image->rows;
10784 if (windows->image.crop_geometry != (char *) NULL)
10785 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,
10787 scale_factor=(double) windows->image.ximage->width/width;
10788 paste_info.width=(unsigned int) (scale_factor*paste_image->columns+0.5);
10789 scale_factor=(double) windows->image.ximage->height/height;
10790 paste_info.height=(unsigned int) (scale_factor*paste_image->rows+0.5);
10791 (void) XCheckDefineCursor(display,windows->image.id,cursor);
10792 paste_info.x=(ssize_t) windows->image.x+event.xbutton.x;
10793 paste_info.y=(ssize_t) windows->image.y+event.xbutton.y;
10796 case ButtonRelease:
10798 if (image->debug != MagickFalse)
10799 (void) LogMagickEvent(X11Event,GetMagickModule(),
10800 "Button Release: 0x%lx %u +%d+%d",event.xbutton.window,
10801 event.xbutton.button,event.xbutton.x,event.xbutton.y);
10802 if (event.xbutton.button != Button1)
10804 if (event.xbutton.window != windows->image.id)
10806 if ((paste_info.width != 0) && (paste_info.height != 0))
10809 User has selected the location of the paste image.
10811 paste_info.x=(ssize_t) windows->image.x+event.xbutton.x;
10812 paste_info.y=(ssize_t) windows->image.y+event.xbutton.y;
10822 command[MaxTextExtent];
10830 if (event.xkey.window != windows->image.id)
10833 Respond to a user key press.
10835 length=XLookupString((XKeyEvent *) &event.xkey,command,(int)
10836 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
10837 *(command+length)='\0';
10838 if (image->debug != MagickFalse)
10839 (void) LogMagickEvent(X11Event,GetMagickModule(),
10840 "Key press: 0x%lx (%s)",(long) key_symbol,command);
10841 switch ((int) key_symbol)
10849 paste_image=DestroyImage(paste_image);
10850 state|=EscapeState;
10857 (void) XSetFunction(display,windows->image.highlight_context,
10859 XTextViewWidget(display,resource_info,windows,MagickFalse,
10860 "Help Viewer - Image Composite",ImagePasteHelp);
10861 (void) XSetFunction(display,windows->image.highlight_context,
10867 (void) XBell(display,0);
10876 Map and unmap Info widget as text cursor crosses its boundaries.
10880 if (windows->info.mapped != MagickFalse)
10882 if ((x < (int) (windows->info.x+windows->info.width)) &&
10883 (y < (int) (windows->info.y+windows->info.height)))
10884 (void) XWithdrawWindow(display,windows->info.id,
10885 windows->info.screen);
10888 if ((x > (int) (windows->info.x+windows->info.width)) ||
10889 (y > (int) (windows->info.y+windows->info.height)))
10890 (void) XMapWindow(display,windows->info.id);
10891 paste_info.x=(ssize_t) windows->image.x+x;
10892 paste_info.y=(ssize_t) windows->image.y+y;
10897 if (image->debug != MagickFalse)
10898 (void) LogMagickEvent(X11Event,GetMagickModule(),"Event type: %d",
10903 } while ((state & ExitState) == 0);
10904 (void) XSelectInput(display,windows->image.id,
10905 windows->image.attributes.event_mask);
10906 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
10907 XSetCursorState(display,windows,MagickFalse);
10908 (void) XFreeCursor(display,cursor);
10909 if ((state & EscapeState) != 0)
10910 return(MagickTrue);
10912 Image pasting is relative to image configuration.
10914 XSetCursorState(display,windows,MagickTrue);
10915 XCheckRefreshWindows(display,windows);
10916 width=(unsigned int) image->columns;
10917 height=(unsigned int) image->rows;
10920 if (windows->image.crop_geometry != (char *) NULL)
10921 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
10922 scale_factor=(double) width/windows->image.ximage->width;
10924 paste_info.x=(ssize_t) (scale_factor*paste_info.x+0.5);
10925 paste_info.width=(unsigned int) (scale_factor*paste_info.width+0.5);
10926 scale_factor=(double) height/windows->image.ximage->height;
10928 paste_info.y=(ssize_t) (scale_factor*paste_info.y*scale_factor+0.5);
10929 paste_info.height=(unsigned int) (scale_factor*paste_info.height+0.5);
10931 Paste image with X Image window.
10933 (void) CompositeImage(image,paste_image,compose,MagickTrue,paste_info.x,
10934 paste_info.y,exception);
10935 paste_image=DestroyImage(paste_image);
10936 XSetCursorState(display,windows,MagickFalse);
10938 Update image colormap.
10940 XConfigureImageColormap(display,resource_info,windows,image,exception);
10941 (void) XConfigureImage(display,resource_info,windows,image,exception);
10942 return(MagickTrue);
10946 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10950 + X P r i n t I m a g e %
10954 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10956 % XPrintImage() prints an image to a Postscript printer.
10958 % The format of the XPrintImage method is:
10960 % MagickBooleanType XPrintImage(Display *display,
10961 % XResourceInfo *resource_info,XWindows *windows,Image *image,
10962 % ExceptionInfo *exception)
10964 % A description of each parameter follows:
10966 % o display: Specifies a connection to an X server; returned from
10969 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
10971 % o windows: Specifies a pointer to a XWindows structure.
10973 % o image: the image.
10975 % o exception: return any errors or warnings in this structure.
10978 static MagickBooleanType XPrintImage(Display *display,
10979 XResourceInfo *resource_info,XWindows *windows,Image *image,
10980 ExceptionInfo *exception)
10983 filename[MaxTextExtent],
10984 geometry[MaxTextExtent];
10996 Request Postscript page geometry from user.
10998 image_info=CloneImageInfo(resource_info->image_info);
10999 (void) FormatLocaleString(geometry,MaxTextExtent,"Letter");
11000 if (image_info->page != (char *) NULL)
11001 (void) CopyMagickString(geometry,image_info->page,MaxTextExtent);
11002 XListBrowserWidget(display,windows,&windows->widget,PageSizes,"Select",
11003 "Select Postscript Page Geometry:",geometry);
11004 if (*geometry == '\0')
11005 return(MagickTrue);
11006 image_info->page=GetPageGeometry(geometry);
11008 Apply image transforms.
11010 XSetCursorState(display,windows,MagickTrue);
11011 XCheckRefreshWindows(display,windows);
11012 print_image=CloneImage(image,0,0,MagickTrue,exception);
11013 if (print_image == (Image *) NULL)
11014 return(MagickFalse);
11015 (void) FormatLocaleString(geometry,MaxTextExtent,"%dx%d!",
11016 windows->image.ximage->width,windows->image.ximage->height);
11017 (void) TransformImage(&print_image,windows->image.crop_geometry,geometry,
11022 (void) AcquireUniqueFilename(filename);
11023 (void) FormatLocaleString(print_image->filename,MaxTextExtent,"print:%s",
11025 status=WriteImage(image_info,print_image,exception);
11026 (void) RelinquishUniqueFileResource(filename);
11027 print_image=DestroyImage(print_image);
11028 image_info=DestroyImageInfo(image_info);
11029 XSetCursorState(display,windows,MagickFalse);
11030 return(status != 0 ? MagickTrue : MagickFalse);
11034 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
11038 + X R O I I m a g e %
11042 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
11044 % XROIImage() applies an image processing technique to a region of interest.
11046 % The format of the XROIImage method is:
11048 % MagickBooleanType XROIImage(Display *display,
11049 % XResourceInfo *resource_info,XWindows *windows,Image **image,
11050 % ExceptionInfo *exception)
11052 % A description of each parameter follows:
11054 % o display: Specifies a connection to an X server; returned from
11057 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
11059 % o windows: Specifies a pointer to a XWindows structure.
11061 % o image: the image; returned from ReadImage.
11063 % o exception: return any errors or warnings in this structure.
11066 static MagickBooleanType XROIImage(Display *display,
11067 XResourceInfo *resource_info,XWindows *windows,Image **image,
11068 ExceptionInfo *exception)
11070 #define ApplyMenus 7
11120 "Contrast Stretch...",
11121 "Sigmoidal Contrast...",
11155 "Charcoal Draw...",
11158 *MiscellanyMenu[] =
11169 **Menus[ApplyMenus] =
11180 static const CommandType
11203 TransformCommands[] =
11207 RotateRightCommand,
11210 EnhanceCommands[] =
11218 ContrastStretchCommand,
11219 SigmoidalContrastCommand,
11227 EffectsCommands[] =
11231 ReduceNoiseCommand,
11250 CharcoalDrawCommand
11252 MiscellanyCommands[] =
11256 ShowPreviewCommand,
11257 ShowHistogramCommand,
11266 static const CommandType
11267 *Commands[ApplyMenus] =
11279 command[MaxTextExtent],
11280 text[MaxTextExtent];
11300 MagickProgressMonitor
11319 Map Command widget.
11321 (void) CloneString(&windows->command.name,"ROI");
11322 windows->command.data=0;
11323 (void) XCommandWidget(display,windows,ROIMenu,(XEvent *) NULL);
11324 (void) XMapRaised(display,windows->command.id);
11325 XClientMessage(display,windows->image.id,windows->im_protocols,
11326 windows->im_update_widget,CurrentTime);
11328 Track pointer until button 1 is pressed.
11330 XQueryPosition(display,windows->image.id,&x,&y);
11331 (void) XSelectInput(display,windows->image.id,
11332 windows->image.attributes.event_mask | PointerMotionMask);
11333 roi_info.x=(ssize_t) windows->image.x+x;
11334 roi_info.y=(ssize_t) windows->image.y+y;
11337 cursor=XCreateFontCursor(display,XC_fleur);
11338 state=DefaultState;
11341 if (windows->info.mapped != MagickFalse)
11344 Display pointer position.
11346 (void) FormatLocaleString(text,MaxTextExtent," %+ld%+ld ",
11347 (long) roi_info.x,(long) roi_info.y);
11348 XInfoWidget(display,windows,text);
11351 Wait for next event.
11353 XScreenEvent(display,windows,&event,exception);
11354 if (event.xany.window == windows->command.id)
11357 Select a command from the Command widget.
11359 id=XCommandWidget(display,windows,ROIMenu,&event);
11362 switch (ROICommands[id])
11364 case ROIHelpCommand:
11366 XTextViewWidget(display,resource_info,windows,MagickFalse,
11367 "Help Viewer - Region of Interest",ImageROIHelp);
11370 case ROIDismissCommand:
11375 state|=EscapeState;
11384 switch (event.type)
11388 if (event.xbutton.button != Button1)
11390 if (event.xbutton.window != windows->image.id)
11393 Note first corner of region of interest rectangle-- exit loop.
11395 (void) XCheckDefineCursor(display,windows->image.id,cursor);
11396 roi_info.x=(ssize_t) windows->image.x+event.xbutton.x;
11397 roi_info.y=(ssize_t) windows->image.y+event.xbutton.y;
11401 case ButtonRelease:
11410 if (event.xkey.window != windows->image.id)
11413 Respond to a user key press.
11415 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
11416 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
11417 switch ((int) key_symbol)
11425 state|=EscapeState;
11432 XTextViewWidget(display,resource_info,windows,MagickFalse,
11433 "Help Viewer - Region of Interest",ImageROIHelp);
11438 (void) XBell(display,0);
11447 Map and unmap Info widget as text cursor crosses its boundaries.
11451 if (windows->info.mapped != MagickFalse)
11453 if ((x < (int) (windows->info.x+windows->info.width)) &&
11454 (y < (int) (windows->info.y+windows->info.height)))
11455 (void) XWithdrawWindow(display,windows->info.id,
11456 windows->info.screen);
11459 if ((x > (int) (windows->info.x+windows->info.width)) ||
11460 (y > (int) (windows->info.y+windows->info.height)))
11461 (void) XMapWindow(display,windows->info.id);
11462 roi_info.x=(ssize_t) windows->image.x+x;
11463 roi_info.y=(ssize_t) windows->image.y+y;
11469 } while ((state & ExitState) == 0);
11470 (void) XSelectInput(display,windows->image.id,
11471 windows->image.attributes.event_mask);
11472 if ((state & EscapeState) != 0)
11475 User want to exit without region of interest.
11477 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
11478 (void) XFreeCursor(display,cursor);
11479 return(MagickTrue);
11481 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
11485 Size rectangle as pointer moves until the mouse button is released.
11487 x=(int) roi_info.x;
11488 y=(int) roi_info.y;
11491 state=DefaultState;
11494 highlight_info=roi_info;
11495 highlight_info.x=roi_info.x-windows->image.x;
11496 highlight_info.y=roi_info.y-windows->image.y;
11497 if ((highlight_info.width > 3) && (highlight_info.height > 3))
11500 Display info and draw region of interest rectangle.
11502 if (windows->info.mapped == MagickFalse)
11503 (void) XMapWindow(display,windows->info.id);
11504 (void) FormatLocaleString(text,MaxTextExtent,
11505 " %.20gx%.20g%+.20g%+.20g",(double) roi_info.width,(double)
11506 roi_info.height,(double) roi_info.x,(double) roi_info.y);
11507 XInfoWidget(display,windows,text);
11508 XHighlightRectangle(display,windows->image.id,
11509 windows->image.highlight_context,&highlight_info);
11512 if (windows->info.mapped != MagickFalse)
11513 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
11515 Wait for next event.
11517 XScreenEvent(display,windows,&event,exception);
11518 if ((highlight_info.width > 3) && (highlight_info.height > 3))
11519 XHighlightRectangle(display,windows->image.id,
11520 windows->image.highlight_context,&highlight_info);
11521 switch (event.type)
11525 roi_info.x=(ssize_t) windows->image.x+event.xbutton.x;
11526 roi_info.y=(ssize_t) windows->image.y+event.xbutton.y;
11529 case ButtonRelease:
11532 User has committed to region of interest rectangle.
11534 roi_info.x=(ssize_t) windows->image.x+event.xbutton.x;
11535 roi_info.y=(ssize_t) windows->image.y+event.xbutton.y;
11536 XSetCursorState(display,windows,MagickFalse);
11538 if (LocaleCompare(windows->command.name,"Apply") == 0)
11540 (void) CloneString(&windows->command.name,"Apply");
11541 windows->command.data=ApplyMenus;
11542 (void) XCommandWidget(display,windows,ApplyMenu,(XEvent *) NULL);
11549 roi_info.x=(ssize_t) windows->image.x+event.xmotion.x;
11550 roi_info.y=(ssize_t) windows->image.y+event.xmotion.y;
11555 if ((((int) roi_info.x != x) && ((int) roi_info.y != y)) ||
11556 ((state & ExitState) != 0))
11559 Check boundary conditions.
11561 if (roi_info.x < 0)
11564 if (roi_info.x > (ssize_t) windows->image.ximage->width)
11565 roi_info.x=(ssize_t) windows->image.ximage->width;
11566 if ((int) roi_info.x < x)
11567 roi_info.width=(unsigned int) (x-roi_info.x);
11570 roi_info.width=(unsigned int) (roi_info.x-x);
11571 roi_info.x=(ssize_t) x;
11573 if (roi_info.y < 0)
11576 if (roi_info.y > (ssize_t) windows->image.ximage->height)
11577 roi_info.y=(ssize_t) windows->image.ximage->height;
11578 if ((int) roi_info.y < y)
11579 roi_info.height=(unsigned int) (y-roi_info.y);
11582 roi_info.height=(unsigned int) (roi_info.y-y);
11583 roi_info.y=(ssize_t) y;
11586 } while ((state & ExitState) == 0);
11588 Wait for user to grab a corner of the rectangle or press return.
11590 state=DefaultState;
11591 command_type=NullCommand;
11592 (void) XMapWindow(display,windows->info.id);
11595 if (windows->info.mapped != MagickFalse)
11598 Display pointer position.
11600 (void) FormatLocaleString(text,MaxTextExtent,
11601 " %.20gx%.20g%+.20g%+.20g",(double) roi_info.width,(double)
11602 roi_info.height,(double) roi_info.x,(double) roi_info.y);
11603 XInfoWidget(display,windows,text);
11605 highlight_info=roi_info;
11606 highlight_info.x=roi_info.x-windows->image.x;
11607 highlight_info.y=roi_info.y-windows->image.y;
11608 if ((highlight_info.width <= 3) || (highlight_info.height <= 3))
11610 state|=EscapeState;
11614 if ((state & UpdateRegionState) != 0)
11616 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
11617 switch (command_type)
11622 (void) XMagickCommand(display,resource_info,windows,command_type,
11629 Region of interest is relative to image configuration.
11631 progress_monitor=SetImageProgressMonitor(*image,
11632 (MagickProgressMonitor) NULL,(*image)->client_data);
11633 crop_info=roi_info;
11634 width=(unsigned int) (*image)->columns;
11635 height=(unsigned int) (*image)->rows;
11638 if (windows->image.crop_geometry != (char *) NULL)
11639 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,
11641 scale_factor=(double) width/windows->image.ximage->width;
11643 crop_info.x=(ssize_t) (scale_factor*crop_info.x+0.5);
11644 crop_info.width=(unsigned int) (scale_factor*crop_info.width+0.5);
11645 scale_factor=(double)
11646 height/windows->image.ximage->height;
11648 crop_info.y=(ssize_t) (scale_factor*crop_info.y+0.5);
11649 crop_info.height=(unsigned int)
11650 (scale_factor*crop_info.height+0.5);
11651 roi_image=CropImage(*image,&crop_info,exception);
11652 (void) SetImageProgressMonitor(*image,progress_monitor,
11653 (*image)->client_data);
11654 if (roi_image == (Image *) NULL)
11657 Apply image processing technique to the region of interest.
11659 windows->image.orphan=MagickTrue;
11660 (void) XMagickCommand(display,resource_info,windows,command_type,
11661 &roi_image,exception);
11662 progress_monitor=SetImageProgressMonitor(*image,
11663 (MagickProgressMonitor) NULL,(*image)->client_data);
11664 (void) XMagickCommand(display,resource_info,windows,
11665 SaveToUndoBufferCommand,image,exception);
11666 windows->image.orphan=MagickFalse;
11667 (void) CompositeImage(*image,roi_image,CopyCompositeOp,
11668 MagickTrue,crop_info.x,crop_info.y,exception);
11669 roi_image=DestroyImage(roi_image);
11670 (void) SetImageProgressMonitor(*image,progress_monitor,
11671 (*image)->client_data);
11675 if (command_type != InfoCommand)
11677 XConfigureImageColormap(display,resource_info,windows,*image,
11679 (void) XConfigureImage(display,resource_info,windows,*image,
11682 XCheckRefreshWindows(display,windows);
11683 XInfoWidget(display,windows,text);
11684 (void) XSetFunction(display,windows->image.highlight_context,
11686 state&=(~UpdateRegionState);
11688 XHighlightRectangle(display,windows->image.id,
11689 windows->image.highlight_context,&highlight_info);
11690 XScreenEvent(display,windows,&event,exception);
11691 if (event.xany.window == windows->command.id)
11694 Select a command from the Command widget.
11696 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
11697 command_type=NullCommand;
11698 id=XCommandWidget(display,windows,ApplyMenu,&event);
11701 (void) CopyMagickString(command,ApplyMenu[id],MaxTextExtent);
11702 command_type=ApplyCommands[id];
11703 if (id < ApplyMenus)
11706 Select a command from a pop-up menu.
11708 entry=XMenuWidget(display,windows,ApplyMenu[id],
11709 (const char **) Menus[id],command);
11712 (void) CopyMagickString(command,Menus[id][entry],
11714 command_type=Commands[id][entry];
11718 (void) XSetFunction(display,windows->image.highlight_context,
11720 XHighlightRectangle(display,windows->image.id,
11721 windows->image.highlight_context,&highlight_info);
11722 if (command_type == HelpCommand)
11724 (void) XSetFunction(display,windows->image.highlight_context,
11726 XTextViewWidget(display,resource_info,windows,MagickFalse,
11727 "Help Viewer - Region of Interest",ImageROIHelp);
11728 (void) XSetFunction(display,windows->image.highlight_context,
11732 if (command_type == QuitCommand)
11737 state|=EscapeState;
11741 if (command_type != NullCommand)
11742 state|=UpdateRegionState;
11745 XHighlightRectangle(display,windows->image.id,
11746 windows->image.highlight_context,&highlight_info);
11747 switch (event.type)
11751 x=windows->image.x;
11752 y=windows->image.y;
11753 if (event.xbutton.button != Button1)
11755 if (event.xbutton.window != windows->image.id)
11757 x=windows->image.x+event.xbutton.x;
11758 y=windows->image.y+event.xbutton.y;
11759 if ((x < (int) (roi_info.x+RoiDelta)) &&
11760 (x > (int) (roi_info.x-RoiDelta)) &&
11761 (y < (int) (roi_info.y+RoiDelta)) &&
11762 (y > (int) (roi_info.y-RoiDelta)))
11764 roi_info.x=(ssize_t) (roi_info.x+roi_info.width);
11765 roi_info.y=(ssize_t) (roi_info.y+roi_info.height);
11766 state|=UpdateConfigurationState;
11769 if ((x < (int) (roi_info.x+RoiDelta)) &&
11770 (x > (int) (roi_info.x-RoiDelta)) &&
11771 (y < (int) (roi_info.y+roi_info.height+RoiDelta)) &&
11772 (y > (int) (roi_info.y+roi_info.height-RoiDelta)))
11774 roi_info.x=(ssize_t) (roi_info.x+roi_info.width);
11775 state|=UpdateConfigurationState;
11778 if ((x < (int) (roi_info.x+roi_info.width+RoiDelta)) &&
11779 (x > (int) (roi_info.x+roi_info.width-RoiDelta)) &&
11780 (y < (int) (roi_info.y+RoiDelta)) &&
11781 (y > (int) (roi_info.y-RoiDelta)))
11783 roi_info.y=(ssize_t) (roi_info.y+roi_info.height);
11784 state|=UpdateConfigurationState;
11787 if ((x < (int) (roi_info.x+roi_info.width+RoiDelta)) &&
11788 (x > (int) (roi_info.x+roi_info.width-RoiDelta)) &&
11789 (y < (int) (roi_info.y+roi_info.height+RoiDelta)) &&
11790 (y > (int) (roi_info.y+roi_info.height-RoiDelta)))
11792 state|=UpdateConfigurationState;
11796 case ButtonRelease:
11798 if (event.xbutton.window == windows->pan.id)
11799 if ((highlight_info.x != crop_info.x-windows->image.x) ||
11800 (highlight_info.y != crop_info.y-windows->image.y))
11801 XHighlightRectangle(display,windows->image.id,
11802 windows->image.highlight_context,&highlight_info);
11803 (void) XSetSelectionOwner(display,XA_PRIMARY,windows->image.id,
11804 event.xbutton.time);
11809 if (event.xexpose.window == windows->image.id)
11810 if (event.xexpose.count == 0)
11812 event.xexpose.x=(int) highlight_info.x;
11813 event.xexpose.y=(int) highlight_info.y;
11814 event.xexpose.width=(int) highlight_info.width;
11815 event.xexpose.height=(int) highlight_info.height;
11816 XRefreshWindow(display,&windows->image,&event);
11818 if (event.xexpose.window == windows->info.id)
11819 if (event.xexpose.count == 0)
11820 XInfoWidget(display,windows,text);
11828 if (event.xkey.window != windows->image.id)
11831 Respond to a user key press.
11833 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
11834 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
11835 switch ((int) key_symbol)
11842 state|=EscapeState;
11851 roi_info.x=(ssize_t) (windows->image.width/2L-roi_info.width/2L);
11852 roi_info.y=(ssize_t) (windows->image.height/2L-
11853 roi_info.height/2L);
11885 (void) XSetFunction(display,windows->image.highlight_context,
11887 XTextViewWidget(display,resource_info,windows,MagickFalse,
11888 "Help Viewer - Region of Interest",ImageROIHelp);
11889 (void) XSetFunction(display,windows->image.highlight_context,
11895 command_type=XImageWindowCommand(display,resource_info,windows,
11896 event.xkey.state,key_symbol,image,exception);
11897 if (command_type != NullCommand)
11898 state|=UpdateRegionState;
11902 (void) XSetSelectionOwner(display,XA_PRIMARY,windows->image.id,
11910 if (event.xbutton.window != windows->image.id)
11913 Map and unmap Info widget as text cursor crosses its boundaries.
11917 if (windows->info.mapped != MagickFalse)
11919 if ((x < (int) (windows->info.x+windows->info.width)) &&
11920 (y < (int) (windows->info.y+windows->info.height)))
11921 (void) XWithdrawWindow(display,windows->info.id,
11922 windows->info.screen);
11925 if ((x > (int) (windows->info.x+windows->info.width)) ||
11926 (y > (int) (windows->info.y+windows->info.height)))
11927 (void) XMapWindow(display,windows->info.id);
11928 roi_info.x=(ssize_t) windows->image.x+event.xmotion.x;
11929 roi_info.y=(ssize_t) windows->image.y+event.xmotion.y;
11932 case SelectionRequest:
11937 XSelectionRequestEvent
11941 Set primary selection.
11943 (void) FormatLocaleString(text,MaxTextExtent,
11944 "%.20gx%.20g%+.20g%+.20g",(double) roi_info.width,(double)
11945 roi_info.height,(double) roi_info.x,(double) roi_info.y);
11946 request=(&(event.xselectionrequest));
11947 (void) XChangeProperty(request->display,request->requestor,
11948 request->property,request->target,8,PropModeReplace,
11949 (unsigned char *) text,(int) strlen(text));
11950 notify.type=SelectionNotify;
11951 notify.display=request->display;
11952 notify.requestor=request->requestor;
11953 notify.selection=request->selection;
11954 notify.target=request->target;
11955 notify.time=request->time;
11956 if (request->property == None)
11957 notify.property=request->target;
11959 notify.property=request->property;
11960 (void) XSendEvent(request->display,request->requestor,False,0,
11961 (XEvent *) ¬ify);
11966 if ((state & UpdateConfigurationState) != 0)
11968 (void) XPutBackEvent(display,&event);
11969 (void) XCheckDefineCursor(display,windows->image.id,cursor);
11972 } while ((state & ExitState) == 0);
11973 } while ((state & ExitState) == 0);
11974 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
11975 XSetCursorState(display,windows,MagickFalse);
11976 if ((state & EscapeState) != 0)
11977 return(MagickTrue);
11978 return(MagickTrue);
11982 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
11986 + X R o t a t e I m a g e %
11990 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
11992 % XRotateImage() rotates the X image. If the degrees parameter if zero, the
11993 % rotation angle is computed from the slope of a line drawn by the user.
11995 % The format of the XRotateImage method is:
11997 % MagickBooleanType XRotateImage(Display *display,
11998 % XResourceInfo *resource_info,XWindows *windows,double degrees,
11999 % Image **image,ExceptionInfo *exception)
12001 % A description of each parameter follows:
12003 % o display: Specifies a connection to an X server; returned from
12006 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
12008 % o windows: Specifies a pointer to a XWindows structure.
12010 % o degrees: Specifies the number of degrees to rotate the image.
12012 % o image: the image.
12014 % o exception: return any errors or warnings in this structure.
12017 static MagickBooleanType XRotateImage(Display *display,
12018 XResourceInfo *resource_info,XWindows *windows,double degrees,Image **image,
12019 ExceptionInfo *exception)
12032 direction = HorizontalRotateCommand;
12034 static const ModeType
12035 DirectionCommands[] =
12037 HorizontalRotateCommand,
12038 VerticalRotateCommand
12042 RotateColorCommand,
12043 RotateDirectionCommand,
12045 RotateDismissCommand
12048 static unsigned int
12052 command[MaxTextExtent],
12053 text[MaxTextExtent];
12064 normalized_degrees;
12074 if (degrees == 0.0)
12089 Map Command widget.
12091 (void) CloneString(&windows->command.name,"Rotate");
12092 windows->command.data=2;
12093 (void) XCommandWidget(display,windows,RotateMenu,(XEvent *) NULL);
12094 (void) XMapRaised(display,windows->command.id);
12095 XClientMessage(display,windows->image.id,windows->im_protocols,
12096 windows->im_update_widget,CurrentTime);
12098 Wait for first button press.
12100 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
12101 XQueryPosition(display,windows->image.id,&x,&y);
12106 state=DefaultState;
12109 XHighlightLine(display,windows->image.id,
12110 windows->image.highlight_context,&rotate_info);
12112 Wait for next event.
12114 XScreenEvent(display,windows,&event,exception);
12115 XHighlightLine(display,windows->image.id,
12116 windows->image.highlight_context,&rotate_info);
12117 if (event.xany.window == windows->command.id)
12120 Select a command from the Command widget.
12122 id=XCommandWidget(display,windows,RotateMenu,&event);
12125 (void) XSetFunction(display,windows->image.highlight_context,
12127 switch (RotateCommands[id])
12129 case RotateColorCommand:
12132 *ColorMenu[MaxNumberPens];
12141 Initialize menu selections.
12143 for (i=0; i < (int) (MaxNumberPens-2); i++)
12144 ColorMenu[i]=resource_info->pen_colors[i];
12145 ColorMenu[MaxNumberPens-2]="Browser...";
12146 ColorMenu[MaxNumberPens-1]=(const char *) NULL;
12148 Select a pen color from the pop-up menu.
12150 pen_number=XMenuWidget(display,windows,RotateMenu[id],
12151 (const char **) ColorMenu,command);
12152 if (pen_number < 0)
12154 if (pen_number == (MaxNumberPens-2))
12157 color_name[MaxTextExtent] = "gray";
12160 Select a pen color from a dialog.
12162 resource_info->pen_colors[pen_number]=color_name;
12163 XColorBrowserWidget(display,windows,"Select",color_name);
12164 if (*color_name == '\0')
12170 (void) XParseColor(display,windows->map_info->colormap,
12171 resource_info->pen_colors[pen_number],&color);
12172 XBestPixel(display,windows->map_info->colormap,(XColor *) NULL,
12173 (unsigned int) MaxColors,&color);
12174 windows->pixel_info->pen_colors[pen_number]=color;
12175 pen_id=(unsigned int) pen_number;
12178 case RotateDirectionCommand:
12189 Select a command from the pop-up menu.
12191 id=XMenuWidget(display,windows,RotateMenu[id],
12192 Directions,command);
12194 direction=DirectionCommands[id];
12197 case RotateHelpCommand:
12199 XTextViewWidget(display,resource_info,windows,MagickFalse,
12200 "Help Viewer - Image Rotation",ImageRotateHelp);
12203 case RotateDismissCommand:
12208 state|=EscapeState;
12215 (void) XSetFunction(display,windows->image.highlight_context,
12219 switch (event.type)
12223 if (event.xbutton.button != Button1)
12225 if (event.xbutton.window != windows->image.id)
12230 (void) XSetFunction(display,windows->image.highlight_context,
12232 rotate_info.x1=event.xbutton.x;
12233 rotate_info.y1=event.xbutton.y;
12237 case ButtonRelease:
12244 command[MaxTextExtent];
12249 if (event.xkey.window != windows->image.id)
12252 Respond to a user key press.
12254 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
12255 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
12256 switch ((int) key_symbol)
12264 state|=EscapeState;
12271 (void) XSetFunction(display,windows->image.highlight_context,
12273 XTextViewWidget(display,resource_info,windows,MagickFalse,
12274 "Help Viewer - Image Rotation",ImageRotateHelp);
12275 (void) XSetFunction(display,windows->image.highlight_context,
12281 (void) XBell(display,0);
12289 rotate_info.x1=event.xmotion.x;
12290 rotate_info.y1=event.xmotion.y;
12293 rotate_info.x2=rotate_info.x1;
12294 rotate_info.y2=rotate_info.y1;
12295 if (direction == HorizontalRotateCommand)
12296 rotate_info.x2+=32;
12298 rotate_info.y2-=32;
12299 } while ((state & ExitState) == 0);
12300 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
12301 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
12302 if ((state & EscapeState) != 0)
12303 return(MagickTrue);
12305 Draw line as pointer moves until the mouse button is released.
12308 (void) XSetFunction(display,windows->image.highlight_context,GXinvert);
12309 state=DefaultState;
12315 Display info and draw rotation line.
12317 if (windows->info.mapped == MagickFalse)
12318 (void) XMapWindow(display,windows->info.id);
12319 (void) FormatLocaleString(text,MaxTextExtent," %g",
12320 direction == VerticalRotateCommand ? degrees-90.0 : degrees);
12321 XInfoWidget(display,windows,text);
12322 XHighlightLine(display,windows->image.id,
12323 windows->image.highlight_context,&rotate_info);
12326 if (windows->info.mapped != MagickFalse)
12327 (void) XWithdrawWindow(display,windows->info.id,
12328 windows->info.screen);
12330 Wait for next event.
12332 XScreenEvent(display,windows,&event,exception);
12334 XHighlightLine(display,windows->image.id,
12335 windows->image.highlight_context,&rotate_info);
12336 switch (event.type)
12340 case ButtonRelease:
12343 User has committed to rotation line.
12345 rotate_info.x2=event.xbutton.x;
12346 rotate_info.y2=event.xbutton.y;
12354 rotate_info.x2=event.xmotion.x;
12355 rotate_info.y2=event.xmotion.y;
12361 Check boundary conditions.
12363 if (rotate_info.x2 < 0)
12366 if (rotate_info.x2 > (int) windows->image.width)
12367 rotate_info.x2=(short) windows->image.width;
12368 if (rotate_info.y2 < 0)
12371 if (rotate_info.y2 > (int) windows->image.height)
12372 rotate_info.y2=(short) windows->image.height;
12374 Compute rotation angle from the slope of the line.
12377 distance=(unsigned int)
12378 ((rotate_info.x2-rotate_info.x1+1)*(rotate_info.x2-rotate_info.x1+1))+
12379 ((rotate_info.y2-rotate_info.y1+1)*(rotate_info.y2-rotate_info.y1+1));
12381 degrees=RadiansToDegrees(-atan2((double) (rotate_info.y2-
12382 rotate_info.y1),(double) (rotate_info.x2-rotate_info.x1)));
12383 } while ((state & ExitState) == 0);
12384 (void) XSetFunction(display,windows->image.highlight_context,GXcopy);
12385 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
12387 return(MagickTrue);
12389 if (direction == VerticalRotateCommand)
12391 if (degrees == 0.0)
12392 return(MagickTrue);
12396 normalized_degrees=degrees;
12397 while (normalized_degrees < -45.0)
12398 normalized_degrees+=360.0;
12399 for (rotations=0; normalized_degrees > 45.0; rotations++)
12400 normalized_degrees-=90.0;
12401 if (normalized_degrees != 0.0)
12402 (void) XMagickCommand(display,resource_info,windows,ApplyCommand,image,
12404 XSetCursorState(display,windows,MagickTrue);
12405 XCheckRefreshWindows(display,windows);
12406 (*image)->background_color.red=(double) ScaleShortToQuantum(
12407 windows->pixel_info->pen_colors[pen_id].red);
12408 (*image)->background_color.green=(double) ScaleShortToQuantum(
12409 windows->pixel_info->pen_colors[pen_id].green);
12410 (*image)->background_color.blue=(double) ScaleShortToQuantum(
12411 windows->pixel_info->pen_colors[pen_id].blue);
12412 rotate_image=RotateImage(*image,degrees,exception);
12413 XSetCursorState(display,windows,MagickFalse);
12414 if (rotate_image == (Image *) NULL)
12415 return(MagickFalse);
12416 *image=DestroyImage(*image);
12417 *image=rotate_image;
12418 if (windows->image.crop_geometry != (char *) NULL)
12421 Rotate crop geometry.
12423 width=(unsigned int) (*image)->columns;
12424 height=(unsigned int) (*image)->rows;
12425 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
12426 switch (rotations % 4)
12436 (void) FormatLocaleString(windows->image.crop_geometry,MaxTextExtent,
12437 "%ux%u%+d%+d",height,width,(int) (*image)->columns-
12444 Rotate 180 degrees.
12446 (void) FormatLocaleString(windows->image.crop_geometry,MaxTextExtent,
12447 "%ux%u%+d%+d",width,height,(int) width-x,(int) height-y);
12453 Rotate 270 degrees.
12455 (void) FormatLocaleString(windows->image.crop_geometry,MaxTextExtent,
12456 "%ux%u%+d%+d",height,width,y,(int) (*image)->rows-(int) width-x);
12461 if (windows->image.orphan != MagickFalse)
12462 return(MagickTrue);
12463 if (normalized_degrees != 0.0)
12466 Update image colormap.
12468 windows->image.window_changes.width=(int) (*image)->columns;
12469 windows->image.window_changes.height=(int) (*image)->rows;
12470 if (windows->image.crop_geometry != (char *) NULL)
12473 Obtain dimensions of image from crop geometry.
12475 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,
12477 windows->image.window_changes.width=(int) width;
12478 windows->image.window_changes.height=(int) height;
12480 XConfigureImageColormap(display,resource_info,windows,*image,exception);
12483 if (((rotations % 4) == 1) || ((rotations % 4) == 3))
12485 windows->image.window_changes.width=windows->image.ximage->height;
12486 windows->image.window_changes.height=windows->image.ximage->width;
12489 Update image configuration.
12491 (void) XConfigureImage(display,resource_info,windows,*image,exception);
12492 return(MagickTrue);
12496 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12500 + X S a v e I m a g e %
12504 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12506 % XSaveImage() saves an image to a file.
12508 % The format of the XSaveImage method is:
12510 % MagickBooleanType XSaveImage(Display *display,
12511 % XResourceInfo *resource_info,XWindows *windows,Image *image,
12512 % ExceptionInfo *exception)
12514 % A description of each parameter follows:
12516 % o display: Specifies a connection to an X server; returned from
12519 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
12521 % o windows: Specifies a pointer to a XWindows structure.
12523 % o image: the image.
12525 % o exception: return any errors or warnings in this structure.
12528 static MagickBooleanType XSaveImage(Display *display,
12529 XResourceInfo *resource_info,XWindows *windows,Image *image,
12530 ExceptionInfo *exception)
12533 filename[MaxTextExtent],
12534 geometry[MaxTextExtent];
12546 Request file name from user.
12548 if (resource_info->write_filename != (char *) NULL)
12549 (void) CopyMagickString(filename,resource_info->write_filename,
12554 path[MaxTextExtent];
12559 GetPathComponent(image->filename,HeadPath,path);
12560 GetPathComponent(image->filename,TailPath,filename);
12563 status=chdir(path);
12565 (void) ThrowMagickException(exception,GetMagickModule(),
12566 FileOpenError,"UnableToOpenFile","%s",path);
12569 XFileBrowserWidget(display,windows,"Save",filename);
12570 if (*filename == '\0')
12571 return(MagickTrue);
12572 if (IsPathAccessible(filename) != MagickFalse)
12578 File exists-- seek user's permission before overwriting.
12580 status=XConfirmWidget(display,windows,"Overwrite",filename);
12582 return(MagickTrue);
12584 image_info=CloneImageInfo(resource_info->image_info);
12585 (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
12586 (void) SetImageInfo(image_info,1,exception);
12587 if ((LocaleCompare(image_info->magick,"JPEG") == 0) ||
12588 (LocaleCompare(image_info->magick,"JPG") == 0))
12591 quality[MaxTextExtent];
12597 Request JPEG quality from user.
12599 (void) FormatLocaleString(quality,MaxTextExtent,"%.20g",(double)
12601 status=XDialogWidget(display,windows,"Save","Enter JPEG quality:",
12603 if (*quality == '\0')
12604 return(MagickTrue);
12605 image->quality=StringToUnsignedLong(quality);
12606 image_info->interlace=status != 0 ? NoInterlace : PlaneInterlace;
12608 if ((LocaleCompare(image_info->magick,"EPS") == 0) ||
12609 (LocaleCompare(image_info->magick,"PDF") == 0) ||
12610 (LocaleCompare(image_info->magick,"PS") == 0) ||
12611 (LocaleCompare(image_info->magick,"PS2") == 0))
12614 geometry[MaxTextExtent];
12617 Request page geometry from user.
12619 (void) CopyMagickString(geometry,PSPageGeometry,MaxTextExtent);
12620 if (LocaleCompare(image_info->magick,"PDF") == 0)
12621 (void) CopyMagickString(geometry,PSPageGeometry,MaxTextExtent);
12622 if (image_info->page != (char *) NULL)
12623 (void) CopyMagickString(geometry,image_info->page,MaxTextExtent);
12624 XListBrowserWidget(display,windows,&windows->widget,PageSizes,"Select",
12625 "Select page geometry:",geometry);
12626 if (*geometry != '\0')
12627 image_info->page=GetPageGeometry(geometry);
12630 Apply image transforms.
12632 XSetCursorState(display,windows,MagickTrue);
12633 XCheckRefreshWindows(display,windows);
12634 save_image=CloneImage(image,0,0,MagickTrue,exception);
12635 if (save_image == (Image *) NULL)
12636 return(MagickFalse);
12637 (void) FormatLocaleString(geometry,MaxTextExtent,"%dx%d!",
12638 windows->image.ximage->width,windows->image.ximage->height);
12639 (void) TransformImage(&save_image,windows->image.crop_geometry,geometry,
12644 (void) CopyMagickString(save_image->filename,filename,MaxTextExtent);
12645 status=WriteImage(image_info,save_image,exception);
12646 if (status != MagickFalse)
12647 image->taint=MagickFalse;
12648 save_image=DestroyImage(save_image);
12649 image_info=DestroyImageInfo(image_info);
12650 XSetCursorState(display,windows,MagickFalse);
12651 return(status != 0 ? MagickTrue : MagickFalse);
12655 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12659 + X S c r e e n E v e n t %
12663 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12665 % XScreenEvent() handles global events associated with the Pan and Magnify
12668 % The format of the XScreenEvent function is:
12670 % void XScreenEvent(Display *display,XWindows *windows,XEvent *event,
12671 % ExceptionInfo *exception)
12673 % A description of each parameter follows:
12675 % o display: Specifies a pointer to the Display structure; returned from
12678 % o windows: Specifies a pointer to a XWindows structure.
12680 % o event: Specifies a pointer to a X11 XEvent structure.
12682 % o exception: return any errors or warnings in this structure.
12686 #if defined(__cplusplus) || defined(c_plusplus)
12690 static int XPredicate(Display *magick_unused(display),XEvent *event,char *data)
12695 windows=(XWindows *) data;
12696 if ((event->type == ClientMessage) &&
12697 (event->xclient.window == windows->image.id))
12698 return(MagickFalse);
12699 return(MagickTrue);
12702 #if defined(__cplusplus) || defined(c_plusplus)
12706 static void XScreenEvent(Display *display,XWindows *windows,XEvent *event,
12707 ExceptionInfo *exception)
12713 (void) XIfEvent(display,event,XPredicate,(char *) windows);
12714 if (event->xany.window == windows->command.id)
12716 switch (event->type)
12719 case ButtonRelease:
12721 if ((event->xbutton.button == Button3) &&
12722 (event->xbutton.state & Mod1Mask))
12725 Convert Alt-Button3 to Button2.
12727 event->xbutton.button=Button2;
12728 event->xbutton.state&=(~Mod1Mask);
12730 if (event->xbutton.window == windows->backdrop.id)
12732 (void) XSetInputFocus(display,event->xbutton.window,RevertToParent,
12733 event->xbutton.time);
12736 if (event->xbutton.window == windows->pan.id)
12738 XPanImage(display,windows,event,exception);
12741 if (event->xbutton.window == windows->image.id)
12742 if (event->xbutton.button == Button2)
12745 Update magnified image.
12747 x=event->xbutton.x;
12748 y=event->xbutton.y;
12752 if (x >= (int) windows->image.width)
12753 x=(int) (windows->image.width-1);
12754 windows->magnify.x=(int) windows->image.x+x;
12758 if (y >= (int) windows->image.height)
12759 y=(int) (windows->image.height-1);
12760 windows->magnify.y=windows->image.y+y;
12761 if (windows->magnify.mapped == MagickFalse)
12762 (void) XMapRaised(display,windows->magnify.id);
12763 XMakeMagnifyImage(display,windows,exception);
12764 if (event->type == ButtonRelease)
12765 (void) XWithdrawWindow(display,windows->info.id,
12766 windows->info.screen);
12771 case ClientMessage:
12774 If client window delete message, exit.
12776 if (event->xclient.message_type != windows->wm_protocols)
12778 if (*event->xclient.data.l != (long) windows->wm_delete_window)
12780 if (event->xclient.window == windows->magnify.id)
12782 (void) XWithdrawWindow(display,windows->magnify.id,
12783 windows->magnify.screen);
12788 case ConfigureNotify:
12790 if (event->xconfigure.window == windows->magnify.id)
12796 Magnify window has a new configuration.
12798 windows->magnify.width=(unsigned int) event->xconfigure.width;
12799 windows->magnify.height=(unsigned int) event->xconfigure.height;
12800 if (windows->magnify.mapped == MagickFalse)
12803 while ((int) magnify <= event->xconfigure.width)
12805 while ((int) magnify <= event->xconfigure.height)
12808 if (((int) magnify != event->xconfigure.width) ||
12809 ((int) magnify != event->xconfigure.height))
12814 window_changes.width=(int) magnify;
12815 window_changes.height=(int) magnify;
12816 (void) XReconfigureWMWindow(display,windows->magnify.id,
12817 windows->magnify.screen,(unsigned int) (CWWidth | CWHeight),
12821 XMakeMagnifyImage(display,windows,exception);
12828 if (event->xexpose.window == windows->image.id)
12830 XRefreshWindow(display,&windows->image,event);
12833 if (event->xexpose.window == windows->pan.id)
12834 if (event->xexpose.count == 0)
12836 XDrawPanRectangle(display,windows);
12839 if (event->xexpose.window == windows->magnify.id)
12840 if (event->xexpose.count == 0)
12842 XMakeMagnifyImage(display,windows,exception);
12850 command[MaxTextExtent];
12855 if (event->xkey.window != windows->magnify.id)
12858 Respond to a user key press.
12860 (void) XLookupString((XKeyEvent *) &event->xkey,command,(int)
12861 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
12862 XMagnifyWindowCommand(display,windows,event->xkey.state,key_symbol,
12868 if (event->xmap.window == windows->magnify.id)
12870 windows->magnify.mapped=MagickTrue;
12871 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
12874 if (event->xmap.window == windows->info.id)
12876 windows->info.mapped=MagickTrue;
12883 while (XCheckMaskEvent(display,ButtonMotionMask,event)) ;
12884 if (event->xmotion.window == windows->image.id)
12885 if (windows->magnify.mapped != MagickFalse)
12888 Update magnified image.
12890 x=event->xmotion.x;
12891 y=event->xmotion.y;
12895 if (x >= (int) windows->image.width)
12896 x=(int) (windows->image.width-1);
12897 windows->magnify.x=(int) windows->image.x+x;
12901 if (y >= (int) windows->image.height)
12902 y=(int) (windows->image.height-1);
12903 windows->magnify.y=windows->image.y+y;
12904 XMakeMagnifyImage(display,windows,exception);
12910 if (event->xunmap.window == windows->magnify.id)
12912 windows->magnify.mapped=MagickFalse;
12915 if (event->xunmap.window == windows->info.id)
12917 windows->info.mapped=MagickFalse;
12928 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12932 + X S e t C r o p G e o m e t r y %
12936 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12938 % XSetCropGeometry() accepts a cropping geometry relative to the Image window
12939 % and translates it to a cropping geometry relative to the image.
12941 % The format of the XSetCropGeometry method is:
12943 % void XSetCropGeometry(Display *display,XWindows *windows,
12944 % RectangleInfo *crop_info,Image *image)
12946 % A description of each parameter follows:
12948 % o display: Specifies a connection to an X server; returned from
12951 % o windows: Specifies a pointer to a XWindows structure.
12953 % o crop_info: A pointer to a RectangleInfo that defines a region of the
12954 % Image window to crop.
12956 % o image: the image.
12959 static void XSetCropGeometry(Display *display,XWindows *windows,
12960 RectangleInfo *crop_info,Image *image)
12963 text[MaxTextExtent];
12976 if (windows->info.mapped != MagickFalse)
12979 Display info on cropping rectangle.
12981 (void) FormatLocaleString(text,MaxTextExtent," %.20gx%.20g%+.20g%+.20g",
12982 (double) crop_info->width,(double) crop_info->height,(double)
12983 crop_info->x,(double) crop_info->y);
12984 XInfoWidget(display,windows,text);
12987 Cropping geometry is relative to any previous crop geometry.
12991 width=(unsigned int) image->columns;
12992 height=(unsigned int) image->rows;
12993 if (windows->image.crop_geometry != (char *) NULL)
12994 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
12996 windows->image.crop_geometry=AcquireString((char *) NULL);
12998 Define the crop geometry string from the cropping rectangle.
13000 scale_factor=(double) width/windows->image.ximage->width;
13001 if (crop_info->x > 0)
13002 x+=(int) (scale_factor*crop_info->x+0.5);
13003 width=(unsigned int) (scale_factor*crop_info->width+0.5);
13006 scale_factor=(double) height/windows->image.ximage->height;
13007 if (crop_info->y > 0)
13008 y+=(int) (scale_factor*crop_info->y+0.5);
13009 height=(unsigned int) (scale_factor*crop_info->height+0.5);
13012 (void) FormatLocaleString(windows->image.crop_geometry,MaxTextExtent,
13013 "%ux%u%+d%+d",width,height,x,y);
13017 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13021 + X T i l e I m a g e %
13025 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13027 % XTileImage() loads or deletes a selected tile from a visual image directory.
13028 % The load or delete command is chosen from a menu.
13030 % The format of the XTileImage method is:
13032 % Image *XTileImage(Display *display,XResourceInfo *resource_info,
13033 % XWindows *windows,Image *image,XEvent *event,ExceptionInfo *exception)
13035 % A description of each parameter follows:
13037 % o tile_image: XTileImage reads or deletes the tile image
13038 % and returns it. A null image is returned if an error occurs.
13040 % o display: Specifies a connection to an X server; returned from
13043 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
13045 % o windows: Specifies a pointer to a XWindows structure.
13047 % o image: the image; returned from ReadImage.
13049 % o event: Specifies a pointer to a XEvent structure. If it is NULL,
13050 % the entire image is refreshed.
13052 % o exception: return any errors or warnings in this structure.
13055 static Image *XTileImage(Display *display,XResourceInfo *resource_info,
13056 XWindows *windows,Image *image,XEvent *event,ExceptionInfo *exception)
13069 static const ModeType
13080 command[MaxTextExtent],
13081 filename[MaxTextExtent];
13108 Tile image is relative to montage image configuration.
13112 width=(unsigned int) image->columns;
13113 height=(unsigned int) image->rows;
13114 if (windows->image.crop_geometry != (char *) NULL)
13115 (void) XParseGeometry(windows->image.crop_geometry,&x,&y,&width,&height);
13116 scale_factor=(double) width/windows->image.ximage->width;
13117 event->xbutton.x+=windows->image.x;
13118 event->xbutton.x=(int) (scale_factor*event->xbutton.x+x+0.5);
13119 scale_factor=(double) height/windows->image.ximage->height;
13120 event->xbutton.y+=windows->image.y;
13121 event->xbutton.y=(int) (scale_factor*event->xbutton.y+y+0.5);
13123 Determine size and location of each tile in the visual image directory.
13125 width=(unsigned int) image->columns;
13126 height=(unsigned int) image->rows;
13129 (void) XParseGeometry(image->montage,&x,&y,&width,&height);
13130 tile=((event->xbutton.y-y)/height)*(((int) image->columns-x)/width)+
13131 (event->xbutton.x-x)/width;
13135 Button press is outside any tile.
13137 (void) XBell(display,0);
13138 return((Image *) NULL);
13141 Determine file name from the tile directory.
13143 p=image->directory;
13144 for (i=tile; (i != 0) && (*p != '\0'); )
13153 Button press is outside any tile.
13155 (void) XBell(display,0);
13156 return((Image *) NULL);
13159 Select a command from the pop-up menu.
13161 id=XMenuWidget(display,windows,"Tile Verb",VerbMenu,command);
13163 return((Image *) NULL);
13165 while ((*q != '\n') && (*q != '\0'))
13167 (void) CopyMagickString(filename,p,(size_t) (q-p+1));
13169 Perform command for the selected tile.
13171 XSetCursorState(display,windows,MagickTrue);
13172 XCheckRefreshWindows(display,windows);
13173 tile_image=NewImageList();
13174 switch (TileCommands[id])
13176 case TileLoadCommand:
13181 XCheckRefreshWindows(display,windows);
13182 (void) CopyMagickString(resource_info->image_info->magick,"MIFF",
13184 (void) CopyMagickString(resource_info->image_info->filename,filename,
13186 tile_image=ReadImage(resource_info->image_info,exception);
13187 CatchException(exception);
13188 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
13191 case TileNextCommand:
13194 Display next image.
13196 XClientMessage(display,windows->image.id,windows->im_protocols,
13197 windows->im_next_image,CurrentTime);
13200 case TileFormerCommand:
13203 Display former image.
13205 XClientMessage(display,windows->image.id,windows->im_protocols,
13206 windows->im_former_image,CurrentTime);
13209 case TileDeleteCommand:
13214 if (IsPathAccessible(filename) == MagickFalse)
13216 XNoticeWidget(display,windows,"Image file does not exist:",filename);
13219 status=XConfirmWidget(display,windows,"Really delete tile",filename);
13222 status=remove_utf8(filename) != 0 ? MagickTrue : MagickFalse;
13223 if (status != MagickFalse)
13225 XNoticeWidget(display,windows,"Unable to delete image file:",
13230 case TileUpdateCommand:
13246 Ensure all the images exist.
13249 GetPixelInfo(image,&pixel);
13250 for (p=image->directory; *p != '\0'; p++)
13256 while ((*q != '\n') && (*q != '\0'))
13258 (void) CopyMagickString(filename,p,(size_t) (q-p+1));
13260 if (IsPathAccessible(filename) != MagickFalse)
13266 Overwrite tile with background color.
13268 x_offset=(int) (width*(tile % (((int) image->columns-x)/width))+x);
13269 y_offset=(int) (height*(tile/(((int) image->columns-x)/width))+y);
13270 image_view=AcquireAuthenticCacheView(image,exception);
13271 (void) GetOneCacheViewVirtualPixelInfo(image_view,0,0,&pixel,exception);
13272 for (i=0; i < (int) height; i++)
13274 s=GetCacheViewAuthenticPixels(image_view,(ssize_t) x_offset,(ssize_t)
13275 y_offset+i,width,1,exception);
13276 if (s == (Quantum *) NULL)
13278 for (j=0; j < (int) width; j++)
13280 SetPixelInfoPixel(image,&pixel,s);
13281 s+=GetPixelChannels(image);
13283 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
13286 image_view=DestroyCacheView(image_view);
13289 windows->image.window_changes.width=(int) image->columns;
13290 windows->image.window_changes.height=(int) image->rows;
13291 XConfigureImageColormap(display,resource_info,windows,image,exception);
13292 (void) XConfigureImage(display,resource_info,windows,image,exception);
13298 XSetCursorState(display,windows,MagickFalse);
13299 return(tile_image);
13303 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13307 + X T r a n s l a t e I m a g e %
13311 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13313 % XTranslateImage() translates the image within an Image window by one pixel
13314 % as specified by the key symbol. If the image has a montage string the
13315 % translation is respect to the width and height contained within the string.
13317 % The format of the XTranslateImage method is:
13319 % void XTranslateImage(Display *display,XWindows *windows,
13320 % Image *image,const KeySym key_symbol)
13322 % A description of each parameter follows:
13324 % o display: Specifies a connection to an X server; returned from
13327 % o windows: Specifies a pointer to a XWindows structure.
13329 % o image: the image.
13331 % o key_symbol: Specifies a KeySym which indicates which side of the image
13335 static void XTranslateImage(Display *display,XWindows *windows,
13336 Image *image,const KeySym key_symbol)
13339 text[MaxTextExtent];
13350 User specified a pan position offset.
13352 x_offset=windows->image.width;
13353 y_offset=windows->image.height;
13354 if (image->montage != (char *) NULL)
13355 (void) XParseGeometry(image->montage,&x,&y,&x_offset,&y_offset);
13356 switch ((int) key_symbol)
13361 windows->image.x=(int) windows->image.width/2;
13362 windows->image.y=(int) windows->image.height/2;
13368 windows->image.x-=x_offset;
13375 windows->image.y-=y_offset;
13381 windows->image.x+=x_offset;
13388 windows->image.y+=y_offset;
13395 Check boundary conditions.
13397 if (windows->image.x < 0)
13398 windows->image.x=0;
13400 if ((int) (windows->image.x+windows->image.width) >
13401 windows->image.ximage->width)
13402 windows->image.x=(int) windows->image.ximage->width-windows->image.width;
13403 if (windows->image.y < 0)
13404 windows->image.y=0;
13406 if ((int) (windows->image.y+windows->image.height) >
13407 windows->image.ximage->height)
13408 windows->image.y=(int) windows->image.ximage->height-windows->image.height;
13410 Refresh Image window.
13412 (void) FormatLocaleString(text,MaxTextExtent," %ux%u%+d%+d ",
13413 windows->image.width,windows->image.height,windows->image.x,
13415 XInfoWidget(display,windows,text);
13416 XCheckRefreshWindows(display,windows);
13417 XDrawPanRectangle(display,windows);
13418 XRefreshWindow(display,&windows->image,(XEvent *) NULL);
13419 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
13423 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13427 + X T r i m I m a g e %
13431 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13433 % XTrimImage() trims the edges from the Image window.
13435 % The format of the XTrimImage method is:
13437 % MagickBooleanType XTrimImage(Display *display,
13438 % XResourceInfo *resource_info,XWindows *windows,Image *image,
13439 % ExceptionInfo *exception)
13441 % A description of each parameter follows:
13443 % o display: Specifies a connection to an X server; returned from
13446 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
13448 % o windows: Specifies a pointer to a XWindows structure.
13450 % o image: the image.
13452 % o exception: return any errors or warnings in this structure.
13455 static MagickBooleanType XTrimImage(Display *display,
13456 XResourceInfo *resource_info,XWindows *windows,Image *image,
13457 ExceptionInfo *exception)
13471 Trim edges from image.
13473 XSetCursorState(display,windows,MagickTrue);
13474 XCheckRefreshWindows(display,windows);
13476 Crop the left edge.
13478 background=XGetPixel(windows->image.ximage,0,0);
13479 trim_info.width=(size_t) windows->image.ximage->width;
13480 for (x=0; x < windows->image.ximage->width; x++)
13482 for (y=0; y < windows->image.ximage->height; y++)
13484 pixel=XGetPixel(windows->image.ximage,x,y);
13485 if (pixel != background)
13488 if (y < windows->image.ximage->height)
13491 trim_info.x=(ssize_t) x;
13492 if (trim_info.x == (ssize_t) windows->image.ximage->width)
13494 XSetCursorState(display,windows,MagickFalse);
13495 return(MagickFalse);
13498 Crop the right edge.
13500 background=XGetPixel(windows->image.ximage,windows->image.ximage->width-1,0);
13501 for (x=windows->image.ximage->width-1; x != 0; x--)
13503 for (y=0; y < windows->image.ximage->height; y++)
13505 pixel=XGetPixel(windows->image.ximage,x,y);
13506 if (pixel != background)
13509 if (y < windows->image.ximage->height)
13512 trim_info.width=(size_t) (x-trim_info.x+1);
13516 background=XGetPixel(windows->image.ximage,0,0);
13517 trim_info.height=(size_t) windows->image.ximage->height;
13518 for (y=0; y < windows->image.ximage->height; y++)
13520 for (x=0; x < windows->image.ximage->width; x++)
13522 pixel=XGetPixel(windows->image.ximage,x,y);
13523 if (pixel != background)
13526 if (x < windows->image.ximage->width)
13529 trim_info.y=(ssize_t) y;
13531 Crop the bottom edge.
13533 background=XGetPixel(windows->image.ximage,0,windows->image.ximage->height-1);
13534 for (y=windows->image.ximage->height-1; y != 0; y--)
13536 for (x=0; x < windows->image.ximage->width; x++)
13538 pixel=XGetPixel(windows->image.ximage,x,y);
13539 if (pixel != background)
13542 if (x < windows->image.ximage->width)
13545 trim_info.height=(size_t) y-trim_info.y+1;
13546 if (((unsigned int) trim_info.width != windows->image.width) ||
13547 ((unsigned int) trim_info.height != windows->image.height))
13550 Reconfigure Image window as defined by the trimming rectangle.
13552 XSetCropGeometry(display,windows,&trim_info,image);
13553 windows->image.window_changes.width=(int) trim_info.width;
13554 windows->image.window_changes.height=(int) trim_info.height;
13555 (void) XConfigureImage(display,resource_info,windows,image,exception);
13557 XSetCursorState(display,windows,MagickFalse);
13558 return(MagickTrue);
13562 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13566 + X V i s u a l D i r e c t o r y I m a g e %
13570 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13572 % XVisualDirectoryImage() creates a Visual Image Directory.
13574 % The format of the XVisualDirectoryImage method is:
13576 % Image *XVisualDirectoryImage(Display *display,
13577 % XResourceInfo *resource_info,XWindows *windows,
13578 % ExceptionInfo *exception)
13580 % A description of each parameter follows:
13582 % o display: Specifies a connection to an X server; returned from
13585 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
13587 % o windows: Specifies a pointer to a XWindows structure.
13589 % o exception: return any errors or warnings in this structure.
13592 static Image *XVisualDirectoryImage(Display *display,
13593 XResourceInfo *resource_info,XWindows *windows,ExceptionInfo *exception)
13595 #define TileImageTag "Scale/Image"
13596 #define XClientName "montage"
13629 filename[MaxTextExtent] = "\0",
13630 filenames[MaxTextExtent] = "*";
13633 background_resources;
13636 Request file name from user.
13638 XFileBrowserWidget(display,windows,"Directory",filenames);
13639 if (*filenames == '\0')
13640 return((Image *) NULL);
13642 Expand the filenames.
13644 filelist=(char **) AcquireMagickMemory(sizeof(*filelist));
13645 if (filelist == (char **) NULL)
13647 ThrowXWindowFatalException(ResourceLimitError,"MemoryAllocationFailed",
13649 return((Image *) NULL);
13652 filelist[0]=filenames;
13653 status=ExpandFilenames(&number_files,&filelist);
13654 if ((status == MagickFalse) || (number_files == 0))
13656 if (number_files == 0)
13657 ThrowXWindowFatalException(ImageError,"NoImagesWereFound",filenames)
13659 ThrowXWindowFatalException(ResourceLimitError,"MemoryAllocationFailed",
13661 return((Image *) NULL);
13664 Set image background resources.
13666 background_resources=(*resource_info);
13667 background_resources.window_id=AcquireString("");
13668 (void) FormatLocaleString(background_resources.window_id,MaxTextExtent,
13669 "0x%lx",windows->image.id);
13670 background_resources.backdrop=MagickTrue;
13672 Read each image and convert them to a tile.
13674 backdrop=(windows->visual_info->klass == TrueColor) ||
13675 (windows->visual_info->klass == DirectColor) ? MagickTrue : MagickFalse;
13676 read_info=CloneImageInfo(resource_info->image_info);
13677 (void) SetImageOption(read_info,"jpeg:size","120x120");
13678 (void) CloneString(&read_info->size,DefaultTileGeometry);
13679 (void) SetImageInfoProgressMonitor(read_info,(MagickProgressMonitor) NULL,
13681 images=NewImageList();
13682 XSetCursorState(display,windows,MagickTrue);
13683 XCheckRefreshWindows(display,windows);
13684 for (i=0; i < (int) number_files; i++)
13686 (void) CopyMagickString(read_info->filename,filelist[i],MaxTextExtent);
13687 filelist[i]=DestroyString(filelist[i]);
13688 *read_info->magick='\0';
13689 next_image=ReadImage(read_info,exception);
13690 CatchException(exception);
13691 if (next_image != (Image *) NULL)
13693 (void) DeleteImageProperty(next_image,"label");
13694 (void) SetImageProperty(next_image,"label",InterpretImageProperties(
13695 read_info,next_image,DefaultTileLabel,exception),exception);
13696 (void) ParseRegionGeometry(next_image,read_info->size,&geometry,
13698 thumbnail_image=ThumbnailImage(next_image,geometry.width,
13699 geometry.height,exception);
13700 if (thumbnail_image != (Image *) NULL)
13702 next_image=DestroyImage(next_image);
13703 next_image=thumbnail_image;
13707 (void) XDisplayBackgroundImage(display,&background_resources,
13708 next_image,exception);
13709 XSetCursorState(display,windows,MagickTrue);
13711 AppendImageToList(&images,next_image);
13712 if (images->progress_monitor != (MagickProgressMonitor) NULL)
13717 proceed=SetImageProgress(images,LoadImageTag,(MagickOffsetType) i,
13718 (MagickSizeType) number_files);
13719 if (proceed == MagickFalse)
13724 filelist=(char **) RelinquishMagickMemory(filelist);
13725 if (images == (Image *) NULL)
13727 read_info=DestroyImageInfo(read_info);
13728 XSetCursorState(display,windows,MagickFalse);
13729 ThrowXWindowFatalException(ImageError,"NoImagesWereLoaded",filenames);
13730 return((Image *) NULL);
13733 Create the Visual Image Directory.
13735 montage_info=CloneMontageInfo(read_info,(MontageInfo *) NULL);
13736 montage_info->pointsize=10;
13737 if (resource_info->font != (char *) NULL)
13738 (void) CloneString(&montage_info->font,resource_info->font);
13739 (void) CopyMagickString(montage_info->filename,filename,MaxTextExtent);
13740 montage_image=MontageImageList(read_info,montage_info,GetFirstImageInList(
13741 images),exception);
13742 images=DestroyImageList(images);
13743 montage_info=DestroyMontageInfo(montage_info);
13744 read_info=DestroyImageInfo(read_info);
13745 XSetCursorState(display,windows,MagickFalse);
13746 if (montage_image == (Image *) NULL)
13747 return(montage_image);
13748 XClientMessage(display,windows->image.id,windows->im_protocols,
13749 windows->im_next_image,CurrentTime);
13750 return(montage_image);
13754 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13758 % X D i s p l a y B a c k g r o u n d I m a g e %
13762 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13764 % XDisplayBackgroundImage() displays an image in the background of a window.
13766 % The format of the XDisplayBackgroundImage method is:
13768 % MagickBooleanType XDisplayBackgroundImage(Display *display,
13769 % XResourceInfo *resource_info,Image *image,ExceptionInfo *exception)
13771 % A description of each parameter follows:
13773 % o display: Specifies a connection to an X server; returned from
13776 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
13778 % o image: the image.
13780 % o exception: return any errors or warnings in this structure.
13783 MagickExport MagickBooleanType XDisplayBackgroundImage(Display *display,
13784 XResourceInfo *resource_info,Image *image,ExceptionInfo *exception)
13787 geometry[MaxTextExtent],
13788 visual_type[MaxTextExtent];
13801 static XStandardColormap
13805 *visual_info = (XVisualInfo *) NULL;
13826 Determine target window.
13828 assert(image != (Image *) NULL);
13829 assert(image->signature == MagickSignature);
13830 if (image->debug != MagickFalse)
13831 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
13832 resources=(*resource_info);
13833 window_info.id=(Window) NULL;
13834 root_window=XRootWindow(display,XDefaultScreen(display));
13835 if (LocaleCompare(resources.window_id,"root") == 0)
13836 window_info.id=root_window;
13839 if (isdigit((unsigned char) *resources.window_id) != 0)
13840 window_info.id=XWindowByID(display,root_window,
13841 (Window) strtol((char *) resources.window_id,(char **) NULL,0));
13842 if (window_info.id == (Window) NULL)
13843 window_info.id=XWindowByName(display,root_window,resources.window_id);
13845 if (window_info.id == (Window) NULL)
13847 ThrowXWindowFatalException(XServerError,"NoWindowWithSpecifiedIDExists",
13848 resources.window_id);
13849 return(MagickFalse);
13852 Determine window visual id.
13854 window_attributes.width=XDisplayWidth(display,XDefaultScreen(display));
13855 window_attributes.height=XDisplayHeight(display,XDefaultScreen(display));
13856 (void) CopyMagickString(visual_type,"default",MaxTextExtent);
13857 status=XGetWindowAttributes(display,window_info.id,&window_attributes);
13859 (void) FormatLocaleString(visual_type,MaxTextExtent,"0x%lx",
13860 XVisualIDFromVisual(window_attributes.visual));
13861 if (visual_info == (XVisualInfo *) NULL)
13864 Allocate standard colormap.
13866 map_info=XAllocStandardColormap();
13867 if (map_info == (XStandardColormap *) NULL)
13868 ThrowXWindowFatalException(XServerFatalError,"MemoryAllocationFailed",
13870 map_info->colormap=(Colormap) NULL;
13871 pixel.pixels=(unsigned long *) NULL;
13873 Initialize visual info.
13875 resources.map_type=(char *) NULL;
13876 resources.visual_type=visual_type;
13877 visual_info=XBestVisualInfo(display,map_info,&resources);
13878 if (visual_info == (XVisualInfo *) NULL)
13879 ThrowXWindowFatalException(XServerFatalError,"UnableToGetVisual",
13880 resources.visual_type);
13882 Initialize window info.
13884 window_info.ximage=(XImage *) NULL;
13885 window_info.matte_image=(XImage *) NULL;
13886 window_info.pixmap=(Pixmap) NULL;
13887 window_info.matte_pixmap=(Pixmap) NULL;
13890 Free previous root colors.
13892 if (window_info.id == root_window)
13893 (void) XDestroyWindowColors(display,root_window);
13895 Initialize Standard Colormap.
13897 resources.colormap=SharedColormap;
13898 XMakeStandardColormap(display,visual_info,&resources,image,map_info,&pixel,
13901 Graphic context superclass.
13903 context_values.background=pixel.background_color.pixel;
13904 context_values.foreground=pixel.foreground_color.pixel;
13905 pixel.annotate_context=XCreateGC(display,window_info.id,
13906 (size_t) (GCBackground | GCForeground),&context_values);
13907 if (pixel.annotate_context == (GC) NULL)
13908 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
13911 Initialize Image window attributes.
13913 window_info.name=AcquireString("\0");
13914 window_info.icon_name=AcquireString("\0");
13915 XGetWindowInfo(display,visual_info,map_info,&pixel,(XFontStruct *) NULL,
13916 &resources,&window_info);
13918 Create the X image.
13920 window_info.width=(unsigned int) image->columns;
13921 window_info.height=(unsigned int) image->rows;
13922 if ((image->columns != window_info.width) ||
13923 (image->rows != window_info.height))
13924 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
13926 (void) FormatLocaleString(geometry,MaxTextExtent,"%ux%u+0+0>",
13927 window_attributes.width,window_attributes.height);
13928 geometry_info.width=window_info.width;
13929 geometry_info.height=window_info.height;
13930 geometry_info.x=(ssize_t) window_info.x;
13931 geometry_info.y=(ssize_t) window_info.y;
13932 (void) ParseMetaGeometry(geometry,&geometry_info.x,&geometry_info.y,
13933 &geometry_info.width,&geometry_info.height);
13934 window_info.width=(unsigned int) geometry_info.width;
13935 window_info.height=(unsigned int) geometry_info.height;
13936 window_info.x=(int) geometry_info.x;
13937 window_info.y=(int) geometry_info.y;
13938 status=XMakeImage(display,&resources,&window_info,image,window_info.width,
13939 window_info.height,exception);
13940 if (status == MagickFalse)
13941 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
13945 if (image->debug != MagickFalse)
13947 (void) LogMagickEvent(X11Event,GetMagickModule(),
13948 "Image: %s[%.20g] %.20gx%.20g ",image->filename,(double) image->scene,
13949 (double) image->columns,(double) image->rows);
13950 if (image->colors != 0)
13951 (void) LogMagickEvent(X11Event,GetMagickModule(),"%.20gc ",(double)
13953 (void) LogMagickEvent(X11Event,GetMagickModule(),"%s",image->magick);
13956 Adjust image dimensions as specified by backdrop or geometry options.
13958 width=(int) window_info.width;
13959 height=(int) window_info.height;
13960 if (resources.backdrop != MagickFalse)
13963 Center image on window.
13965 window_info.x=(window_attributes.width/2)-
13966 (window_info.ximage->width/2);
13967 window_info.y=(window_attributes.height/2)-
13968 (window_info.ximage->height/2);
13969 width=window_attributes.width;
13970 height=window_attributes.height;
13972 if ((resources.image_geometry != (char *) NULL) &&
13973 (*resources.image_geometry != '\0'))
13976 default_geometry[MaxTextExtent];
13986 User specified geometry.
13988 size_hints=XAllocSizeHints();
13989 if (size_hints == (XSizeHints *) NULL)
13990 ThrowXWindowFatalException(ResourceLimitFatalError,
13991 "MemoryAllocationFailed",image->filename);
13992 size_hints->flags=0L;
13993 (void) FormatLocaleString(default_geometry,MaxTextExtent,"%dx%d",
13995 flags=XWMGeometry(display,visual_info->screen,resources.image_geometry,
13996 default_geometry,window_info.border_width,size_hints,&window_info.x,
13997 &window_info.y,&width,&height,&gravity);
13998 if (flags & (XValue | YValue))
14000 width=window_attributes.width;
14001 height=window_attributes.height;
14003 (void) XFree((void *) size_hints);
14006 Create the X pixmap.
14008 window_info.pixmap=XCreatePixmap(display,window_info.id,(unsigned int) width,
14009 (unsigned int) height,window_info.depth);
14010 if (window_info.pixmap == (Pixmap) NULL)
14011 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXPixmap",
14014 Display pixmap on the window.
14016 if (((unsigned int) width > window_info.width) ||
14017 ((unsigned int) height > window_info.height))
14018 (void) XFillRectangle(display,window_info.pixmap,
14019 window_info.annotate_context,0,0,(unsigned int) width,
14020 (unsigned int) height);
14021 (void) XPutImage(display,window_info.pixmap,window_info.annotate_context,
14022 window_info.ximage,0,0,window_info.x,window_info.y,(unsigned int)
14023 window_info.width,(unsigned int) window_info.height);
14024 (void) XSetWindowBackgroundPixmap(display,window_info.id,window_info.pixmap);
14025 (void) XClearWindow(display,window_info.id);
14026 delay=1000*image->delay/MagickMax(image->ticks_per_second,1L);
14027 XDelay(display,delay == 0UL ? 10UL : delay);
14028 (void) XSync(display,MagickFalse);
14029 return(window_info.id == root_window ? MagickTrue : MagickFalse);
14033 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
14037 + X D i s p l a y I m a g e %
14041 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
14043 % XDisplayImage() displays an image via X11. A new image is created and
14044 % returned if the user interactively transforms the displayed image.
14046 % The format of the XDisplayImage method is:
14048 % Image *XDisplayImage(Display *display,XResourceInfo *resource_info,
14049 % char **argv,int argc,Image **image,size_t *state,
14050 % ExceptionInfo *exception)
14052 % A description of each parameter follows:
14054 % o nexus: Method XDisplayImage returns an image when the
14055 % user chooses 'Open Image' from the command menu or picks a tile
14056 % from the image directory. Otherwise a null image is returned.
14058 % o display: Specifies a connection to an X server; returned from
14061 % o resource_info: Specifies a pointer to a X11 XResourceInfo structure.
14063 % o argv: Specifies the application's argument list.
14065 % o argc: Specifies the number of arguments.
14067 % o image: Specifies an address to an address of an Image structure;
14069 % o exception: return any errors or warnings in this structure.
14072 MagickExport Image *XDisplayImage(Display *display,XResourceInfo *resource_info,
14073 char **argv,int argc,Image **image,size_t *state,ExceptionInfo *exception)
14075 #define MagnifySize 256 /* must be a power of 2 */
14076 #define MagickMenus 10
14077 #define MagickTitle "Commands"
14104 "Visual Directory...",
14150 "Contrast Stretch...",
14151 "Sigmoidal Contrast...",
14185 "Charcoal Draw...",
14199 "Region of Interest...",
14202 *MiscellanyMenu[] =
14217 "Browse Documentation",
14244 **Menus[MagickMenus] =
14282 VisualDirectoryCommand,
14296 OriginalSizeCommand,
14303 TransformCommands[] =
14309 RotateRightCommand,
14316 EnhanceCommands[] =
14324 ContrastStretchCommand,
14325 SigmoidalContrastCommand,
14333 EffectsCommands[] =
14337 ReduceNoiseCommand,
14357 CharcoalDrawCommand
14359 ImageEditCommands[] =
14370 RegionofInterestCommand
14372 MiscellanyCommands[] =
14376 ShowPreviewCommand,
14377 ShowHistogramCommand,
14386 BrowseDocumentationCommand,
14389 ShortCutsCommands[] =
14401 VirtualCommands[] =
14410 *Commands[MagickMenus] =
14420 MiscellanyCommands,
14425 command[MaxTextExtent],
14427 geometry[MaxTextExtent],
14428 resource_name[MaxTextExtent];
14455 working_directory[MaxTextExtent];
14461 *magick_windows[MaxXWindows];
14463 static unsigned int
14523 assert(image != (Image **) NULL);
14524 assert((*image)->signature == MagickSignature);
14525 if ((*image)->debug != MagickFalse)
14526 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",(*image)->filename);
14527 display_image=(*image);
14528 warning_handler=(WarningHandler) NULL;
14529 windows=XSetWindows((XWindows *) ~0);
14530 if (windows != (XWindows *) NULL)
14535 status=chdir(working_directory);
14537 (void) ThrowMagickException(exception,GetMagickModule(),FileOpenError,
14538 "UnableToOpenFile","%s",working_directory);
14539 warning_handler=resource_info->display_warnings ?
14540 SetErrorHandler(XWarning) : SetErrorHandler((ErrorHandler) NULL);
14541 warning_handler=resource_info->display_warnings ?
14542 SetWarningHandler(XWarning) : SetWarningHandler((WarningHandler) NULL);
14547 Allocate windows structure.
14549 resource_info->colors=display_image->colors;
14550 windows=XSetWindows(XInitializeWindows(display,resource_info));
14551 if (windows == (XWindows *) NULL)
14552 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateWindow",
14553 (*image)->filename);
14555 Initialize window id's.
14558 magick_windows[number_windows++]=(&windows->icon);
14559 magick_windows[number_windows++]=(&windows->backdrop);
14560 magick_windows[number_windows++]=(&windows->image);
14561 magick_windows[number_windows++]=(&windows->info);
14562 magick_windows[number_windows++]=(&windows->command);
14563 magick_windows[number_windows++]=(&windows->widget);
14564 magick_windows[number_windows++]=(&windows->popup);
14565 magick_windows[number_windows++]=(&windows->magnify);
14566 magick_windows[number_windows++]=(&windows->pan);
14567 for (i=0; i < (int) number_windows; i++)
14568 magick_windows[i]->id=(Window) NULL;
14573 Initialize font info.
14575 if (windows->font_info != (XFontStruct *) NULL)
14576 (void) XFreeFont(display,windows->font_info);
14577 windows->font_info=XBestFont(display,resource_info,MagickFalse);
14578 if (windows->font_info == (XFontStruct *) NULL)
14579 ThrowXWindowFatalException(XServerFatalError,"UnableToLoadFont",
14580 resource_info->font);
14582 Initialize Standard Colormap.
14584 map_info=windows->map_info;
14585 icon_map=windows->icon_map;
14586 visual_info=windows->visual_info;
14587 icon_visual=windows->icon_visual;
14588 pixel=windows->pixel_info;
14589 icon_pixel=windows->icon_pixel;
14590 font_info=windows->font_info;
14591 icon_resources=windows->icon_resources;
14592 class_hints=windows->class_hints;
14593 manager_hints=windows->manager_hints;
14594 root_window=XRootWindow(display,visual_info->screen);
14595 nexus=NewImageList();
14596 if (display_image->debug != MagickFalse)
14598 (void) LogMagickEvent(X11Event,GetMagickModule(),
14599 "Image: %s[%.20g] %.20gx%.20g ",display_image->filename,
14600 (double) display_image->scene,(double) display_image->columns,
14601 (double) display_image->rows);
14602 if (display_image->colors != 0)
14603 (void) LogMagickEvent(X11Event,GetMagickModule(),"%.20gc ",(double)
14604 display_image->colors);
14605 (void) LogMagickEvent(X11Event,GetMagickModule(),"%s",
14606 display_image->magick);
14608 XMakeStandardColormap(display,visual_info,resource_info,display_image,
14609 map_info,pixel,exception);
14610 display_image->taint=MagickFalse;
14612 Initialize graphic context.
14614 windows->context.id=(Window) NULL;
14615 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
14616 resource_info,&windows->context);
14617 (void) CloneString(&class_hints->res_name,resource_info->client_name);
14618 (void) CloneString(&class_hints->res_class,resource_info->client_name);
14619 class_hints->res_class[0]=(char) toupper((int) class_hints->res_class[0]);
14620 manager_hints->flags=InputHint | StateHint;
14621 manager_hints->input=MagickFalse;
14622 manager_hints->initial_state=WithdrawnState;
14623 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14624 &windows->context);
14625 if (display_image->debug != MagickFalse)
14626 (void) LogMagickEvent(X11Event,GetMagickModule(),
14627 "Window id: 0x%lx (context)",windows->context.id);
14628 context_values.background=pixel->background_color.pixel;
14629 context_values.font=font_info->fid;
14630 context_values.foreground=pixel->foreground_color.pixel;
14631 context_values.graphics_exposures=MagickFalse;
14632 context_mask=(MagickStatusType)
14633 (GCBackground | GCFont | GCForeground | GCGraphicsExposures);
14634 if (pixel->annotate_context != (GC) NULL)
14635 (void) XFreeGC(display,pixel->annotate_context);
14636 pixel->annotate_context=XCreateGC(display,windows->context.id,
14637 context_mask,&context_values);
14638 if (pixel->annotate_context == (GC) NULL)
14639 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
14640 display_image->filename);
14641 context_values.background=pixel->depth_color.pixel;
14642 if (pixel->widget_context != (GC) NULL)
14643 (void) XFreeGC(display,pixel->widget_context);
14644 pixel->widget_context=XCreateGC(display,windows->context.id,context_mask,
14646 if (pixel->widget_context == (GC) NULL)
14647 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
14648 display_image->filename);
14649 context_values.background=pixel->foreground_color.pixel;
14650 context_values.foreground=pixel->background_color.pixel;
14651 context_values.plane_mask=context_values.background ^
14652 context_values.foreground;
14653 if (pixel->highlight_context != (GC) NULL)
14654 (void) XFreeGC(display,pixel->highlight_context);
14655 pixel->highlight_context=XCreateGC(display,windows->context.id,
14656 (size_t) (context_mask | GCPlaneMask),&context_values);
14657 if (pixel->highlight_context == (GC) NULL)
14658 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
14659 display_image->filename);
14660 (void) XDestroyWindow(display,windows->context.id);
14662 Initialize icon window.
14664 XGetWindowInfo(display,icon_visual,icon_map,icon_pixel,(XFontStruct *) NULL,
14665 icon_resources,&windows->icon);
14666 windows->icon.geometry=resource_info->icon_geometry;
14667 XBestIconSize(display,&windows->icon,display_image);
14668 windows->icon.attributes.colormap=XDefaultColormap(display,
14669 icon_visual->screen);
14670 windows->icon.attributes.event_mask=ExposureMask | StructureNotifyMask;
14671 manager_hints->flags=InputHint | StateHint;
14672 manager_hints->input=MagickFalse;
14673 manager_hints->initial_state=IconicState;
14674 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14676 if (display_image->debug != MagickFalse)
14677 (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (icon)",
14680 Initialize graphic context for icon window.
14682 if (icon_pixel->annotate_context != (GC) NULL)
14683 (void) XFreeGC(display,icon_pixel->annotate_context);
14684 context_values.background=icon_pixel->background_color.pixel;
14685 context_values.foreground=icon_pixel->foreground_color.pixel;
14686 icon_pixel->annotate_context=XCreateGC(display,windows->icon.id,
14687 (size_t) (GCBackground | GCForeground),&context_values);
14688 if (icon_pixel->annotate_context == (GC) NULL)
14689 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateGraphicContext",
14690 display_image->filename);
14691 windows->icon.annotate_context=icon_pixel->annotate_context;
14693 Initialize Image window.
14695 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,resource_info,
14697 windows->image.shape=MagickTrue; /* non-rectangular shape hint */
14698 if (resource_info->use_shared_memory == MagickFalse)
14699 windows->image.shared_memory=MagickFalse;
14700 if ((resource_info->title != (char *) NULL) && !(*state & MontageImageState))
14705 title=InterpretImageProperties(resource_info->image_info,display_image,
14706 resource_info->title,exception);
14707 (void) CopyMagickString(windows->image.name,title,MaxTextExtent);
14708 (void) CopyMagickString(windows->image.icon_name,title,MaxTextExtent);
14709 title=DestroyString(title);
14714 filename[MaxTextExtent];
14717 Window name is the base of the filename.
14719 GetPathComponent(display_image->magick_filename,TailPath,filename);
14720 if (display_image->scene == 0)
14721 (void) FormatLocaleString(windows->image.name,MaxTextExtent,
14722 "%s: %s",MagickPackageName,filename);
14724 (void) FormatLocaleString(windows->image.name,MaxTextExtent,
14725 "%s: %s[scene: %.20g frames: %.20g]",MagickPackageName,filename,
14726 (double) display_image->scene,(double) GetImageListLength(
14728 (void) CopyMagickString(windows->image.icon_name,filename,MaxTextExtent);
14730 if (resource_info->immutable)
14731 windows->image.immutable=MagickTrue;
14732 windows->image.use_pixmap=resource_info->use_pixmap;
14733 windows->image.geometry=resource_info->image_geometry;
14734 (void) FormatLocaleString(geometry,MaxTextExtent,"%ux%u+0+0>!",
14735 XDisplayWidth(display,visual_info->screen),
14736 XDisplayHeight(display,visual_info->screen));
14737 geometry_info.width=display_image->columns;
14738 geometry_info.height=display_image->rows;
14741 (void) ParseMetaGeometry(geometry,&geometry_info.x,&geometry_info.y,
14742 &geometry_info.width,&geometry_info.height);
14743 windows->image.width=(unsigned int) geometry_info.width;
14744 windows->image.height=(unsigned int) geometry_info.height;
14745 windows->image.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
14746 ButtonReleaseMask | EnterWindowMask | ExposureMask | KeyPressMask |
14747 KeyReleaseMask | LeaveWindowMask | OwnerGrabButtonMask |
14748 PropertyChangeMask | StructureNotifyMask | SubstructureNotifyMask;
14749 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
14750 resource_info,&windows->backdrop);
14751 if ((resource_info->backdrop) || (windows->backdrop.id != (Window) NULL))
14754 Initialize backdrop window.
14756 windows->backdrop.x=0;
14757 windows->backdrop.y=0;
14758 (void) CloneString(&windows->backdrop.name,"Backdrop");
14759 windows->backdrop.flags=(size_t) (USSize | USPosition);
14760 windows->backdrop.width=(unsigned int)
14761 XDisplayWidth(display,visual_info->screen);
14762 windows->backdrop.height=(unsigned int)
14763 XDisplayHeight(display,visual_info->screen);
14764 windows->backdrop.border_width=0;
14765 windows->backdrop.immutable=MagickTrue;
14766 windows->backdrop.attributes.do_not_propagate_mask=ButtonPressMask |
14768 windows->backdrop.attributes.event_mask=ButtonPressMask | KeyPressMask |
14769 StructureNotifyMask;
14770 manager_hints->flags=IconWindowHint | InputHint | StateHint;
14771 manager_hints->icon_window=windows->icon.id;
14772 manager_hints->input=MagickTrue;
14773 manager_hints->initial_state=resource_info->iconic ? IconicState :
14775 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14776 &windows->backdrop);
14777 if (display_image->debug != MagickFalse)
14778 (void) LogMagickEvent(X11Event,GetMagickModule(),
14779 "Window id: 0x%lx (backdrop)",windows->backdrop.id);
14780 (void) XMapWindow(display,windows->backdrop.id);
14781 (void) XClearWindow(display,windows->backdrop.id);
14782 if (windows->image.id != (Window) NULL)
14784 (void) XDestroyWindow(display,windows->image.id);
14785 windows->image.id=(Window) NULL;
14788 Position image in the center the backdrop.
14790 windows->image.flags|=USPosition;
14791 windows->image.x=(XDisplayWidth(display,visual_info->screen)/2)-
14792 (windows->image.width/2);
14793 windows->image.y=(XDisplayHeight(display,visual_info->screen)/2)-
14794 (windows->image.height/2);
14796 manager_hints->flags=IconWindowHint | InputHint | StateHint;
14797 manager_hints->icon_window=windows->icon.id;
14798 manager_hints->input=MagickTrue;
14799 manager_hints->initial_state=resource_info->iconic ? IconicState :
14801 if (windows->group_leader.id != (Window) NULL)
14806 manager_hints->flags|=WindowGroupHint;
14807 manager_hints->window_group=windows->group_leader.id;
14808 (void) XSelectInput(display,windows->group_leader.id,StructureNotifyMask);
14809 if (display_image->debug != MagickFalse)
14810 (void) LogMagickEvent(X11Event,GetMagickModule(),
14811 "Window id: 0x%lx (group leader)",windows->group_leader.id);
14813 XMakeWindow(display,
14814 (Window) (resource_info->backdrop ? windows->backdrop.id : root_window),
14815 argv,argc,class_hints,manager_hints,&windows->image);
14816 (void) XChangeProperty(display,windows->image.id,windows->im_protocols,
14817 XA_STRING,8,PropModeReplace,(unsigned char *) NULL,0);
14818 if (windows->group_leader.id != (Window) NULL)
14819 (void) XSetTransientForHint(display,windows->image.id,
14820 windows->group_leader.id);
14821 if (display_image->debug != MagickFalse)
14822 (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (image)",
14823 windows->image.id);
14825 Initialize Info widget.
14827 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,resource_info,
14829 (void) CloneString(&windows->info.name,"Info");
14830 (void) CloneString(&windows->info.icon_name,"Info");
14831 windows->info.border_width=1;
14834 windows->info.flags|=PPosition;
14835 windows->info.attributes.win_gravity=UnmapGravity;
14836 windows->info.attributes.event_mask=ButtonPressMask | ExposureMask |
14837 StructureNotifyMask;
14838 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
14839 manager_hints->input=MagickFalse;
14840 manager_hints->initial_state=NormalState;
14841 manager_hints->window_group=windows->image.id;
14842 XMakeWindow(display,windows->image.id,argv,argc,class_hints,manager_hints,
14844 windows->info.highlight_stipple=XCreateBitmapFromData(display,
14845 windows->info.id,(char *) HighlightBitmap,HighlightWidth,HighlightHeight);
14846 windows->info.shadow_stipple=XCreateBitmapFromData(display,
14847 windows->info.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
14848 (void) XSetTransientForHint(display,windows->info.id,windows->image.id);
14849 if (windows->image.mapped != MagickFalse)
14850 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
14851 if (display_image->debug != MagickFalse)
14852 (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (info)",
14855 Initialize Command widget.
14857 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
14858 resource_info,&windows->command);
14859 windows->command.data=MagickMenus;
14860 (void) XCommandWidget(display,windows,CommandMenu,(XEvent *) NULL);
14861 (void) FormatLocaleString(resource_name,MaxTextExtent,"%s.command",
14862 resource_info->client_name);
14863 windows->command.geometry=XGetResourceClass(resource_info->resource_database,
14864 resource_name,"geometry",(char *) NULL);
14865 (void) CloneString(&windows->command.name,MagickTitle);
14866 windows->command.border_width=0;
14867 windows->command.flags|=PPosition;
14868 windows->command.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
14869 ButtonReleaseMask | EnterWindowMask | ExposureMask | LeaveWindowMask |
14870 OwnerGrabButtonMask | StructureNotifyMask;
14871 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
14872 manager_hints->input=MagickTrue;
14873 manager_hints->initial_state=NormalState;
14874 manager_hints->window_group=windows->image.id;
14875 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14876 &windows->command);
14877 windows->command.highlight_stipple=XCreateBitmapFromData(display,
14878 windows->command.id,(char *) HighlightBitmap,HighlightWidth,
14880 windows->command.shadow_stipple=XCreateBitmapFromData(display,
14881 windows->command.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
14882 (void) XSetTransientForHint(display,windows->command.id,windows->image.id);
14883 if (windows->command.mapped != MagickFalse)
14884 (void) XMapRaised(display,windows->command.id);
14885 if (display_image->debug != MagickFalse)
14886 (void) LogMagickEvent(X11Event,GetMagickModule(),
14887 "Window id: 0x%lx (command)",windows->command.id);
14889 Initialize Widget window.
14891 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
14892 resource_info,&windows->widget);
14893 (void) FormatLocaleString(resource_name,MaxTextExtent,"%s.widget",
14894 resource_info->client_name);
14895 windows->widget.geometry=XGetResourceClass(resource_info->resource_database,
14896 resource_name,"geometry",(char *) NULL);
14897 windows->widget.border_width=0;
14898 windows->widget.flags|=PPosition;
14899 windows->widget.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
14900 ButtonReleaseMask | EnterWindowMask | ExposureMask | KeyPressMask |
14901 KeyReleaseMask | LeaveWindowMask | OwnerGrabButtonMask |
14902 StructureNotifyMask;
14903 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
14904 manager_hints->input=MagickTrue;
14905 manager_hints->initial_state=NormalState;
14906 manager_hints->window_group=windows->image.id;
14907 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14909 windows->widget.highlight_stipple=XCreateBitmapFromData(display,
14910 windows->widget.id,(char *) HighlightBitmap,HighlightWidth,HighlightHeight);
14911 windows->widget.shadow_stipple=XCreateBitmapFromData(display,
14912 windows->widget.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
14913 (void) XSetTransientForHint(display,windows->widget.id,windows->image.id);
14914 if (display_image->debug != MagickFalse)
14915 (void) LogMagickEvent(X11Event,GetMagickModule(),
14916 "Window id: 0x%lx (widget)",windows->widget.id);
14918 Initialize popup window.
14920 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
14921 resource_info,&windows->popup);
14922 windows->popup.border_width=0;
14923 windows->popup.flags|=PPosition;
14924 windows->popup.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
14925 ButtonReleaseMask | EnterWindowMask | ExposureMask | KeyPressMask |
14926 KeyReleaseMask | LeaveWindowMask | StructureNotifyMask;
14927 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
14928 manager_hints->input=MagickTrue;
14929 manager_hints->initial_state=NormalState;
14930 manager_hints->window_group=windows->image.id;
14931 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14933 windows->popup.highlight_stipple=XCreateBitmapFromData(display,
14934 windows->popup.id,(char *) HighlightBitmap,HighlightWidth,HighlightHeight);
14935 windows->popup.shadow_stipple=XCreateBitmapFromData(display,
14936 windows->popup.id,(char *) ShadowBitmap,ShadowWidth,ShadowHeight);
14937 (void) XSetTransientForHint(display,windows->popup.id,windows->image.id);
14938 if (display_image->debug != MagickFalse)
14939 (void) LogMagickEvent(X11Event,GetMagickModule(),
14940 "Window id: 0x%lx (pop up)",windows->popup.id);
14942 Initialize Magnify window and cursor.
14944 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
14945 resource_info,&windows->magnify);
14946 if (resource_info->use_shared_memory == MagickFalse)
14947 windows->magnify.shared_memory=MagickFalse;
14948 (void) FormatLocaleString(resource_name,MaxTextExtent,"%s.magnify",
14949 resource_info->client_name);
14950 windows->magnify.geometry=XGetResourceClass(resource_info->resource_database,
14951 resource_name,"geometry",(char *) NULL);
14952 (void) FormatLocaleString(windows->magnify.name,MaxTextExtent,"Magnify %uX",
14953 resource_info->magnify);
14954 if (windows->magnify.cursor != (Cursor) NULL)
14955 (void) XFreeCursor(display,windows->magnify.cursor);
14956 windows->magnify.cursor=XMakeCursor(display,windows->image.id,
14957 map_info->colormap,resource_info->background_color,
14958 resource_info->foreground_color);
14959 if (windows->magnify.cursor == (Cursor) NULL)
14960 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateCursor",
14961 display_image->filename);
14962 windows->magnify.width=MagnifySize;
14963 windows->magnify.height=MagnifySize;
14964 windows->magnify.flags|=PPosition;
14965 windows->magnify.min_width=MagnifySize;
14966 windows->magnify.min_height=MagnifySize;
14967 windows->magnify.width_inc=MagnifySize;
14968 windows->magnify.height_inc=MagnifySize;
14969 windows->magnify.data=resource_info->magnify;
14970 windows->magnify.attributes.cursor=windows->magnify.cursor;
14971 windows->magnify.attributes.event_mask=ButtonPressMask | ButtonReleaseMask |
14972 ExposureMask | KeyPressMask | KeyReleaseMask | OwnerGrabButtonMask |
14973 StructureNotifyMask;
14974 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
14975 manager_hints->input=MagickTrue;
14976 manager_hints->initial_state=NormalState;
14977 manager_hints->window_group=windows->image.id;
14978 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
14979 &windows->magnify);
14980 if (display_image->debug != MagickFalse)
14981 (void) LogMagickEvent(X11Event,GetMagickModule(),
14982 "Window id: 0x%lx (magnify)",windows->magnify.id);
14983 (void) XSetTransientForHint(display,windows->magnify.id,windows->image.id);
14985 Initialize panning window.
14987 XGetWindowInfo(display,visual_info,map_info,pixel,font_info,
14988 resource_info,&windows->pan);
14989 (void) CloneString(&windows->pan.name,"Pan Icon");
14990 windows->pan.width=windows->icon.width;
14991 windows->pan.height=windows->icon.height;
14992 (void) FormatLocaleString(resource_name,MaxTextExtent,"%s.pan",
14993 resource_info->client_name);
14994 windows->pan.geometry=XGetResourceClass(resource_info->resource_database,
14995 resource_name,"geometry",(char *) NULL);
14996 (void) XParseGeometry(windows->pan.geometry,&windows->pan.x,&windows->pan.y,
14997 &windows->pan.width,&windows->pan.height);
14998 windows->pan.flags|=PPosition;
14999 windows->pan.immutable=MagickTrue;
15000 windows->pan.attributes.event_mask=ButtonMotionMask | ButtonPressMask |
15001 ButtonReleaseMask | ExposureMask | KeyPressMask | KeyReleaseMask |
15002 StructureNotifyMask;
15003 manager_hints->flags=InputHint | StateHint | WindowGroupHint;
15004 manager_hints->input=MagickFalse;
15005 manager_hints->initial_state=NormalState;
15006 manager_hints->window_group=windows->image.id;
15007 XMakeWindow(display,root_window,argv,argc,class_hints,manager_hints,
15009 if (display_image->debug != MagickFalse)
15010 (void) LogMagickEvent(X11Event,GetMagickModule(),"Window id: 0x%lx (pan)",
15012 (void) XSetTransientForHint(display,windows->pan.id,windows->image.id);
15013 if (windows->info.mapped != MagickFalse)
15014 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
15015 if ((windows->image.mapped == MagickFalse) ||
15016 (windows->backdrop.id != (Window) NULL))
15017 (void) XMapWindow(display,windows->image.id);
15019 Set our progress monitor and warning handlers.
15021 if (warning_handler == (WarningHandler) NULL)
15023 warning_handler=resource_info->display_warnings ?
15024 SetErrorHandler(XWarning) : SetErrorHandler((ErrorHandler) NULL);
15025 warning_handler=resource_info->display_warnings ?
15026 SetWarningHandler(XWarning) : SetWarningHandler((WarningHandler) NULL);
15029 Initialize Image and Magnify X images.
15031 windows->image.x=0;
15032 windows->image.y=0;
15033 windows->magnify.shape=MagickFalse;
15034 width=(unsigned int) display_image->columns;
15035 height=(unsigned int) display_image->rows;
15036 if ((display_image->columns != width) || (display_image->rows != height))
15037 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
15038 display_image->filename);
15039 status=XMakeImage(display,resource_info,&windows->image,display_image,
15040 width,height,exception);
15041 if (status == MagickFalse)
15042 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
15043 display_image->filename);
15044 status=XMakeImage(display,resource_info,&windows->magnify,(Image *) NULL,
15045 windows->magnify.width,windows->magnify.height,exception);
15046 if (status == MagickFalse)
15047 ThrowXWindowFatalException(XServerFatalError,"UnableToCreateXImage",
15048 display_image->filename);
15049 if (windows->magnify.mapped != MagickFalse)
15050 (void) XMapRaised(display,windows->magnify.id);
15051 if (windows->pan.mapped != MagickFalse)
15052 (void) XMapRaised(display,windows->pan.id);
15053 windows->image.window_changes.width=(int) display_image->columns;
15054 windows->image.window_changes.height=(int) display_image->rows;
15055 (void) XConfigureImage(display,resource_info,windows,display_image,exception);
15056 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
15057 (void) XSync(display,MagickFalse);
15061 delay=display_image->delay/MagickMax(display_image->ticks_per_second,1L);
15062 timer=time((time_t *) NULL)+(delay == 0 ? 1 : delay)+1;
15064 if (resource_info->update != MagickFalse)
15070 Determine when file data was last modified.
15072 status=GetPathAttributes(display_image->filename,&attributes);
15073 if (status != MagickFalse)
15074 update_time=attributes.st_mtime;
15076 *state&=(~FormerImageState);
15077 *state&=(~MontageImageState);
15078 *state&=(~NextImageState);
15082 Handle a window event.
15084 if (windows->image.mapped != MagickFalse)
15085 if ((display_image->delay != 0) || (resource_info->update != 0))
15087 if (timer < time((time_t *) NULL))
15089 if (resource_info->update == MagickFalse)
15090 *state|=NextImageState | ExitState;
15097 Determine if image file was modified.
15099 status=GetPathAttributes(display_image->filename,&attributes);
15100 if (status != MagickFalse)
15101 if (update_time != attributes.st_mtime)
15106 (void) FormatLocaleString(
15107 resource_info->image_info->filename,MaxTextExtent,
15108 "%s:%s",display_image->magick,
15109 display_image->filename);
15110 nexus=ReadImage(resource_info->image_info,exception);
15111 if (nexus != (Image *) NULL)
15113 nexus=DestroyImage(nexus);
15114 *state|=NextImageState | ExitState;
15117 delay=display_image->delay/MagickMax(
15118 display_image->ticks_per_second,1L);
15119 timer=time((time_t *) NULL)+(delay == 0 ? 1 : delay)+1;
15122 if (XEventsQueued(display,QueuedAfterFlush) == 0)
15125 Do not block if delay > 0.
15127 XDelay(display,SuspendTime << 2);
15131 timestamp=time((time_t *) NULL);
15132 (void) XNextEvent(display,&event);
15133 if (windows->image.stasis == MagickFalse)
15134 windows->image.stasis=(time((time_t *) NULL)-timestamp) > 0 ?
15135 MagickTrue : MagickFalse;
15136 if (windows->magnify.stasis == MagickFalse)
15137 windows->magnify.stasis=(time((time_t *) NULL)-timestamp) > 0 ?
15138 MagickTrue : MagickFalse;
15139 if (event.xany.window == windows->command.id)
15142 Select a command from the Command widget.
15144 id=XCommandWidget(display,windows,CommandMenu,&event);
15147 (void) CopyMagickString(command,CommandMenu[id],MaxTextExtent);
15148 command_type=CommandMenus[id];
15149 if (id < MagickMenus)
15152 Select a command from a pop-up menu.
15154 entry=XMenuWidget(display,windows,CommandMenu[id],Menus[id],
15158 (void) CopyMagickString(command,Menus[id][entry],MaxTextExtent);
15159 command_type=Commands[id][entry];
15161 if (command_type != NullCommand)
15162 nexus=XMagickCommand(display,resource_info,windows,command_type,
15163 &display_image,exception);
15166 switch (event.type)
15170 if (display_image->debug != MagickFalse)
15171 (void) LogMagickEvent(X11Event,GetMagickModule(),
15172 "Button Press: 0x%lx %u +%d+%d",event.xbutton.window,
15173 event.xbutton.button,event.xbutton.x,event.xbutton.y);
15174 if ((event.xbutton.button == Button3) &&
15175 (event.xbutton.state & Mod1Mask))
15178 Convert Alt-Button3 to Button2.
15180 event.xbutton.button=Button2;
15181 event.xbutton.state&=(~Mod1Mask);
15183 if (event.xbutton.window == windows->backdrop.id)
15185 (void) XSetInputFocus(display,event.xbutton.window,RevertToParent,
15186 event.xbutton.time);
15189 if (event.xbutton.window == windows->image.id)
15191 switch (event.xbutton.button)
15195 if (resource_info->immutable)
15198 Select a command from the Virtual menu.
15200 entry=XMenuWidget(display,windows,"Commands",VirtualMenu,
15203 nexus=XMagickCommand(display,resource_info,windows,
15204 VirtualCommands[entry],&display_image,exception);
15208 Map/unmap Command widget.
15210 if (windows->command.mapped != MagickFalse)
15211 (void) XWithdrawWindow(display,windows->command.id,
15212 windows->command.screen);
15215 (void) XCommandWidget(display,windows,CommandMenu,
15217 (void) XMapRaised(display,windows->command.id);
15224 User pressed the image magnify button.
15226 (void) XMagickCommand(display,resource_info,windows,ZoomCommand,
15227 &display_image,exception);
15228 XMagnifyImage(display,windows,&event,exception);
15233 if (resource_info->immutable)
15236 Select a command from the Virtual menu.
15238 entry=XMenuWidget(display,windows,"Commands",VirtualMenu,
15241 nexus=XMagickCommand(display,resource_info,windows,
15242 VirtualCommands[entry],&display_image,exception);
15245 if (display_image->montage != (char *) NULL)
15248 Open or delete a tile from a visual image directory.
15250 nexus=XTileImage(display,resource_info,windows,
15251 display_image,&event,exception);
15252 if (nexus != (Image *) NULL)
15253 *state|=MontageImageState | NextImageState | ExitState;
15254 vid_info.x=(short int) windows->image.x;
15255 vid_info.y=(short int) windows->image.y;
15259 Select a command from the Short Cuts menu.
15261 entry=XMenuWidget(display,windows,"Short Cuts",ShortCutsMenu,
15264 nexus=XMagickCommand(display,resource_info,windows,
15265 ShortCutsCommands[entry],&display_image,exception);
15273 XTranslateImage(display,windows,*image,XK_Up);
15281 XTranslateImage(display,windows,*image,XK_Down);
15289 if (event.xbutton.window == windows->magnify.id)
15309 MagnifyCommands[] =
15322 Select a magnify factor from the pop-up menu.
15324 factor=XMenuWidget(display,windows,"Magnify",MagnifyMenu,command);
15326 XMagnifyWindowCommand(display,windows,0,MagnifyCommands[factor],
15330 if (event.xbutton.window == windows->pan.id)
15332 switch (event.xbutton.button)
15339 XTranslateImage(display,windows,*image,XK_Up);
15347 XTranslateImage(display,windows,*image,XK_Down);
15352 XPanImage(display,windows,&event,exception);
15358 delay=display_image->delay/MagickMax(display_image->ticks_per_second,
15360 timer=time((time_t *) NULL)+(delay == 0 ? 1 : delay)+1;
15363 case ButtonRelease:
15365 if (display_image->debug != MagickFalse)
15366 (void) LogMagickEvent(X11Event,GetMagickModule(),
15367 "Button Release: 0x%lx %u +%d+%d",event.xbutton.window,
15368 event.xbutton.button,event.xbutton.x,event.xbutton.y);
15371 case ClientMessage:
15373 if (display_image->debug != MagickFalse)
15374 (void) LogMagickEvent(X11Event,GetMagickModule(),
15375 "Client Message: 0x%lx 0x%lx %d 0x%lx",event.xclient.window,
15376 event.xclient.message_type,event.xclient.format,(unsigned long)
15377 event.xclient.data.l[0]);
15378 if (event.xclient.message_type == windows->im_protocols)
15380 if (*event.xclient.data.l == (long) windows->im_update_widget)
15382 (void) CloneString(&windows->command.name,MagickTitle);
15383 windows->command.data=MagickMenus;
15384 (void) XCommandWidget(display,windows,CommandMenu,
15388 if (*event.xclient.data.l == (long) windows->im_update_colormap)
15391 Update graphic context and window colormap.
15393 for (i=0; i < (int) number_windows; i++)
15395 if (magick_windows[i]->id == windows->icon.id)
15397 context_values.background=pixel->background_color.pixel;
15398 context_values.foreground=pixel->foreground_color.pixel;
15399 (void) XChangeGC(display,magick_windows[i]->annotate_context,
15400 context_mask,&context_values);
15401 (void) XChangeGC(display,magick_windows[i]->widget_context,
15402 context_mask,&context_values);
15403 context_values.background=pixel->foreground_color.pixel;
15404 context_values.foreground=pixel->background_color.pixel;
15405 context_values.plane_mask=context_values.background ^
15406 context_values.foreground;
15407 (void) XChangeGC(display,magick_windows[i]->highlight_context,
15408 (size_t) (context_mask | GCPlaneMask),
15410 magick_windows[i]->attributes.background_pixel=
15411 pixel->background_color.pixel;
15412 magick_windows[i]->attributes.border_pixel=
15413 pixel->border_color.pixel;
15414 magick_windows[i]->attributes.colormap=map_info->colormap;
15415 (void) XChangeWindowAttributes(display,magick_windows[i]->id,
15416 (unsigned long) magick_windows[i]->mask,
15417 &magick_windows[i]->attributes);
15419 if (windows->pan.mapped != MagickFalse)
15421 (void) XSetWindowBackgroundPixmap(display,windows->pan.id,
15422 windows->pan.pixmap);
15423 (void) XClearWindow(display,windows->pan.id);
15424 XDrawPanRectangle(display,windows);
15426 if (windows->backdrop.id != (Window) NULL)
15427 (void) XInstallColormap(display,map_info->colormap);
15430 if (*event.xclient.data.l == (long) windows->im_former_image)
15432 *state|=FormerImageState | ExitState;
15435 if (*event.xclient.data.l == (long) windows->im_next_image)
15437 *state|=NextImageState | ExitState;
15440 if (*event.xclient.data.l == (long) windows->im_retain_colors)
15442 *state|=RetainColorsState;
15445 if (*event.xclient.data.l == (long) windows->im_exit)
15452 if (event.xclient.message_type == windows->dnd_protocols)
15470 Display image named by the Drag-and-Drop selection.
15472 if ((*event.xclient.data.l != 2) && (*event.xclient.data.l != 128))
15474 selection=XInternAtom(display,"DndSelection",MagickFalse);
15475 status=XGetWindowProperty(display,root_window,selection,0L,(long)
15476 MaxTextExtent,MagickFalse,(Atom) AnyPropertyType,&type,&format,
15477 &length,&after,&data);
15478 if ((status != Success) || (length == 0))
15480 if (*event.xclient.data.l == 2)
15485 (void) CopyMagickString(resource_info->image_info->filename,
15486 (char *) data,MaxTextExtent);
15493 if (strncmp((char *) data, "file:", 5) != 0)
15495 (void) XFree((void *) data);
15498 (void) CopyMagickString(resource_info->image_info->filename,
15499 ((char *) data)+5,MaxTextExtent);
15501 nexus=ReadImage(resource_info->image_info,exception);
15502 CatchException(exception);
15503 if (nexus != (Image *) NULL)
15504 *state|=NextImageState | ExitState;
15505 (void) XFree((void *) data);
15509 If client window delete message, exit.
15511 if (event.xclient.message_type != windows->wm_protocols)
15513 if (*event.xclient.data.l != (long) windows->wm_delete_window)
15515 (void) XWithdrawWindow(display,event.xclient.window,
15516 visual_info->screen);
15517 if (event.xclient.window == windows->image.id)
15522 if (event.xclient.window == windows->pan.id)
15525 Restore original image size when pan window is deleted.
15527 windows->image.window_changes.width=windows->image.ximage->width;
15528 windows->image.window_changes.height=windows->image.ximage->height;
15529 (void) XConfigureImage(display,resource_info,windows,
15530 display_image,exception);
15534 case ConfigureNotify:
15536 if (display_image->debug != MagickFalse)
15537 (void) LogMagickEvent(X11Event,GetMagickModule(),
15538 "Configure Notify: 0x%lx %dx%d+%d+%d %d",event.xconfigure.window,
15539 event.xconfigure.width,event.xconfigure.height,event.xconfigure.x,
15540 event.xconfigure.y,event.xconfigure.send_event);
15541 if (event.xconfigure.window == windows->image.id)
15544 Image window has a new configuration.
15546 if (event.xconfigure.send_event != 0)
15552 Position the transient windows relative of the Image window.
15554 if (windows->command.geometry == (char *) NULL)
15555 if (windows->command.mapped == MagickFalse)
15557 windows->command.x=event.xconfigure.x-
15558 windows->command.width-25;
15559 windows->command.y=event.xconfigure.y;
15560 XConstrainWindowPosition(display,&windows->command);
15561 window_changes.x=windows->command.x;
15562 window_changes.y=windows->command.y;
15563 (void) XReconfigureWMWindow(display,windows->command.id,
15564 windows->command.screen,(unsigned int) (CWX | CWY),
15567 if (windows->widget.geometry == (char *) NULL)
15568 if (windows->widget.mapped == MagickFalse)
15570 windows->widget.x=event.xconfigure.x+
15571 event.xconfigure.width/10;
15572 windows->widget.y=event.xconfigure.y+
15573 event.xconfigure.height/10;
15574 XConstrainWindowPosition(display,&windows->widget);
15575 window_changes.x=windows->widget.x;
15576 window_changes.y=windows->widget.y;
15577 (void) XReconfigureWMWindow(display,windows->widget.id,
15578 windows->widget.screen,(unsigned int) (CWX | CWY),
15581 if (windows->magnify.geometry == (char *) NULL)
15582 if (windows->magnify.mapped == MagickFalse)
15584 windows->magnify.x=event.xconfigure.x+
15585 event.xconfigure.width+25;
15586 windows->magnify.y=event.xconfigure.y;
15587 XConstrainWindowPosition(display,&windows->magnify);
15588 window_changes.x=windows->magnify.x;
15589 window_changes.y=windows->magnify.y;
15590 (void) XReconfigureWMWindow(display,windows->magnify.id,
15591 windows->magnify.screen,(unsigned int) (CWX | CWY),
15594 if (windows->pan.geometry == (char *) NULL)
15595 if (windows->pan.mapped == MagickFalse)
15597 windows->pan.x=event.xconfigure.x+
15598 event.xconfigure.width+25;
15599 windows->pan.y=event.xconfigure.y+
15600 windows->magnify.height+50;
15601 XConstrainWindowPosition(display,&windows->pan);
15602 window_changes.x=windows->pan.x;
15603 window_changes.y=windows->pan.y;
15604 (void) XReconfigureWMWindow(display,windows->pan.id,
15605 windows->pan.screen,(unsigned int) (CWX | CWY),
15609 if ((event.xconfigure.width == (int) windows->image.width) &&
15610 (event.xconfigure.height == (int) windows->image.height))
15612 windows->image.width=(unsigned int) event.xconfigure.width;
15613 windows->image.height=(unsigned int) event.xconfigure.height;
15614 windows->image.x=0;
15615 windows->image.y=0;
15616 if (display_image->montage != (char *) NULL)
15618 windows->image.x=vid_info.x;
15619 windows->image.y=vid_info.y;
15621 if ((windows->image.mapped != MagickFalse) &&
15622 (windows->image.stasis != MagickFalse))
15625 Update image window configuration.
15627 windows->image.window_changes.width=event.xconfigure.width;
15628 windows->image.window_changes.height=event.xconfigure.height;
15629 (void) XConfigureImage(display,resource_info,windows,
15630 display_image,exception);
15633 Update pan window configuration.
15635 if ((event.xconfigure.width < windows->image.ximage->width) ||
15636 (event.xconfigure.height < windows->image.ximage->height))
15638 (void) XMapRaised(display,windows->pan.id);
15639 XDrawPanRectangle(display,windows);
15642 if (windows->pan.mapped != MagickFalse)
15643 (void) XWithdrawWindow(display,windows->pan.id,
15644 windows->pan.screen);
15647 if (event.xconfigure.window == windows->magnify.id)
15653 Magnify window has a new configuration.
15655 windows->magnify.width=(unsigned int) event.xconfigure.width;
15656 windows->magnify.height=(unsigned int) event.xconfigure.height;
15657 if (windows->magnify.mapped == MagickFalse)
15660 while ((int) magnify <= event.xconfigure.width)
15662 while ((int) magnify <= event.xconfigure.height)
15665 if (((int) magnify != event.xconfigure.width) ||
15666 ((int) magnify != event.xconfigure.height))
15668 window_changes.width=(int) magnify;
15669 window_changes.height=(int) magnify;
15670 (void) XReconfigureWMWindow(display,windows->magnify.id,
15671 windows->magnify.screen,(unsigned int) (CWWidth | CWHeight),
15675 if ((windows->magnify.mapped != MagickFalse) &&
15676 (windows->magnify.stasis != MagickFalse))
15678 status=XMakeImage(display,resource_info,&windows->magnify,
15679 display_image,windows->magnify.width,windows->magnify.height,
15681 XMakeMagnifyImage(display,windows,exception);
15685 if ((windows->magnify.mapped != MagickFalse) &&
15686 (event.xconfigure.window == windows->pan.id))
15689 Pan icon window has a new configuration.
15691 if (event.xconfigure.send_event != 0)
15693 windows->pan.x=event.xconfigure.x;
15694 windows->pan.y=event.xconfigure.y;
15696 windows->pan.width=(unsigned int) event.xconfigure.width;
15697 windows->pan.height=(unsigned int) event.xconfigure.height;
15700 if (event.xconfigure.window == windows->icon.id)
15703 Icon window has a new configuration.
15705 windows->icon.width=(unsigned int) event.xconfigure.width;
15706 windows->icon.height=(unsigned int) event.xconfigure.height;
15711 case DestroyNotify:
15714 Group leader has exited.
15716 if (display_image->debug != MagickFalse)
15717 (void) LogMagickEvent(X11Event,GetMagickModule(),
15718 "Destroy Notify: 0x%lx",event.xdestroywindow.window);
15719 if (event.xdestroywindow.window == windows->group_leader.id)
15729 Selectively install colormap.
15731 if (map_info->colormap != XDefaultColormap(display,visual_info->screen))
15732 if (event.xcrossing.mode != NotifyUngrab)
15733 XInstallColormap(display,map_info->colormap);
15738 if (display_image->debug != MagickFalse)
15739 (void) LogMagickEvent(X11Event,GetMagickModule(),
15740 "Expose: 0x%lx %dx%d+%d+%d",event.xexpose.window,
15741 event.xexpose.width,event.xexpose.height,event.xexpose.x,
15744 Refresh windows that are now exposed.
15746 if ((event.xexpose.window == windows->image.id) &&
15747 (windows->image.mapped != MagickFalse))
15749 XRefreshWindow(display,&windows->image,&event);
15750 delay=display_image->delay/MagickMax(
15751 display_image->ticks_per_second,1L);
15752 timer=time((time_t *) NULL)+(delay == 0 ? 1 : delay)+1;
15755 if ((event.xexpose.window == windows->magnify.id) &&
15756 (windows->magnify.mapped != MagickFalse))
15758 XMakeMagnifyImage(display,windows,exception);
15761 if (event.xexpose.window == windows->pan.id)
15763 XDrawPanRectangle(display,windows);
15766 if (event.xexpose.window == windows->icon.id)
15768 XRefreshWindow(display,&windows->icon,&event);
15779 Respond to a user key press.
15781 length=XLookupString((XKeyEvent *) &event.xkey,command,(int)
15782 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
15783 *(command+length)='\0';
15784 if (display_image->debug != MagickFalse)
15785 (void) LogMagickEvent(X11Event,GetMagickModule(),
15786 "Key press: %d 0x%lx (%s)",event.xkey.state,(unsigned long)
15787 key_symbol,command);
15788 if (event.xkey.window == windows->image.id)
15790 command_type=XImageWindowCommand(display,resource_info,windows,
15791 event.xkey.state,key_symbol,&display_image,exception);
15792 if (command_type != NullCommand)
15793 nexus=XMagickCommand(display,resource_info,windows,command_type,
15794 &display_image,exception);
15796 if (event.xkey.window == windows->magnify.id)
15797 XMagnifyWindowCommand(display,windows,event.xkey.state,key_symbol,
15799 if (event.xkey.window == windows->pan.id)
15801 if ((key_symbol == XK_q) || (key_symbol == XK_Escape))
15802 (void) XWithdrawWindow(display,windows->pan.id,
15803 windows->pan.screen);
15805 if ((key_symbol == XK_F1) || (key_symbol == XK_Help))
15806 XTextViewWidget(display,resource_info,windows,MagickFalse,
15807 "Help Viewer - Image Pan",ImagePanHelp);
15809 XTranslateImage(display,windows,*image,key_symbol);
15811 delay=display_image->delay/MagickMax(
15812 display_image->ticks_per_second,1L);
15813 timer=time((time_t *) NULL)+(delay == 0 ? 1 : delay)+1;
15819 Respond to a user key release.
15821 (void) XLookupString((XKeyEvent *) &event.xkey,command,(int)
15822 sizeof(command),&key_symbol,(XComposeStatus *) NULL);
15823 if (display_image->debug != MagickFalse)
15824 (void) LogMagickEvent(X11Event,GetMagickModule(),
15825 "Key release: 0x%lx (%c)",(unsigned long) key_symbol,*command);
15831 Selectively uninstall colormap.
15833 if (map_info->colormap != XDefaultColormap(display,visual_info->screen))
15834 if (event.xcrossing.mode != NotifyUngrab)
15835 XUninstallColormap(display,map_info->colormap);
15840 if (display_image->debug != MagickFalse)
15841 (void) LogMagickEvent(X11Event,GetMagickModule(),"Map Notify: 0x%lx",
15842 event.xmap.window);
15843 if (event.xmap.window == windows->backdrop.id)
15845 (void) XSetInputFocus(display,event.xmap.window,RevertToParent,
15847 windows->backdrop.mapped=MagickTrue;
15850 if (event.xmap.window == windows->image.id)
15852 if (windows->backdrop.id != (Window) NULL)
15853 (void) XInstallColormap(display,map_info->colormap);
15854 if (LocaleCompare(display_image->magick,"LOGO") == 0)
15856 if (LocaleCompare(display_image->filename,"LOGO") == 0)
15857 nexus=XOpenImage(display,resource_info,windows,MagickFalse);
15859 if (((int) windows->image.width < windows->image.ximage->width) ||
15860 ((int) windows->image.height < windows->image.ximage->height))
15861 (void) XMapRaised(display,windows->pan.id);
15862 windows->image.mapped=MagickTrue;
15865 if (event.xmap.window == windows->magnify.id)
15867 XMakeMagnifyImage(display,windows,exception);
15868 windows->magnify.mapped=MagickTrue;
15869 (void) XWithdrawWindow(display,windows->info.id,
15870 windows->info.screen);
15873 if (event.xmap.window == windows->pan.id)
15875 XMakePanImage(display,resource_info,windows,display_image,
15877 windows->pan.mapped=MagickTrue;
15880 if (event.xmap.window == windows->info.id)
15882 windows->info.mapped=MagickTrue;
15885 if (event.xmap.window == windows->icon.id)
15891 Create an icon image.
15893 taint=display_image->taint;
15894 XMakeStandardColormap(display,icon_visual,icon_resources,
15895 display_image,icon_map,icon_pixel,exception);
15896 (void) XMakeImage(display,icon_resources,&windows->icon,
15897 display_image,windows->icon.width,windows->icon.height,
15899 display_image->taint=taint;
15900 (void) XSetWindowBackgroundPixmap(display,windows->icon.id,
15901 windows->icon.pixmap);
15902 (void) XClearWindow(display,windows->icon.id);
15903 (void) XWithdrawWindow(display,windows->info.id,
15904 windows->info.screen);
15905 windows->icon.mapped=MagickTrue;
15908 if (event.xmap.window == windows->command.id)
15910 windows->command.mapped=MagickTrue;
15913 if (event.xmap.window == windows->popup.id)
15915 windows->popup.mapped=MagickTrue;
15918 if (event.xmap.window == windows->widget.id)
15920 windows->widget.mapped=MagickTrue;
15925 case MappingNotify:
15927 (void) XRefreshKeyboardMapping(&event.xmapping);
15932 case PropertyNotify:
15948 if (display_image->debug != MagickFalse)
15949 (void) LogMagickEvent(X11Event,GetMagickModule(),
15950 "Property Notify: 0x%lx 0x%lx %d",event.xproperty.window,
15951 event.xproperty.atom,event.xproperty.state);
15952 if (event.xproperty.atom != windows->im_remote_command)
15955 Display image named by the remote command protocol.
15957 status=XGetWindowProperty(display,event.xproperty.window,
15958 event.xproperty.atom,0L,(long) MaxTextExtent,MagickFalse,(Atom)
15959 AnyPropertyType,&type,&format,&length,&after,&data);
15960 if ((status != Success) || (length == 0))
15962 if (LocaleCompare((char *) data,"-quit") == 0)
15964 XClientMessage(display,windows->image.id,windows->im_protocols,
15965 windows->im_exit,CurrentTime);
15966 (void) XFree((void *) data);
15969 (void) CopyMagickString(resource_info->image_info->filename,
15970 (char *) data,MaxTextExtent);
15971 (void) XFree((void *) data);
15972 nexus=ReadImage(resource_info->image_info,exception);
15973 CatchException(exception);
15974 if (nexus != (Image *) NULL)
15975 *state|=NextImageState | ExitState;
15978 case ReparentNotify:
15980 if (display_image->debug != MagickFalse)
15981 (void) LogMagickEvent(X11Event,GetMagickModule(),
15982 "Reparent Notify: 0x%lx=>0x%lx",event.xreparent.parent,
15983 event.xreparent.window);
15988 if (display_image->debug != MagickFalse)
15989 (void) LogMagickEvent(X11Event,GetMagickModule(),
15990 "Unmap Notify: 0x%lx",event.xunmap.window);
15991 if (event.xunmap.window == windows->backdrop.id)
15993 windows->backdrop.mapped=MagickFalse;
15996 if (event.xunmap.window == windows->image.id)
15998 windows->image.mapped=MagickFalse;
16001 if (event.xunmap.window == windows->magnify.id)
16003 windows->magnify.mapped=MagickFalse;
16006 if (event.xunmap.window == windows->pan.id)
16008 windows->pan.mapped=MagickFalse;
16011 if (event.xunmap.window == windows->info.id)
16013 windows->info.mapped=MagickFalse;
16016 if (event.xunmap.window == windows->icon.id)
16018 if (map_info->colormap == icon_map->colormap)
16019 XConfigureImageColormap(display,resource_info,windows,
16020 display_image,exception);
16021 (void) XFreeStandardColormap(display,icon_visual,icon_map,
16023 windows->icon.mapped=MagickFalse;
16026 if (event.xunmap.window == windows->command.id)
16028 windows->command.mapped=MagickFalse;
16031 if (event.xunmap.window == windows->popup.id)
16033 if (windows->backdrop.id != (Window) NULL)
16034 (void) XSetInputFocus(display,windows->image.id,RevertToParent,
16036 windows->popup.mapped=MagickFalse;
16039 if (event.xunmap.window == windows->widget.id)
16041 if (windows->backdrop.id != (Window) NULL)
16042 (void) XSetInputFocus(display,windows->image.id,RevertToParent,
16044 windows->widget.mapped=MagickFalse;
16051 if (display_image->debug != MagickFalse)
16052 (void) LogMagickEvent(X11Event,GetMagickModule(),"Event type: %d",
16057 } while (!(*state & ExitState));
16058 if ((*state & ExitState) == 0)
16059 (void) XMagickCommand(display,resource_info,windows,FreeBuffersCommand,
16060 &display_image,exception);
16062 if (resource_info->confirm_edit != MagickFalse)
16065 Query user if image has changed.
16067 if ((resource_info->immutable == MagickFalse) &&
16068 (display_image->taint != MagickFalse))
16073 status=XConfirmWidget(display,windows,"Your image changed.",
16074 "Do you want to save it");
16076 *state&=(~ExitState);
16079 (void) XMagickCommand(display,resource_info,windows,SaveCommand,
16080 &display_image,exception);
16083 if ((windows->visual_info->klass == GrayScale) ||
16084 (windows->visual_info->klass == PseudoColor) ||
16085 (windows->visual_info->klass == DirectColor))
16088 Withdraw pan and Magnify window.
16090 if (windows->info.mapped != MagickFalse)
16091 (void) XWithdrawWindow(display,windows->info.id,windows->info.screen);
16092 if (windows->magnify.mapped != MagickFalse)
16093 (void) XWithdrawWindow(display,windows->magnify.id,
16094 windows->magnify.screen);
16095 if (windows->command.mapped != MagickFalse)
16096 (void) XWithdrawWindow(display,windows->command.id,
16097 windows->command.screen);
16099 if (windows->pan.mapped != MagickFalse)
16100 (void) XWithdrawWindow(display,windows->pan.id,windows->pan.screen);
16101 if (resource_info->backdrop == MagickFalse)
16102 if (windows->backdrop.mapped)
16104 (void) XWithdrawWindow(display,windows->backdrop.id,
16105 windows->backdrop.screen);
16106 (void) XDestroyWindow(display,windows->backdrop.id);
16107 windows->backdrop.id=(Window) NULL;
16108 (void) XWithdrawWindow(display,windows->image.id,
16109 windows->image.screen);
16110 (void) XDestroyWindow(display,windows->image.id);
16111 windows->image.id=(Window) NULL;
16113 XSetCursorState(display,windows,MagickTrue);
16114 XCheckRefreshWindows(display,windows);
16115 if (((*state & FormerImageState) != 0) || ((*state & NextImageState) != 0))
16116 *state&=(~ExitState);
16117 if (*state & ExitState)
16120 Free Standard Colormap.
16122 (void) XFreeStandardColormap(display,icon_visual,icon_map,icon_pixel);
16123 if (resource_info->map_type == (char *) NULL)
16124 (void) XFreeStandardColormap(display,visual_info,map_info,pixel);
16128 if (resource_info->copy_image != (Image *) NULL)
16130 resource_info->copy_image=DestroyImage(resource_info->copy_image);
16131 resource_info->copy_image=NewImageList();
16133 DestroyXResources();
16135 (void) XSync(display,MagickFalse);
16137 Restore our progress monitor and warning handlers.
16139 (void) SetErrorHandler(warning_handler);
16140 (void) SetWarningHandler(warning_handler);
16142 Change to home directory.
16144 directory=getcwd(working_directory,MaxTextExtent);
16150 status=chdir(resource_info->home_directory);
16152 (void) ThrowMagickException(exception,GetMagickModule(),FileOpenError,
16153 "UnableToOpenFile","%s",resource_info->home_directory);
16155 *image=display_image;
16161 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
16165 + D i s p l a y I m a g e s %
16169 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
16171 % DisplayImages() displays an image sequence to any X window screen. It
16172 % returns a value other than 0 if successful. Check the exception member
16173 % of image to determine the reason for any failure.
16175 % The format of the DisplayImages method is:
16177 % MagickBooleanType DisplayImages(const ImageInfo *image_info,
16178 % Image *images,ExceptionInfo *exception)
16180 % A description of each parameter follows:
16182 % o image_info: the image info.
16184 % o image: the image.
16186 % o exception: return any errors or warnings in this structure.
16189 MagickExport MagickBooleanType DisplayImages(const ImageInfo *image_info,
16190 Image *image,ExceptionInfo *exception)
16192 assert(image_info != (const ImageInfo *) NULL);
16193 assert(image_info->signature == MagickSignature);
16194 assert(image != (Image *) NULL);
16195 assert(image->signature == MagickSignature);
16196 if (image->debug != MagickFalse)
16197 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
16198 (void) ThrowMagickException(exception,GetMagickModule(),MissingDelegateError,
16199 "DelegateLibrarySupportNotBuiltIn","'%s' (X11)",image->filename);
16200 return(MagickFalse);
16204 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
16208 + R e m o t e D i s p l a y C o m m a n d %
16212 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
16214 % RemoteDisplayCommand() encourages a remote display program to display the
16215 % specified image filename.
16217 % The format of the RemoteDisplayCommand method is:
16219 % MagickBooleanType RemoteDisplayCommand(const ImageInfo *image,
16220 % const char *window,const char *filename,ExceptionInfo *exception)
16222 % A description of each parameter follows:
16224 % o image_info: the image info.
16226 % o window: Specifies the name or id of an X window.
16228 % o filename: the name of the image filename to display.
16230 % o exception: return any errors or warnings in this structure.
16233 MagickExport MagickBooleanType RemoteDisplayCommand(const ImageInfo *image_info,
16234 const char *window,const char *filename,ExceptionInfo *exception)
16236 assert(image_info != (const ImageInfo *) NULL);
16237 assert(image_info->signature == MagickSignature);
16238 assert(filename != (char *) NULL);
16240 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
16241 (void) ThrowMagickException(exception,GetMagickModule(),MissingDelegateError,
16242 "DelegateLibrarySupportNotBuiltIn","'%s' (X11)",image_info->filename);
16243 return(MagickFalse);