/*

   ImageMagick operations edited by Alan Gibson (aka "snibgo"; snibgo at earthling dot net).
   1-Apr-2014
     Minor corrections to Geometry_widget and Alpha.
     Added loads of widgets and Menuactions.
     Not fully tested.
   5-Apr-2014
     Many more menu actions.
     Reorganised Magick menu.
   10-Apr-2014
     Many more menu actions.
   11-Apr-2014 jcupitt
     Split to separate Magick.def
   13-Apr-2014 snibgo
     Put "new image" items into sub-menu.
     New class VirtualPixlBack.
   17-Apr-2014 snibgo
     Many small changes.
     A few new menu options.
     Created sub-menu for multi-input operations.
   3-May-2014 jcupitt
     Put quotes around ( in shadow to help unix

   Last update: 17-Apr-2014.

   For details of ImageMagick operations, see http://www.imagemagick.org/script/command-line-options.php etc.
*/

// We don't need Noop.
/*===
Magick_noop_item = class
	Menuaction "_Noop" "no operation" {
	action x = class
		_result {
		_vislevel = 3;

		command = Magick.command [
			"'%s'",
			"'%s'"
		];

		_result = Magick.system command x;
	}
}
===*/

/*
Magick_testPar_item = class
	Menuaction "_TestPar" "no operation" {
	action x = class
		_result {
		_vislevel = 3;

		command = Magick.command [
			"'%s'",
			"( +clone ) +append ",
			"'%s'"
		];

		_result = Magick.system command x;
	}
}
 */

/* Removed Read_item and Write_item, much better to use nip2 load/save image.
 * Plus they can load all libMagick formats anyway.
 */


// Put "new image" items into sub-menu
Magick_NewImageMenu_item = class
	Menupullright "_New image" "make a new image" {

	Magick_newcanvas_item = class
		Menuaction "_Solid colour" "make image of solid colour" {
		action = class
			_result {
			_vislevel = 3;

			size = Magick.Size_widget;
			colour = Magick.generalcol_widget;
			command = Magick.command [
				size._flag,
				"'canvas:" ++ colour._flag ++ "'",
				"'%s'"
			];

			_result = Magick.system0 command;
		}
	}

	Magick_builtin_item = class
		Menuaction "_Built-in image" "create a built-in image" {
		action = class
			_result {
			_vislevel = 3;

			builtin = Magick.builtin_widget;
			command = Magick.command [
				builtin._flag,
				"'%s'"
			];

			_result = Magick.system0 command;
		}
	}

	Magick_gradient_item = class
		Menuaction "_Gradient" "make a linear gradient between two colours" {
		action = class
			_result {
			_vislevel = 3;

			size = Magick.Size_widget;
			topColour = Magick.generalcol_widget;
			bottomColour = Magick.generalcol_widget;

			command = Magick.command [
				size._flag,
				concat ["'gradient:",
					topColour._flag, "-", bottomColour._flag, "'"],
				"'%s'"
			];

			_result = Magick.system0 command;
		}
	}

	Magick_hald_item = class
		Menuaction "_Hald-clut image" "create an identity hald-clut image" {
		action = class
			_result {
			_vislevel = 3;

			order = Expression "order" 8;
			command = Magick.command [
				"hald:" ++ print order.expr,
				"'%s'"
			];

			_result = Magick.system0 command;
		}
	}

	Magick_pattern_item = class
		Menuaction "_Pattern" "create pattern" {
		action = class
			_result {
			_vislevel = 3;

			size = Magick.Size_widget;
			pattern = Magick.pattern_widget;
			command = Magick.command [
				size._flag,
				pattern._flag,
				"'%s'"
			];

			_result = Magick.system0 command;
		}
	}

	Magick_plasma_item = class
		Menuaction "_Plasma image" "create plasma image" {
		action = class
			_result {
			_vislevel = 3;

			size = Magick.Size_widget;
			// FIXME? ColourA-ColourB.
			// FIXME? Allow plasma:fractal?

			command = Magick.command [
				size._flag,
				"plasma:",
				"'%s'"
			];

			_result = Magick.system0 command;
		}
	}

	Magick_radialgradient_item = class
		Menuaction "_Radial gradient"
			"make a radial gradient between two colours" {
		action = class
			_result {
			_vislevel = 3;

			size = Magick.Size_widget;
			innerColour = Magick.generalcol_widget;
			outerColour = Magick.generalcol_widget;

			command = Magick.command [
				size._flag,
				concat ["'radial-gradient:",
					innerColour._flag, "-", outerColour._flag, "'"],
				"'%s'"
			];

			_result = Magick.system0 command;
		}
	}
}  // end Magick_NewImageMenu_item


Magick_MultiMenu_item = class
	Menupullright "_Multiple inputs" "make an image from multiple images" {

	Magick_composite_item = class
		Menuaction "_Composite" "composite two images (without mask)" {
		action x y = class
			_result {
			_vislevel = 3;

			method = Magick.compose_widget;
			offsets = Magick.OffsetGeometry_widget;
			gravity = Magick.gravity_widget;

			command = Magick.command [
				"'%s'",
				"'%s'",
				"-geometry", offsets._flag,
				gravity._flag,
				method._flag,
				"-composite",
				"'%s'"
			];

			_result = Magick.system2 command x y;
		}
	}

	Magick_compositeMask_item = class
		Menuaction "_Composite masked" "composite two images (with mask)" {
		action x y z = class
			_result {
			_vislevel = 3;

			method = Magick.compose_widget;
			offsets = Magick.OffsetGeometry_widget;
			gravity = Magick.gravity_widget;

			command = Magick.command [
				"'%s'",
				"'%s'",
				"'%s'",
				"-geometry", offsets._flag,
				gravity._flag,
				method._flag,
				"-composite",
				"'%s'"
			];

			_result = Magick.system3 command x y z;
		}
	}

	// FIXME: other operations like remap that take another image as arguments are:
	// mask (pointless?), texture, tile (pointless?)

	// FIXME: operations that take a filename that isn't an image:
	// cdl, profile

	Magick_clut_item = class
		Menuaction "_Clut" "replace values using second image as colour look-up table" {
		action x y = class
			_result {
			_vislevel = 3;

			// FIXME: uses -intensity "when mapping greyscale CLUT image to alpha channel if set by -channels"

			command = Magick.command [
				"'%s'",
				"'%s'",
				"-clut",
				"'%s'"
			];

			_result = Magick.system2 command x y;
		}
	}

	Magick_haldclut_item = class
		Menuaction "_Hald clut" "replace values using second image as Hald colour look-up table" {
		action x y = class
			_result {
			_vislevel = 3;

			command = Magick.command [
				"'%s'",
				"'%s'",
				"-hald-clut",
				"'%s'"
			];

			_result = Magick.system2 command x y;
		}
	}


	// Encipher and decipher: key files can be text or image files.

	Magick_encipher_item = class
		Menuaction "_Encipher/Decipher" "encipher or decipher an image image" {
		action x = class
			_result {
			_vislevel = 3;

			pathname = Pathname "Read key file" "";
			isDecipher = Toggle "Decipher" false;

			command = Magick.command [
				"'%s'",
				if pathname.value == "" then "" else (
					( if isDecipher then "-decipher " else "-encipher ") ++
					( "'" ++ pathname.value ++ "'" )
				),
				"'%s'"
			];

			_result = Magick.system command x;
		}
	}

	Magick_profile_item = class
		Menuaction "_Profile" "assigns/applies an ICC profile" {
		action x = class
			_result {
			_vislevel = 3;

			pathname1 = Pathname "Read profile file" "";
			pathname2 = Pathname "Read profile file" "";

			command = Magick.command [
				"'%s'",
				if pathname1.value == "" then "" else (
					"-profile " ++
					"'" ++ pathname1.value ++ "'"),
				if pathname2.value == "" then "" else (
					"-profile " ++
					"'" ++ pathname2.value ++ "'"),
				"'%s'"
			];

			_result = Magick.system command x;
		}
	}

	Magick_remap_item = class
		Menuaction "_Remap" "reduce colours to those in another image" {
		action x y = class
			_result {
			_vislevel = 3;

			command = Magick.command [
				"'%s'",
				"-remap",
				"'%s'",
				"'%s'"
			];

			_result = Magick.system2 command x y;
		}
	}

}  // end Magick_MultiMenu_item


Magick_image_type_item = class
	Menuaction "_Image Type" "change image type" {
	action x = class
		_result {
		_vislevel = 3;

		imagetype = Magick.imagetype_widget;

		command = Magick.command [
			"'%s'",
			imagetype._flag,
			"'%s'"
		];

		_result = Magick.system command x;
	}
}

sep2 = Menuseparator;

Magick_alpha_item = class
	Menuaction "_Alpha" "add/remove alpha channel" {
	action x = class
		_result {
		_vislevel = 3;

		alpha = Magick.alpha_widget;
		command = Magick.command [
			"'%s'",
			alpha._flag,
			"'%s'"
		];

		_result = Magick.system command x;
	}
}

Magick_annotate_item = class
	Menuaction "_Annotate" "add text annotation" {
	action x = class
		_result {
		_vislevel = 3;

		text = Magick.text_widget;
		font = Magick.Font_widget;
		geometry = Magick.AnnotGeometry_widget;
		gravity = Magick.gravity_widget;
		foreground = Magick.foreground_widget;
		undercol = Magick.undercol_widget;
		antialias = Magick.antialias_widget;
		command = Magick.command [
			"'%s'",
			font._flag,
			antialias._flag,
			gravity._flag,
			foreground._flag,
			undercol._flag,
			"-annotate",
			geometry._flag,
			"'" ++ text.value ++ "'",
			"'%s'"
		];

		_result = Magick.system command x;
	}
}

Magick_autoGamma_item = class
	Menuaction "_AutoGamma" "automatic gamma" {
	action x = class
		_result {
		_vislevel = 3;

		channels = Magick.channels_widget;
		command = Magick.command [
			"'%s'",
			channels._flag,
			"-auto-gamma",
			"'%s'"
		];

		_result = Magick.system command x;
	}
}

Magick_autoLevel_item = class
	Menuaction "_AutoLevel" "automatic level" {
	action x = class
		_result {
		_vislevel = 3;

		channels = Magick.channels_widget;
		command = Magick.command [
			"'%s'",
			channels._flag,
			"-auto-level",
			"'%s'"
		];

		_result = Magick.system command x;
	}
}

Magick_blurSharpMenu_item = class
	Menupullright "_Blur/Sharpen" "blur and sharpen" {

	Magick_adaptive_blur_item = class
		Menuaction "_Adaptive Blur" "blur less near edges" {
		action x = class
			_result {
			_vislevel = 3;

			intensity = Magick.intensity_widget;
			radius = Magick.blur_rad_widget;
			sigma = Magick.sigma_widget;
			channels = Magick.channels_widget;
			// note: adaptive-blur doesn't regard VP.

			command = Magick.command [
				"'%s'",
				intensity._flag,
				channels._flag,
				"-adaptive-blur",
				print radius.value ++ "x" ++ print sigma.value,
				"'%s'"
			];

			_result = Magick.system command x;
		}
	}

	Magick_blur_item = class
		Menuaction "_Blur" "blur" {
		action x = class
			_result {
			_vislevel = 3;

			radius = Magick.blur_rad_widget;
			sigma = Magick.sigma_widget;
			channels = Magick.channels_widget;
			virtpixback = Magick.VirtualPixelBack_widget;
			command = Magick.command [
				"'%s'",
				virtpixback._flag,
				channels._flag,
				"-blur",
				print radius.value ++ "x" ++ print sigma.value,
				"'%s'"
			];

			_result = Magick.system command x;
		}
	}

	Magick_gaussianBlur_item = class
		Menuaction "_Gaussian Blur" "blur with a Gaussian operator" {
		action x = class
			_result {
			_vislevel = 3;

			radius = Magick.blur_rad_widget;
			sigma = Magick.sigma_widget;
			channels = Magick.channels_widget;
			virtpixback = Magick.VirtualPixelBack_widget;
			command = Magick.command [
				"'%s'",
				virtpixback._flag,
				channels._flag,
				"-gaussian-blur",
				print radius.value ++ "x" ++ print sigma.value,
				"'%s'"
			];

			_result = Magick.system command x;
		}
	}

	Magick_motionBlur_item = class
		Menuaction "_Motion Blur" "simulate motion blur" {
		action x = class
			_result {
			_vislevel = 3;

			radius = Magick.blur_rad_widget;
			sigma = Magick.sigma_widget;
			angle = Scale "angle" (-360) 360 0;
			channels = Magick.ch_widget;
			virtpixback = Magick.VirtualPixelBack_widget;
			command = Magick.command [
				"'%s'",
				virtpixback._flag,
				channels._flag,
				"-motion-blur",
				print radius.value ++ "x" ++
					print sigma.value ++ "+" ++
					print angle.value,
				"'%s'"
			];

			_result = Magick.system command x;
		}
	}

	Magick_rotationalBlur_item = class
		Menuaction "_Rotational Blur" "blur around the centre" {
		action x = class
			_result {
			_vislevel = 3;

			channels = Magick.channels_widget;
			virtpixback = Magick.VirtualPixelBack_widget;
			angle = Scale "angle (degrees)" (-360) 360 20;

			command = Magick.command [
				"'%s'",
				virtpixback._flag,
				channels._flag,
				"-radial-blur",
				print angle.value,
				"'%s'"
			];

			_result = Magick.system command x;
		}
	}

	Magick_selectiveBlur_item = class
		Menuaction "_Selective Blur" "blur where contrast is less than or equal to threshold" {
		action x = class
			_result {
			_vislevel = 3;

			intensity = Magick.intensity_widget;
			radius = Magick.blur_rad_widget;
			sigma = Magick.sigma_widget;
			threshold = Scale "Threshold (percent)" 0 100 50;
			channels = Magick.channels_widget;
			virtpixback = Magick.VirtualPixelBack_widget;
			command = Magick.command [
				"'%s'",
				intensity._flag,
				virtpixback._flag,
				channels._flag,
				"-selective-blur",
				print radius.value ++ "x" ++
					print sigma.value ++  "+" ++
					print threshold.value ++ "%%",
				"'%s'"
			];

			_result = Magick.system command x;
		}
	}

	sep1 = Menuseparator;

	Magick_adaptive_sharpen_item = class
		Menuaction "_Adaptive Sharpen" "sharpen more near edges" {
		action x = class
			_result {
			_vislevel = 3;

			intensity = Magick.intensity_widget;
			radius = Magick.blur_rad_widget;
			sigma = Magick.sigma_widget;

			command = Magick.command [
				"'%s'",
				intensity._flag,
				"-adaptive-sharpen",
				print radius.value ++ "x" ++ print sigma.value,
				"'%s'"
			];

			_result = Magick.system command x;
		}
	}

	Magick_sharpen_item = class
		Menuaction "_Sharpen" "sharpen" {
		action x = class
			_result {
			_vislevel = 3;

			radius = Magick.blur_rad_widget;
			sigma = Magick.sigma_widget;
			channels = Magick.channels_widget;
			virtpixback = Magick.VirtualPixelBack_widget;
			command = Magick.command [
				"'%s'",
				virtpixback._flag,
				channels._flag,
				"-sharpen",
				print radius.value ++ "x" ++ print sigma.value,
				"'%s'"
			];

			_result = Magick.system command x;
		}
	}

	Magick_unsharpen_item = class
		Menuaction "_Unsharp" "sharpen with unsharp mask" {
		action x = class
			_result {
			_vislevel = 3;

			radius = Magick.blur_rad_widget;
			sigma = Magick.sigma_widget;
			channels = Magick.channels_widget;
			gain = Scale "Gain" (-10) 10 1;
			threshold = Scale "Threshold" 0 1 0.05;
			virtpixback = Magick.VirtualPixelBack_widget;

			command = Magick.command [
				"'%s'",
				virtpixback._flag,
				channels._flag,
				"-unsharp",
				print radius.value ++ "x" ++
					print sigma.value ++ "+" ++
					print gain.value ++ "+" ++
					print threshold.value,
				"'%s'"
			];

			_result = Magick.system command x;
		}
	}

} // end BlurSharpMenu_item


Magick_border_item = class
	Menuaction "_Border" "add border of given colour" {
	action x = class
		_result {
		_vislevel = 3;

		compose = Magick.compose_widget;
		width = Expression "Width" 3;
		bordercol = Magick.bordercol_widget;

		command = Magick.command [
			"'%s'",
			compose._flag,
			bordercol._flag,
			"-border",
			print width.expr,
			"'%s'"
		];

		_result = Magick.system command x;
	}
}

Magick_brightCont_item = class
	Menuaction "_Brightness-contrast" "adjust the brightness and/or contrast" {
	action x = class
		_result {
		_vislevel = 3;

		bri = Scale "brightness" (-100) 100 0;
		con = Scale "contrast" (-100) 100 0;
		channels = Magick.channels_widget;

		command = Magick.command [
			"'%s'",
			channels._flag,
			"-brightness-contrast",
			print bri.value ++ "x" ++ print con.value,
			"'%s'"
		];

		_result = Magick.system command x;
	}
}

// Note: canny requires ImageMagick 6.8.9-0 or later.

Magick_canny_item = class
	Menuaction "_Canny" "detect a wide range of edges" {
	action x = class
		_result {
		_vislevel = 3;

		radius = Magick.blur_rad_widget;
		sigma = Magick.sigma_widget;
		lowPc = Scale "lower percent" 0 100 10;
		highPc = Scale "lower percent" 0 100 10;

		command = Magick.command [
			"'%s'",
			"-canny",
			concat ["'",
				print radius.value ++ "x" ++
				print sigma.value ++ "+" ++
				print lowPc.value ++ "%+" ++
				print highPc.value ++ "%" ++ "'"
			],
			"'%s'"
		];

		_result = Magick.system command x;
	}
}


Magick_charcoal_item = class
	Menuaction "_Charcoal" "simulate a charcoal drawing" {
	action x = class
		_result {
		_vislevel = 3;

		intensity = Magick.intensity_widget;
		factor = Scale "factor" 0 50 1;

		command = Magick.command [
			"'%s'",
			intensity._flag,
			"-charcoal",
			print factor.value,
			"'%s'"
		];

		_result = Magick.system command x;
	}
}

Magick_chop_item = class
	Menuaction "_Chop" "remove pixels from the interior" {
	action x = class
		_result {
		_vislevel = 3;

		gravity = Magick.gravity_widget;
		geometry = Magick.WhxyGeometry_widget;

		command = Magick.command [
			"'%s'",
			gravity._flag,
			"-chop",
			geometry._flag,
			"'%s'"
		];

		_result = Magick.system command x;
	}
}

Magick_colorize_item = class
	Menuaction "_Colorize" "colorize by given amount" {
	action x = class
		_result {
		_vislevel = 3;

		foreground = Magick.foreground_widget;
		val = Scale "value" 0 100 100;

		command = Magick.command [
			"'%s'",
			foreground._flag,
			"-colorize",
			print val.value,
			"'%s'"
		];

		_result = Magick.system command x;
	}
}

Magick_colors_item = class
	Menuaction "_Colors" "reduce number of colors" {
	action x = class
		_result {
		_vislevel = 3;

		treedepth = Expression "Treedepth" 8;
		dither = Magick.dither_widget;
		quantize = Magick.colorspace_widget;
		colors = Expression "Colours" 3;

		command = Magick.command [
			"'%s'",
			"-quantize", quantize._flag,
			"-treedepth",
			print treedepth.expr,
			dither._flag,
			"-colors",
			print colors.expr,
			"'%s'"
		];

		_result = Magick.system command x;
	}
}

// FIXME: color-matrix?

Magick_colorspace_item = class
	Menuaction "_Colourspace" "convert to arbitrary colourspace" {
	action x = class
		_result {
		_vislevel = 3;

		colsp = Magick.colorspace_widget;

		command = Magick.command [
			"'%s'",
			"-colorspace",
			colsp._flag,
			"'%s'"
		];

		_result = Magick.system command x;
	}
}

Magick_colorspaceGray_item = class
	Menuaction "_Colourspace gray" "convert to gray using given intensity method" {
	action x = class
		_result {
		_vislevel = 3;

		intensity = Magick.intensity_widget;

		command = Magick.command [
			"'%s'",
			intensity._flag,
			"-colorspace gray",
			"'%s'"
		];

		_result = Magick.system command x;
	}
}

Magick_contrast_item = class
	Menuaction "_Contrast" "increase or reduce the contrast" {
	action x = class
		_result {
		_vislevel = 3;

		isReduce = Toggle "reduce contrast" false;

		command = Magick.command [
			"'%s'",
			(if isReduce then "+" else "-") ++ "contrast",
			"'%s'"
		];

		_result = Magick.system command x;
	}
}

Magick_contrastStretch_item = class
	Menuaction "_Contrast stretch" "stretches tones, making some black/white" {
	action x = class
		_result {
		_vislevel = 3;

		intensity = Magick.intensity_widget;
		channels = Magick.channels_widget;
		blk = Scale "percent to make black" 0 100 0;
		wht = Scale "percent to make white" 0 100 0;

		command = Magick.command [
			"'%s'",
			intensity._flag,
			channels._flag,
			"-contrast-stretch",
			"'" ++ print blk.value ++ "x" ++ print wht.value ++ "%'",
			"'%s'"
		];

		_result = Magick.system command x;
	}
}

// FIXME: convolve (bias, kernel)

Magick_crop_item = class
	Menuaction "_Crop" "cut out a rectangular region" {
	action x = class
		_result {
		_vislevel = 3;

		gravity = Magick.gravity_widget;
		geometry = Magick.WhxyGeometry_widget;

		command = Magick.command [
			"'%s'",
			gravity._flag,
			"-crop",
			geometry._flag,
			"+repage",
			"'%s'"
		];

		_result = Magick.system command x;
	}
}

Magick_deskew_item = class
	Menuaction "_Deskew" "straighten the image" {
	action x = class
		_result {
		_vislevel = 3;

		threshold = Scale "Threshold (percent)" 0 100 80;

		// FIXME: toggle auto-crop?

		command = Magick.command [
			"'%s'",
			"-deskew",
			"'" ++ print threshold.value ++ "%'",
			"+repage",
			"'%s'"
		];

		_result = Magick.system command x;
	}
}

Magick_despeckle_item = class
	Menuaction "_Despeckle" "reduce the speckles" {
	action x = class
		_result {
		_vislevel = 3;

		command = Magick.command [
			"'%s'",
			"-despeckle",
			"'%s'"
		];

		_result = Magick.system command x;
	}
}

Magick_distort_item = class
	Menuaction "_Distort" "distort using a method and arguments" {
	action x = class
		_result {
		_vislevel = 3;

		virtpixback = Magick.VirtualPixelBack_widget;
		distort = Magick.distort_widget;
		args = String "Arguments" "1,0";
		isPlus = Toggle "Extend to show entire image" false;

		command = Magick.command [
			"'%s'",
			virtpixback._flag,
			(if isPlus then "+" else "-") ++ "distort",
			distort._flag,
			args.value,
			"+repage",
			"'%s'"
		];

		_result = Magick.system command x;
	}
}

Magick_draw_item = class
	Menuaction "_Draw" "annotate with one or more graphic primitives" {
	action x = class
		_result {
		_vislevel = 3;

		foreground = Magick.foreground_widget;
		args = String "Arguments" "line 0,0 9,9 rectangle 10,10 20,20";

		command = Magick.command [
			"'%s'",
			foreground._flag,
			"-draw",
			concat ["'", args.value, "'"],
			"'%s'"
		];

		_result = Magick.system command x;
	}
}

Magick_edge_item = class
	Menuaction "_Edge" "detect edges" {
	action x = class
		_result {
		_vislevel = 3;

		rad = Expression "Radius" 3;

		command = Magick.command [
			"'%s'",
			"-edge",
			print rad.expr,
			"'%s'"
		];

		_result = Magick.system command x;
	}
}

Magick_emboss_item = class
	Menuaction "_Emboss" "emboss" {
	action x = class
		_result {
		_vislevel = 3;

		rad = Expression "Radius" 3;

		command = Magick.command [
			"'%s'",
			"-emboss",
			print rad.expr,
			"'%s'"
		];

		_result = Magick.system command x;
	}
}

Magick_enhance_item = class
	Menuaction "_Enhance" "enhance a noisy image" {
	action x = class
		_result {
		_vislevel = 3;

		command = Magick.command [
			"'%s'",
			"-enhance",
			"'%s'"
		];

		_result = Magick.system command x;
	}
}

Magick_equalize_item = class
	Menuaction "_Equalize" "equalize the histogram" {
	action x = class
		_result {
		_vislevel = 3;

		channels = Magick.channels_widget;

		command = Magick.command [
			"'%s'",
			channels._flag,
			"-equalize",
			"'%s'"
		];

		_result = Magick.system command x;
	}
}

Magick_evaluate_item = class
	Menuaction "_Evaluate" "evaluate an expression on each pixel channel" {
	action x = class
		_result {
		_vislevel = 3;

		channels = Magick.channels_widget;
		operation = Magick.evaluate_widget;
		val = Expression "value" 5;
		isPc = Toggle "Value is percent" false;

		command = Magick.command [
			"'%s'",
			channels._flag,
			operation._flag,
			print val.expr ++ if isPc then "%%" else "",
			"'%s'"
		];

		_result = Magick.system command x;
	}
}

Magick_extent_item = class
	Menuaction "_Extent" "set the image size and offset" {
	action x = class
		_result {
		_vislevel = 3;

		background = Magick.background_widget;
		compose = Magick.compose_widget;
		gravity = Magick.gravity_widget;
		geometry = Magick.WhxyGeometry_widget;

		command = Magick.command [
			"'%s'",
			compose._flag,
			background._flag,
			gravity._flag,
			"-extent",
			geometry._flag,
			"'%s'"
		];

		_result = Magick.system command x;
	}
}


Magick_FlipFlopMenu_item = class
	Menupullright "_Flip/flop" "flip/flop/transverse/transpose" {

	Magick_flip_item = class
		Menuaction "_Flip vertically" "mirror upside-down" {
		action x = class
			_result {
			_vislevel = 3;

			command = Magick.command [
				"'%s'",
				"-flip",
				"'%s'"
			];

			_result = Magick.system command x;
		}
	}

	Magick_flop_item = class
		Menuaction "_Flop horizontally" "mirror left-right" {
		action x = class
			_result {
			_vislevel = 3;

			command = Magick.command [
				"'%s'",
				"-flop",
				"'%s'"
			];

			_result = Magick.system command x;
		}
	}

	Magick_transpose_item = class
		Menuaction "_Transpose" "mirror along the top-left to bottom-right diagonal" {
		action x = class
			_result {
			_vislevel = 3;

			command = Magick.command [
				"'%s'",
				"-transpose +repage",
				"'%s'"
			];

			_result = Magick.system command x;
		}
	}

	Magick_transverse_item = class
		Menuaction "_Transverse" "mirror along the bottom-left to top-right diagonal" {
		action x = class
			_result {
			_vislevel = 3;

			command = Magick.command [
				"'%s'",
				"-transverse +repage",
				"'%s'"
			];

			_result = Magick.system command x;
		}
	}

} // end Magick_FlipFlopMenu_item


Magick_floodfill_item = class
	Menuaction "_Floodfill" "recolour neighbours that match" {
	action x = class
		_result {
		_vislevel = 3;

		foreground = Magick.foreground_widget;
		fuzz = Magick.fuzz_widget;
		coordinate = Magick.coordinate_widget;

		// -draw "color x,y floodfill"
		command = Magick.command [
			"'%s'",
			foreground._flag,
			"-fuzz",
			"'" ++ print fuzz.value ++ "%'",
			"-draw ' color",
			coordinate._flag,
			"floodfill '",
			"'%s'"
		];

		_result = Magick.system command x;
	}
}

Magick_frame_item = class
	Menuaction "_Frame" "surround with border or beveled frame" {
	action x = class
		_result {
		_vislevel = 3;

		border = Magick.bordercol_widget;
		compose = Magick.compose_widget;
		matte = Magick.mattecol_widget;
		geometry = Magick.FrameGeometry_widget;

		command = Magick.command [
			"'%s'",
			compose._flag,
			border._flag,
			matte._flag,
			"-frame",
			geometry._flag,
			"'%s'"
		];

		_result = Magick.system command x;
	}
}

Magick_function_item = class
	Menuaction "_Function" "evaluate a function on each pixel channel" {
	action x = class
		_result {
		_vislevel = 3;

		channels = Magick.channels_widget;
		function = Magick.function_widget;
		// FIXME: explain values; use sensible defaults.
		values = String "values" "0,0,0,0";

		command = Magick.command [
			"'%s'",
			channels._flag,
			"-function",
			function._flag,
			values.value,
			"'%s'"
		];

		_result = Magick.system command x;
	}
}

Magick_fx_item = class
	Menuaction "_Fx" "apply a mathematical expression" {
	action x = class
		_result {
		_vislevel = 3;

		channels = Magick.channels_widget;
		interpolate = Magick.interpolate_widget;
		virtpixback = Magick.VirtualPixelBack_widget;
		args = String "Expression" "u*1/2";

		command = Magick.command [
			"'%s'",
			channels._flag,
			interpolate._flag,
			virtpixback._flag,
			"-fx",
			concat ["'", args.value, "'"],
			"'%s'"
		];

		_result = Magick.system command x;
	}
}

Magick_gamma_item = class
	Menuaction "_Gamma" "apply a gamma correction" {
	action x = class
		_result {
		_vislevel = 3;

		channels = Magick.channels_widget;
		gamma = Magick.gamma_widget;

		command = Magick.command [
			"'%s'",
			channels._flag,
			"-gamma",
			print gamma.value,
			"'%s'"
		];

		_result = Magick.system command x;
	}
}

Magick_gradient_item = class
	Menuaction "_Gradient" "apply a linear gradient" {
	action x = class
		_result {
		_vislevel = 3;

		colourA = Magick.generalcol_widget;
		colourB = Magick.generalcol_widget;

		position = Option "colourA is at" [
				"top", "bottom",
				"left", "right",
				"top-left", "top-right",
				"bottom-left", "bottom-right"] 0;
		_baryArg
			= concat ["0,0,", colourA._flag, " 0,%[fx:h-1],", colourB._flag], position.value == 0
			= concat ["0,0,", colourB._flag, " 0,%[fx:h-1],", colourA._flag], position.value == 1
			= concat ["0,0,", colourA._flag, " %[fx:w-1],0,", colourB._flag], position.value == 2
			= concat ["0,0,", colourB._flag, " %[fx:w-1],0,", colourA._flag], position.value == 3
			= concat ["0,0,", colourA._flag, " %[fx:w-1],%[fx:h-1],", colourB._flag], position.value == 4
			= concat ["%[fx:w-1],0,", colourA._flag, " 0,%[fx:h-1],", colourB._flag], position.value == 5
			= concat ["%[fx:w-1],0,", colourB._flag, " 0,%[fx:h-1],", colourA._flag], position.value == 6
			= concat ["0,0,", colourB._flag, " %[fx:w-1],%[fx:h-1],", colourA._flag], position.value == 7
			= "dunno";

		command = Magick.command [
			"'%s'",
			"-sparse-color barycentric '" ++ _baryArg ++ "'",
			"'%s'"
		];

		_result = Magick.system command x;
	}
}

Magick_gradientCorn_item = class
	Menuaction "_Gradient corners"
		"apply a bilinear gradient between the corners" {
	action x = class
		_result {
		_vislevel = 3;

		colour_top_left = Magick.generalcol_widget;
		colour_top_right = Magick.generalcol_widget;
		colour_bottom_left = Magick.generalcol_widget;
		colour_bottom_right = Magick.generalcol_widget;

		command = Magick.command [
			"'%s'",
			"-sparse-color bilinear '" ++
				"0,0," ++ colour_top_left._flag ++
				",%[fx:w-1],0" ++ colour_top_right._flag ++
				",0,%[fx:h-1]" ++ colour_bottom_left._flag ++
				",%[fx:w-1],%[fx:h-1]" ++ colour_bottom_right._flag ++ "'",
			"+depth",
			"'%s'"
		];

		_result = Magick.system command x;
	}
}

Magick_histogram_item = class
	Menuaction "_Histogram" "make a histogram image" {
	action x = class
		_result {
		_vislevel = 3;

		command = Magick.command [
			"'%s'",
			"-define histogram:unique-colors=false histogram:" ++
				"'%s'"
		];

		_result = Magick.system command x;
	}
}

Magick_implode_item = class
	Menuaction "_Implode" "implode pixels about the center" {
	action x = class
		_result {
		_vislevel = 3;

		factor = Scale "factor" 0 20 1;
		interpolate = Magick.interpolate_widget;
		// FIXME: virtual-pixel?

		command = Magick.command [
			"'%s'",
			interpolate._flag,
			"-implode",
			print factor.value,
			"'%s'"
		];

		_result = Magick.system command x;
	}
}

Magick_level_item = class
	Menuaction "_Level" "adjust the level of channels" {
	action x = class
		_result {
		_vislevel = 3;

		channels = Magick.channels_widget;
		blk = Scale "black point" (-100) 200 0;
		wht = Scale "white point" (-100) 200 100;
		gam = Scale "gamma" 0 30 1;
		isPc = Toggle "Levels are percent" true;
		isInv = Toggle "Invert effect" false;

		command = Magick.command [
			"'%s'",
			channels._flag,
			(if isInv then "+" else "-") ++ "level",
			"'" ++ print blk.value ++ "," ++
				print wht.value ++ (if isPc then "%" else "") ++ "," ++
				print gam.value ++ "'",
			"'%s'"
		];

		_result = Magick.system command x;
	}
}

Magick_levelCols_item = class
	Menuaction "_Level colors" "adjust levels to given colours" {
	action x = class
		_result {
		_vislevel = 3;

		channels = Magick.channels_widget;
		colour_black = Magick.generalcol_widget;
		colour_white = Magick.generalcol_widget;
		isInv = Toggle "Invert effect" false;

		command = Magick.command [
			"'%s'",
			channels._flag,
			(if isInv then "+" else "-") ++ "level-colors",
			"'" ++ colour_black._flag ++ "," ++ colour_white._flag ++ "'",
			"'%s'"
		];

		_result = Magick.system command x;
	}
}

Magick_linearStretch_item = class
	Menuaction "_Linear stretch" "stretches tones, making some black/white" {
	action x = class
		_result {
		_vislevel = 3;

		channels = Magick.channels_widget;
		blk = Scale "percent to make black" 0 100 0;
		wht = Scale "percent to make white" 0 100 0;

		command = Magick.command [
			"'%s'",
			channels._flag,
			"-linear-stretch",
			"'" ++ print blk.value ++ "x" ++ print wht.value ++ "%'",
			"'%s'"
		];

		_result = Magick.system command x;
	}
}

Magick_magnify_item = class
	Menuaction "_Magnify" "double the size of the image with pixel art scaling" {
	action x = class
		_result {
		_vislevel = 3;

		command = Magick.command [
			"'%s'",
			"-magnify",
			"'%s'"
		];

		_result = Magick.system command x;
	}
}

Magick_modulate_item = class
	Menuaction "_Modulate" "modulate brightness, saturation and hue" {
	action x = class
		_result {
		_vislevel = 3;

		modcolsp = Magick.ModColSp_widget;
		bright = Scale "brightness" 0 200 100;
		sat = Scale "saturation" 0 200 100;
		hue = Scale "hue" 0 200 100;

		command = Magick.command [
			"'%s'",
			modcolsp._flag,
			"-modulate",
			print bright.value ++ "," ++ print sat.value ++ "," ++
				print hue.value,
			"'%s'"
		];

		_result = Magick.system command x;
	}
}

Magick_monochrome_item = class
	Menuaction "_Monochrome" "transform to black and white" {
	action x = class
		_result {
		_vislevel = 3;

		// FIXME: also intensity?

		intensity = Magick.intensity_widget;
		treedepth = Expression "Treedepth" 8;
		dither = Magick.dither_widget;

		command = Magick.command [
			"'%s'",
			intensity._flag,
			dither._flag,
			"-treedepth",
			print treedepth.expr,
			"-monochrome",
			"'%s'"
		];

		_result = Magick.system command x;
	}
}

Magick_morphology_item = class
	// See http://www.imagemagick.org/Usage/morphology/
	Menuaction "_Morphology" "apply a morphological method" {
	action x = class
		_result {
		_vislevel = 3;

		method = Magick.morphmeth_widget;
		iter = Expression "Iterations (-1=repeat until done)" 1;

		kernel = Magick.kernel_widget;
		// FIXME: custom kernel eg "3x1+2+0:1,0,0"
		//   width x height + offsx + offsy : {w*h values}
		//   each value is 0.0 to 1.0 or "NaN" or "-"

		// kernel args, mostly float radius,scale. radius=0=default. default scale = 1.0
		// but
		//   ring takes: radius1, radius2, scale
		//   rectangle and comet take: width x height + offsx + offsy
		//   blur takes: radius x sigma
		// FIXME: for now, simply allow any string input.
		kernel_arg = String "Kernel arguments" "";
		channels = Magick.channels_widget;

		command = Magick.command [
			"'%s'",
			channels._flag,
			"-morphology",
			method._flag ++ ":" ++ print iter.expr,
			kernel._flag ++
			(if kernel_arg.value == "" then "" else ":") ++ kernel_arg.value,
			"'%s'"
		];

		_result = Magick.system command x;
	}
}

Magick_negate_item = class
	Menuaction "_Negate" "negate" {
	action x = class
		_result {
		_vislevel = 3;

		channels = Magick.channels_widget;

		command = Magick.command [
			"'%s'",
			channels._flag,
			"-negate",
			"'%s'"
		];

		_result = Magick.system command x;
	}
}

Magick_addNoise_item = class
	Menuaction "_add Noise" "add noise" {
	action x = class
		_result {
		_vislevel = 3;

		channels = Magick.channels_widget;
		attenuate = Scale "attenuate" 0 1.0 1.0;
		noise = Magick.noise_widget;

		command = Magick.command [
			"'%s'",
			channels._flag,
			"-attenuate",
			print attenuate.value,
			noise._flag,
			"'%s'"
		];

		_result = Magick.system command x;
	}
}

Magick_normalize_item = class
	Menuaction "_Normalize" "normalize" {
	action x = class
		_result {
		_vislevel = 3;

		intensity = Magick.intensity_widget;
		channels = Magick.channels_widget;

		command = Magick.command [
			"'%s'",
			intensity._flag,
			channels._flag,
			"-normalize",
			"'%s'"
		];

		_result = Magick.system command x;
	}
}

Magick_opaque_item = class
	Menuaction "_Opaque" "change this colour to the fill colour" {
	action x = class
		_result {
		_vislevel = 3;

		channels = Magick.channels_widget;
		fill = Magick.foreground_widget;
		changeColour = Magick.changeCol_widget;

		command = Magick.command [
			"'%s'",
			fill._flag,
			channels._flag,
			"-fuzz",
			"'" ++ print changeColour.fuzz.value ++ "%'",
			(if changeColour.nonMatch then "+" else "-") ++ "opaque",
			"'" ++ changeColour.colour._flag ++ "'",
			"'%s'"
		];

		_result = Magick.system command x;
	}
}

Magick_paint_item = class
	Menuaction "_Paint" "simulate an oil painting" {
	action x = class
		_result {
		_vislevel = 3;

		rad = Expression "radius" 10;

		command = Magick.command [
			"'%s'",
			"-paint",
			print rad.expr,
			"'%s'"
		];

		_result = Magick.system command x;
	}
}

/*=== FIXME Bug; remove for now.
Polaroid_item = class
	Menuaction "_Polaroid" "simulate a polaroid picture" {
	action x = class
		_result {
		_vislevel = 3;

		angle = Scale "angle" (-90) 90 20;

		command = Magick.command [
			"'%s'",
			"-polaroid",
			print angle.value,
			"'%s'"
		];

		_result = Magick.system command x;
	}
}
===*/

Magick_posterize_item = class
	Menuaction "_Posterize" "reduce to (n) levels per channel" {
	action x = class
		_result {
		_vislevel = 3;

		levels = Expression "levels" 3;

		command = Magick.command [
			"'%s'",
			"-posterize",
			print levels.expr,
			"'%s'"
		];

		_result = Magick.system command x;
	}
}

Magick_raise_item = class
	Menuaction "_Raise" "lighten or darken image edges" {
	action x = class
		_result {
		_vislevel = 3;

		thk = Expression "Thickness" 3;

		command = Magick.command [
			"'%s'",
			"-raise",
			print thk.expr,
			"'%s'"
		];

		_result = Magick.system command x;
	}
}

Magick_resize_item = class
	Menuaction "_Resize" "resize to given width and height" {
	action x = class
		_result {
		_vislevel = 3;

		filter = Magick.filter_widget;
		type = Magick.ResizeType_widget;
		width = Scale "Width" 1 100 10;
		height = Scale "Height" 1 100 10;
		isPc = Toggle "Width and height are percent" false;

		command = Magick.command [
			"'%s'",
			filter._flag,
			"-" ++ type._flag,
			"'" ++ print width.value ++ "x" ++ print height.value ++
				(if isPc then "%" else "!") ++ "'",
			"'%s'"
		];

		_result = Magick.system command x;
	}
}

Magick_roll_item = class
	Menuaction "_Roll" "roll an image horizontally or vertically" {
	action x = class
		_result {
		_vislevel = 3;

		rollx = Expression "X" 3;
		rolly = Expression "Y" 3;

		command = Magick.command [
			"'%s'",
			"-roll",
			(if rollx.expr >= 0 then "+" else "") ++ print rollx.expr ++
			(if rolly.expr >= 0 then "+" else "") ++ print rolly.expr,
			"'%s'"
		];

		_result = Magick.system command x;
	}
}

Magick_rotate_item = class
	Menuaction "_Rotate" "rotate" {
	action x = class
		_result {
		_vislevel = 3;

		angle = Scale "angle (degrees)" (-360) 360 20;
		virtpixback = Magick.VirtualPixelBack_widget;

		command = Magick.command [
			"'%s'",
			virtpixback._flag,
			"+distort",
			"SRT",
			print angle.value,
			"+repage",
			"'%s'"
		];

		_result = Magick.system command x;
	}
}

// FIXME: -segment, but cluster-threshold should be percentage of image area.

Magick_sepia_item = class
	Menuaction "_Sepia tone" "simulate a sepia-toned photo" {
	action x = class
		_result {
		_vislevel = 3;

		threshold = Scale "Threshold (percent)" 0 100 80;

		command = Magick.command [
			"'%s'",
			"-sepia-tone",
			"'" ++ print threshold.value ++ "%'",
			"'%s'"
		];

		_result = Magick.system command x;
	}
}

Magick_shade_item = class
	Menuaction "_Shade" "shade with a distant light source" {
	action x = class
		_result {
		_vislevel = 3;

		azimuth = Scale "Azimuth (degrees)" (-360) 360 0;
		elevation = Scale "Elevation (degrees)" 0 90 45;

		command = Magick.command [
			"'%s'",
			"-shade",
			print azimuth.value ++ "x" ++ print elevation.value,
			"'%s'"
		];

		_result = Magick.system command x;
	}
}

Magick_shadow_item = class
	Menuaction "_Shadow" "simulate a shadow" {
	action x = class
		_result {
		_vislevel = 3;

		shadowCol = Magick.generalcol_widget;
		opacity = Scale "Opacity (percent)" 0 100 75;
		sigma = Scale "Sigma" 0 30 2;
		// FIXME: make offsets a single widget?
		offsx = Scale "X-offset" (-20) 20 4;
		offsy = Scale "Y-offset" (-20) 20 4;
		arePc = Toggle "offsets are percentages" false;

		// FIXME: raw operation creates page offset, which vips dislikes.
		// So we take this futher, compositing with source.
		command = Magick.command [
			"'%s'",
			"'(' +clone",
			"-background", "'" ++ shadowCol._flag ++ "'",
			"-shadow",
			concat [
				"'",
				print opacity.value, "x", print sigma.value,
				(if offsx.value >= 0 then "+" else ""), print offsx.value,
				(if offsy.value >= 0 then "+" else ""), print offsy.value,
				(if arePc then "%" else ""),
				"'"
			],
			"')' +swap -background None -layers merge",
			"+repage",
			"'%s'"
		];

		_result = Magick.system command x;
	}
}

Magick_shave_item = class
	Menuaction "_Shave" "shave pixels from the edges" {
	action x = class
		_result {
		_vislevel = 3;

		width = Scale "Width" 0 50 10;
		height = Scale "Height" 0 50 10;
		isPc = Toggle "Width and height are percent" false;

		command = Magick.command [
			"'%s'",
			"-shave",
			"'" ++ print width.value ++ "x" ++ print height.value ++
				(if isPc then "%" else "") ++ "'",
			"'%s'"
		];

		_result = Magick.system command x;
	}
}

Magick_shear_item = class
	Menuaction "_Shear" "shear along the x-axis and/or y-axis" {
	action x = class
		_result {
		_vislevel = 3;

		shearX = Expression "shear X (degrees)" 0;
		shearY = Expression "shear Y (degrees)" 0;
		background = Magick.background_widget;

		command = Magick.command [
			"'%s'",
			background._flag,
			"-shear",
			print shearX.expr ++ "x" ++ print shearY.expr,
			"'%s'"
		];

		_result = Magick.system command x;
	}
}

Magick_sigmoid_item = class
	Menuaction "_Sigmoid" "increase or decrease mid-tone contrast sigmoidally" {
	action x = class
		_result {
		_vislevel = 3;

		channels = Magick.channels_widget;
		contrast = Scale "contrast" 0 30 3;
		midpoint = Scale "mid-point (percent)" 0 100 50;
		isInv = Toggle "Invert effect" false;

		command = Magick.command [
			"'%s'",
			channels._flag,
			(if isInv then "+" else "-") ++ "sigmoidal-contrast",
			"'" ++ print contrast.value ++ "x" ++
				print midpoint.value ++ "%'",
			"'%s'"
		];

		_result = Magick.system command x;
	}
}

Magick_sketch_item = class
	Menuaction "_Sketch" "simulate a pencil sketch" {
	action x = class
		_result {
		_vislevel = 3;

		radius = Magick.blur_rad_widget;
		sigma = Magick.sigma_widget;
		angle = Scale "angle" (-360) 360 0;

		command = Magick.command [
			"'%s'",
			"-sketch",
			print radius.value ++ "x" ++ print sigma.value ++
				(if angle >= 0 then ("+" ++ print angle.value) else ""),
			"'%s'"
		];

		_result = Magick.system command x;
	}
}

Magick_solarize_item = class
	Menuaction "_Solarize" "negate all pixels above a threshold level" {
	action x = class
		_result {
		_vislevel = 3;

		channels = Magick.channels_widget;
		threshold = Scale "Threshold (percent)" 0 100 50;

		command = Magick.command [
			"'%s'",
			channels._flag,
			"-solarize",
			"'" ++ print threshold.value ++ "%'",
			"'%s'"
		];

		_result = Magick.system command x;
	}
}

// FIXME: -sparse-color needs abitrary list of {x,y,colour}.

Magick_splice_item = class
	Menuaction "_Splice" "splice a colour into the image" {
	action x = class
		_result {
		_vislevel = 3;

		background = Magick.background_widget;
		gravity = Magick.gravity_widget;
		geometry = Magick.WhxyGeometry_widget;

		command = Magick.command [
			"'%s'",
			background._flag,
			gravity._flag,
			"-splice",
			geometry._flag,
			"'%s'"
		];

		_result = Magick.system command x;
	}
}

Magick_spread_item = class
	Menuaction "_Spread" "displace pixels by random amount" {
	action x = class
		_result {
		_vislevel = 3;

		virtpixback = Magick.VirtualPixelBack_widget;
		amount = Expression "Amount (pixels)" 5;

		command = Magick.command [
			"'%s'",
			virtpixback._flag,
			"-spread",
			print amount.expr,
			"'%s'"
		];

		_result = Magick.system command x;
	}
}

Magick_statistic_item = class
	Menuaction "_Statistic" "replace each pixel with statistic from neighbourhood" {
	action x = class
		_result {
		_vislevel = 3;

		width = Expression "Width" 5;
		height = Expression "Height" 5;
		statisticType = Magick.StatType_widget;

		command = Magick.command [
			"'%s'",
			"-statistic",
			statisticType._flag,
			print width.expr ++ "x" ++ print height.expr,
			"'%s'"
		];

		_result = Magick.system command x;
	}
}

Magick_swirl_item = class
	Menuaction "_Swirl" "swirl around the centre" {
	action x = class
		_result {
		_vislevel = 3;

		angle = Magick.angle_widget;

		command = Magick.command [
			"'%s'",
			"-swirl",
			print angle.value,
			"'%s'"
		];

		_result = Magick.system command x;
	}
}

Magick_thresholdMenu_item = class
	Menupullright "_Threshold" "make black or white" {

	Magick_threshold_item = class
		Menuaction "_Threshold" "apply black/white threshold" {
		action x = class
			_result {
			_vislevel = 3;

			intensity = Magick.intensity_widget;
			channels = Magick.channels_widget;
			threshold = Scale "Threshold (percent)" 0 100 50;

			command = Magick.command [
				"'%s'",
				intensity._flag,
				channels._flag,
				"-threshold",
				"'" ++ print threshold.value ++ "%'",
				"'%s'"
			];

			_result = Magick.system command x;
		}
	}

	Magick_blackThreshold_item = class
		Menuaction "_Black threshold" "where below threshold set to black" {
		action x = class
			_result {
			_vislevel = 3;

			channels = Magick.channels_widget;
			threshold = Scale "Threshold (percent)" 0 100 50;

			command = Magick.command [
				"'%s'",
				channels._flag,
				"-black-threshold",
				"'" ++ print threshold.value ++ "%'",
				"'%s'"
			];

			_result = Magick.system command x;
		}
	}

	Magick_whiteThreshold_item = class
		Menuaction "_White threshold" "where above threshold set to white" {
		action x = class
			_result {
			_vislevel = 3;

			channels = Magick.channels_widget;
			threshold = Scale "Threshold (percent)" 0 100 50;

			command = Magick.command [
				"'%s'",
				channels._flag,
				"-white-threshold",
				"'" ++ print threshold.value ++ "%'",
				"'%s'"
			];

			_result = Magick.system command x;
		}
	}

	Magick_latThreshold_item = class
		Menuaction "_Local Adaptive Threshold" "where above average plus offset set to white, otherwise black" {
		action x = class
			_result {
			_vislevel = 3;

			width = Expression "Width" 10;
			height = Expression "Height" 10;
			offset = Scale "Offset (percent)" (-100) 100 0;
			// note: "-lat" doesn't respond to channels

			command = Magick.command [
				"'%s'",
				"-lat",
				concat ["'", print width.expr, "x", print height.expr,
					(if offset.value >= 0 then "+" else ""), print offset.value,
					"%'"
				],
				"'%s'"
			];

			_result = Magick.system command x;
		}
	}

	Magick_randThreshold_item = class
		Menuaction "_Random Threshold" "between specified limits, apply random threshold" {
		action x = class
			_result {
			_vislevel = 3;

			channels = Magick.channels_widget;
			low = Scale "Low threshold" 0 100 10;
			high = Scale "High threshold" 0 100 90;
			isPc = Toggle "Thresholds are percent" true;

			command = Magick.command [
				"'%s'",
				channels._flag,
				"-random-threshold",
				"'" ++ print low.value ++ "x" ++ print high.value ++
					(if isPc then "%" else "") ++ "'",
				"'%s'"
			];

			_result = Magick.system command x;
		}
	}

} // end ThresholdMenu_item


// Note: alternatives include:
// convert in.tif -write mpr:TILE +delete -size 200x200 -background XXXX -tile-offset +30+30 tile:mpr:TILE out.tif

Magick_tile_item = class
	Menuaction "_Tile" "fill given size with tiled image" {
	action x = class
		_result {
		_vislevel = 3;

		size = Magick.Size_widget;

		command = Magick.command [
			size._flag,
			"tile:" ++ "'%s'",
			"'%s'"
		];

		_result = Magick.system command x;
	}
}

Magick_tint_item = class
	Menuaction "_Tint" "apply a tint" {
	action x = class
		_result {
		_vislevel = 3;

		foreground = Magick.foreground_widget;
		amount = Scale "amount (percent)" 0 100 50;

		command = Magick.command [
			"'%s'",
			foreground._flag,
			"-tint",
			// snibgo note: although the amount is a percentage, it doesn't need "%" character.
			print amount.value,
			"'%s'"
		];

		_result = Magick.system command x;
	}
}

Magick_transparent_item = class
	Menuaction "_Transparent" "make this colour transparent" {
	action x = class
		_result {
		_vislevel = 3;

		changeColour = Magick.changeCol_widget;

		command = Magick.command [
			"'%s'",
			"-fuzz",
			"'" ++ print changeColour.fuzz.value ++ "%'",
			(if changeColour.nonMatch then "+" else "-") ++ "transparent",
			"'" ++ changeColour.colour._flag ++ "'",
			"'%s'"
		];

		_result = Magick.system command x;
	}
}

Magick_trim_item = class
	Menuaction "_Trim" "trims away border" {
	action x = class
		_result {
		_vislevel = 3;

		fuzz = Magick.fuzz_widget;

		command = Magick.command [
			"'%s'",
			"-fuzz",
			"'" ++ print fuzz.value ++ "%'",
			"-trim +repage",
			"'%s'"
		];

		_result = Magick.system command x;
	}
}

Magick_uniqueCols_item = class
	Menuaction "_Unique colours" "discard all but one of any pixel color" {
	action x = class
		_result {
		_vislevel = 3;

		command = Magick.command [
			"'%s'",
			"-unique-colors",
			"'%s'"
		];

		_result = Magick.system command x;
	}
}

Magick_vignette_item = class
	Menuaction "_Vignette" "soften the edges in vignette style" {
	action x = class
		_result {
		_vislevel = 3;

		radius = Magick.blur_rad_widget;
		sigma = Magick.sigma_widget;
		rx = Scale "Rolloff x (percent)" 0 100 10;
		ry = Scale "Rolloff y (percent)" 0 100 10;
		background = Magick.background_widget;

		command = Magick.command [
			"'%s'",
			background._flag,
			"-vignette",
			print radius.value ++ "x" ++ print sigma.value ++
				(if rx.value >= 0 then "+" else "") ++ print rx.value ++
				(if ry.value >= 0 then "+" else "") ++ print ry.value,
			"'%s'"
		];

		_result = Magick.system command x;
	}
}

Magick_wave_item = class
	Menuaction "_Wave" "shear the columns into a sine wave" {
	action x = class
		_result {
		_vislevel = 3;

		amplitude = Scale "Amplitude (pixels)" 0 100 10;
		wavelength = Scale "Wavelength (pixels)" 0 100 10;

		command = Magick.command [
			"'%s'",
			"-wave",
			print amplitude.value ++ "x" ++ print wavelength.value,
			"'%s'"
		];

		_result = Magick.system command x;
	}
}


