Tasks_capture_item = class
	Menupullright "_Capture" 
		"useful stuff for capturing and preprocessing images" {
	Video_item = class 
		Menuaction "Capture _Video Frame" "capture a frame of still video" {
		// shortcut to prefs
		prefs = Workspaces.Preferences;

		action = class
			_result {
			_vislevel = 3;

			device = prefs.VIDEO_DEVICE;
			channel = Option "Input channel" [
				"TV",
				"Composite 1",
				"Composite 2",
				"Composite 3"
			] prefs.VIDEO_CHANNEL;
			brightness = Slider 0 32767 prefs.VIDEO_BRIGHTNESS;
			colour = Slider 0 32767 prefs.VIDEO_COLOUR;
			contrast = Slider 0 32767 prefs.VIDEO_CONTRAST;
			hue = Slider 0 32767 prefs.VIDEO_HUE;
			frames_hint = "Average this many frames:";
			frames = Slider 0 100 prefs.VIDEO_FRAMES;
			mono = Toggle "Monochrome grab" prefs.VIDEO_MONO;
			crop = Toggle "Crop image" prefs.VIDEO_CROP;

			// grab, but hide it ... if we let the crop edit
			_raw_grab = Image (im_video_v4l1 device channel.value
				brightness.value colour.value contrast.value 
				hue.value frames.value);

			edit_crop
				= Region _raw_grab left top width height
			{
				left = prefs.VIDEO_CROP_LEFT;
				top = prefs.VIDEO_CROP_TOP;
				width = min_pair 
					prefs.VIDEO_CROP_WIDTH (_raw_grab.width + left);
				height = min_pair
					prefs.VIDEO_CROP_HEIGHT (_raw_grab.height + top);
			}

			aspect_ratio = Expression "Stretch vertically by"
				prefs.VIDEO_ASPECT;

			_result 
				= frame'
			{
				frame 
					= edit_crop, crop
					= _raw_grab;

				frame' 
					= colour_transform_to Image_type.B_W frame, mono
					= frame;
			}
		}
	}

	Smooth_image_item = class 
		Menuaction "_Smooth" "remove small features from image" {
		action in = class
			_result {
			_vislevel = 3;

			feature = Slider 1 50 20;

			_result = map_unary (smooth feature.value) in;
		}
	}

	Light_correct_item = class
		Menuaction "_Flatfield" "use white image w to flatfield image i" {
		action w i
			= map_binary wc w i
		{
			wc w i
				= clip2fmt i.format (w' * i)
			{
				fac = mean w / max w;
				w' = fac * (max w / w);
			}
		}
	}

	Image_rank_item = Filter_rank_item.Image_rank_item;

	Tilt_item = Filter_tilt_item;

	sep1 = Menuseparator;

	White_balance_item = class
		Menuaction "_White Balance" 
			"use average of small image to set white of large image" {
		action a b = class
			_result {
			_vislevel = 3;

			white_hint = "Set image white to:";
			white = Colour_picker "Lab" [100, 0, 0];

			_result
					= map_binary wb a b
			{
				wb a b
					= colour_transform_to (get_type image) image_xyz'
				{
					area x = x.width * x.height;
					larger x y = area x > area y;
					args = sortc larger [a, b];
					image = args?0;
					patch = args?1;
					to_xyz = colour_transform_to Image_type.XYZ;
			
					// white balance in XYZ
					patch_xyz = to_colour (to_xyz patch);
					white_xyz = to_xyz white;

					facs = (mean patch_xyz / mean white_xyz) * 
						(white_xyz / patch_xyz);

					image_xyz = to_xyz image;
					image_xyz' = image_xyz * facs;
				}
			}
		}
	}

	Gamma_item = Image_levels_item.Gamma_item;

	Tone_item = Image_levels_item.Tone_item;

	sep2 = Menuseparator;

	Crop_item = Image_crop_item;

	Rotate_item = Image_transform_item.Rotate_item;

	Flip_item = Image_transform_item.Flip_item;

	Resize_item = Image_transform_item.Resize_item;

	Rubber_item = Image_transform_item.Image_rubber_item;

	sep3 = Menuseparator;

	ICC_item = Colour_icc_item;

	Temp_item = Colour_temperature_item;

	Find_calib_item = class 
		Menuaction "Find _Colour Calibration" 
			"find an RGB -> XYZ transform from an image of a colour chart" {
		action image = class
			_result {
			_check_args = [
				[image, "image", check_Image]
			];
			_vislevel = 3;

			// get macbeth data file to use
			macbeth = Pathname "Pick a Macbeth data file" 
				"$VIPSHOME/share/$PACKAGE/data/macbeth_lab_d65.mat";

			// get max of input image
			_max_value = Image_format.maxval image.format;

			// measure chart image
			_camera = im_measure image.value 0 0 image.width image.height 6 4;

			// load true values
			_true_Lab = Matrix_file macbeth.value;
			_true_XYZ = colour_transform 
				Image_type.LAB Image_type.XYZ _true_Lab;

			// get Ys of greyscale
			_true_grey_Y = map (extract 1) (drop 18 _true_XYZ.value);

			// camera greyscale (all bands)
			_camera_grey = drop 18 _camera.value;

			// normalise both to 0-1 and combine
			_camera_grey' = map (map (multiply (1 / _max_value))) _camera_grey;
			_true_grey_Y' = map (multiply (1 / 100)) _true_grey_Y;
			_comb = Matrix (map2 cons _true_grey_Y' _camera_grey');

			// make a linearising lut ... zero on left
			_linear_lut = im_invertlut _comb (_max_value + 1);

			// and display it
			linearising_lut = Image _linear_lut;

			// map the original image through the lineariser to 
			// get linear 0-1 RGB image
			_image' = hist_map linearising_lut.value image.value;

			// remeasure and solve for RGB -> XYZ
			_camera' = im_measure _image' 0 0 image.width image.height 6 4;
			_pinv = (transpose _camera' * _camera') ** -1;
			M = transpose (_pinv * transpose _camera' * _true_XYZ);

			// convert linear RGB camera to Lab 
			_result = (Image @
				colour_transform Image_type.XYZ Image_type.LAB @
				cast_float @
				recomb M) _image';

			// measure again and compute dE76
			_camera'' = im_measure _result.value 0 0 
				image.width image.height 6 4;

			_dEs = map abs_vec (map Vector (_camera'' - _true_Lab).value);
			final_dE76 = mean (Vector _dEs);
			_max_dE = foldr max_pair 0 _dEs;
			_worst = index (equal _max_dE) _dEs;
			worst_patch = _macbeth_names ? _worst ++ " (patch " ++ 
				print (_worst + 1) ++ ", " ++ 
			print _max_dE ++ " dE)";
		}
	}

	Apply_calib_item = class 
		Menuaction "_Apply Colour Calibration" 
			"apply an RGB -> LAB transform to an image" {
		action a b 
			= result, is_instanceof calib_name calib && is_Image image
			= error (_ "bad arguments to " ++ "Calibrate_image")
		{
			// the name of the calib object we need
			calib_name = "Tasks_capture_item.Find_calib_item.action";

			// get the Calibrate_chart arg first
			args = sortc (const (is_instanceof calib_name)) [a, b];
			calib = args?1;
			image = args?0;

			// map the original image through the lineariser to get 
			// linear 0-1 RGB image
			image' = hist_map calib.linearising_lut image;

			// convert linear RGB camera to Lab 
			result = colour_transform Image_type.XYZ Image_type.LAB 
				((float) (recomb calib.M image'));
		}
	}
}

Tasks_mosaic_item = class
	Menupullright "_Mosaic" "building image mosaics" {
	/* Check and group a point list by image.
	 */
	mosaic_sort_test l
		= error "mosaic: not all points",
			!is_listof is_Mark l
		= error "mosaic: points not on two images",
			len images != 2 
		= error "mosaic: images do not match in format and coding",
			!all_equal (map get_format l) || !all_equal (map get_coding l)
		= error "mosaic: not same number of points on each image",
			!foldr1 equal (map len l') 
		= l'
	{
		// test for all elements of a list equal
		all_equal l = land (map (equal (hd l)) (tl l));
	
		// all the different images
		images = mkset pointer_equal (map get_image l);
	
		// find all points defined on image
		test_image image p = (get_image p) === image;
		find l image = filter (test_image image) l;
	
		// group point list by image
		l' = map (find l) images;
	}
	
	/* Sort a point group to get right before left, and within each group to 
	 * get above before below.
	 */
	mosaic_sort_lr l
		= l''
	{
		// sort to get upper point first
		above a b = a.top < b.top;
		l' = map (sortc above) l;
	
		// sort to get right group before left group
		right a b = a?0.left > b?0.left;
		l'' = sortc right l';
	}
	
	/* Sort a point group to get top before bottom, and within each group to 
	 * get left before right.
	 */
	mosaic_sort_tb l
		= l''
	{
		// sort to get upper point first
		left a b = a.left < b.left;
		l' = map (sortc left) l;
	
		// sort to get right group before left group
		below a b = a?0.top > b?0.top;
		l'' = sortc below l';
	}
	
	/* Put 'em together! Group by image, sort vertically (or horizontally) with
	 * one of the above, transpose to get pairs matched up, and flatten again.
	 */
	mosaic_sort fn = concat @ transpose @ fn @ mosaic_sort_test;

	Mosaic_1point_item = class 
		Menupullright "_One Point" "join two images with a single tie point" {
		check_ab_args a b = [
			[a, "a", check_Mark],
			[b, "b", check_Mark]
		];
	
		// shortcut to prefs
		prefs = Workspaces.Preferences;
		search_area = prefs.MOSAIC_WINDOW_SIZE;
		object_size = prefs.MOSAIC_OBJECT_SIZE;
		blend_width_widget = Slider 0 100 prefs.MOSAIC_MAX_BLEND_WIDTH;
		refine_widget = Toggle "Refine selected tie-points" prefs.MOSAIC_REFINE;

		lr_mos _refine a b = class 
			Image _result {
			_check_args = check_ab_args a b;
	
			blend_width = blend_width_widget;
			refine = _refine;
	
			_result 
				= im_lrmosaic a'.image.value b'.image.value 0 
					a'.left a'.top b'.left b'.top
					(object_size / 2) (search_area / 2) 0 blend_width.value,
						refine
				= im_lrmerge a'.image.value b'.image.value
					(b'.left - a'.left) (b'.top - a'.top) blend_width.value
			{
				sorted = mosaic_sort mosaic_sort_lr [a, b];
				a' = sorted?0;
				b' = sorted?1;
			}
		}

		tb_mos _refine a b = class
			Image _result {
			_check_args = check_ab_args a b;
	
			blend_width = blend_width_widget;
			refine = _refine;
	
			_result 
				= im_tbmosaic a'.image.value b'.image.value 0 
					a'.left a'.top b'.left b'.top
					(object_size / 2) (search_area / 2) 0 blend_width.value,
						refine
				= im_tbmerge a'.image.value b'.image.value
					(b'.left - a'.left) (b'.top - a'.top) blend_width.value
			{
				sorted = mosaic_sort mosaic_sort_tb [a, b];
				a' = sorted?0;
				b' = sorted?1;
			}
		}

		Left_right_item = class 
			Menuaction "_Left to Right" 
				"join two images left-right with a single tie point" {
			action a b = lr_mos refine_widget a b;
		}

		Top_bottom_item = class 
			Menuaction "_Top to Bottom" 
				"join two images top-bottom with a single tie point" {
			action a b = tb_mos refine_widget a b;
		}
	
		sep1 = Menuseparator;

		Left_right_manual_item = class 
			Menuaction "Manual L_eft to Right" 
				"join left-right, no auto-adjust of tie points" {
			action a b = lr_mos false a b;
		}

		Top_bottom_manual_item = class 
			Menuaction "Manual T_op to Bottom" 
				"join top-bottom, no auto-adjust of tie points" {
			action a b = tb_mos false a b;
		}
	}

	Mosaic_2point_item = class 
		Menupullright "_Two Point" "join two images with two tie points" {
		check_abcd_args a b c d = [
			[a, "a", check_Mark],
			[b, "b", check_Mark],
			[c, "c", check_Mark],
			[d, "d", check_Mark]
		];
	
		// shortcut to prefs
		prefs = Workspaces.Preferences;
		search_area = prefs.MOSAIC_WINDOW_SIZE;
		object_size = prefs.MOSAIC_OBJECT_SIZE;
		blend_width_widget = Slider 0 100 prefs.MOSAIC_MAX_BLEND_WIDTH;
		refine_widget = Toggle "Refine selected tie-points" prefs.MOSAIC_REFINE;

		Left_right_item = class 
			Menuaction "_Left to Right" 
				"join two images left-right with a pair of tie points" {
			action a b c d = class 
				Image _result {
				_check_args = check_abcd_args a b c d;
	
				blend_width = blend_width_widget;
				refine = refine_widget;
	
				_result 
					= im_lrmosaic1 a'.image.value b'.image.value 0
						a'.left a'.top b'.left b'.top
						c'.left c'.top d'.left d'.top
						(object_size / 2) (search_area / 2)
						0 blend_width.value,
							refine
					= im_lrmerge1 a'.image.value b'.image.value
						a'.left a'.top b'.left b'.top
						c'.left c'.top d'.left d'.top
						blend_width.value
				{
					sorted = mosaic_sort mosaic_sort_lr [a, b, c, d];
					a' = sorted?0;
					b' = sorted?1;
					c' = sorted?2;
					d' = sorted?3;
				}
			}
		}

		Top_bottom_item = class 
			Menuaction "_Top to Bottom" 
				"join two images top-bottom with a pair of tie points" {
			action a b c d = class 
				Image _result {
				_check_args = check_abcd_args a b c d;
	
				blend_width = blend_width_widget;
				refine = refine_widget;
	
				_result 
					= im_tbmosaic1 a'.image.value b'.image.value 0
						a'.left a'.top b'.left b'.top
						c'.left c'.top d'.left d'.top
						(object_size / 2) (search_area / 2)
						0 blend_width.value,
							refine
					= im_tbmerge1 a'.image.value b'.image.value
						a'.left a'.top b'.left b'.top
						c'.left c'.top d'.left d'.top
						blend_width.value
				{
					sorted = mosaic_sort mosaic_sort_tb [a, b, c, d];
					a' = sorted?0;
					b' = sorted?1;
					c' = sorted?2;
					d' = sorted?3;
				}
			}
		}
	}
	
	sep1 = Menuseparator;

	Balance_item = class 
		Menuaction "Mosaic _Balance" 
			"disassemble mosaic, scale brightness to match, reassemble" {
		action x 
			= map_unary balance x
		{
			balance x
				= oo_unary_function balance_op x, is_class x
				= im_global_balancef x 
					Workspaces.Preferences.MOSAIC_BALANCE_GAMMA, 
					is_image x
				= error (_ "bad arguments to " ++ "balance")
			{
				balance_op = Operator "balance" balance 
					Operator_type.COMPOUND_REWRAP false;
			}
		}
	}

////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////
Manual_balance_item = class
	Menupullright "Manual B_alance" "balance tonality of user defined areas" {
	prefs = Workspaces.Preferences;
	
	////////////////////////////////////////////////////////////////////////////////////
	Balance_find_item = class
		Menuaction "_Find Values"
			 "calculates values required to scale and offset balance user defined areas in a given image"
			 /* Outputs a matrix of scale and offset values. Eg. Values required to balance the secondary 
			  * structure in an X-ray image.  Takes an X-ray image an 8-bit control mask and a list of 
			  * 8-bit reference masks, where the masks are white on a black background.
			  */
	{
		action im_in m_control m_group = class
			Matrix values{
			_vislevel = 1;

			_control_im = if_then_else m_control im_in 0;
			_control_meanmax = so_meanmax _control_im;
			_group_check = is_instanceof "Group"  m_group;
			_m_list = m_group.value, _group_check
		     		= m_group;

			process m_current mat_in = mat_out
				{so_values  = so_calculate _control_meanmax im_in m_current;
				 mat_out = join [so_values] mat_in;}
		
			values = (foldr process [] _m_list);
		}
	}
	
	////////////////////////////////////////////////////////////////////////////////////
	Balance_check_item = class 
		Menuaction "_Check Values"
			 "allows calculated set of scale and offset values to be checked and adjusted if required" 
			 /* Outputs adjusted matrix of scale and offset values and scale and offset image maps.
			  * Eg. Check values required to balance the secondary structure in an X-ray image.  
			  * Takes an X-ray image an 8-bit control mask and a list of 8-bit reference masks, 
			  * where the masks are white on a black background. 
			  */
	{
		action im_in m_matrix m_group = class
			Image value 
			{
			_vislevel = 3;
			
			blur = Slider 1 10 1;
			_blur = (blur.value/2 + 0.5), blur.value > 1
				  =  1;
		
			_group_check = is_instanceof "Group"  m_group;
			_m_list = m_group.value, _group_check
		     		= m_group;
						
			adjust = Matrix_rec mat_a
				{
				no_masks = len _m_list;
				mat_a = replicate no_masks [0, 0];
				}
			
		// Apply the user defined adjustments to the inputted matrix of scale and offset values	 
			_adjusted = map2 fn_adjust m_matrix.value adjust.value;
				fn_adjust a b = [(a?0 + b?0), (a?1 + (a?1 * b?1))];
				
			_scaled_ims = map (fn_so_apply im_in) _adjusted;
				fn_so_apply im so = map_unary adj im
					{adj im = im * (so?0) + (so?1);}			
			_im_pairs = zip2 _m_list _scaled_ims;
			
		// Prepare black images as starting point. ////////////
			_blank = image_new (_m_list?0).width (_m_list?0).height 1 6 Image_coding.NOCODING 1 0 0 0;
			_pair_start = [(_blank + 1), _blank];
			
			Build = Toggle "Build Scale and Offset Correction Images" false;
			
			Output = class
				{ 
				_vislevel = 1;
				scale_im = _build?0;
				offset_im = _build?1;	
				so_values = Matrix _adjusted;
				
				_build = [Image so_images?0, Image so_images?1], Build
				       = ["Scale image not built.", "Offset image not built."]
					{
					m_list' = transpose [_m_list];			
					m_all = map2 join m_list' _adjusted;					
					so_images = foldr process_2 _pair_start m_all;					
					}
				}
				  
			value = (foldr process_1 im_in_b _im_pairs).value
				{im_in_b = map_unary cast_float im_in;}
				
			process_1 m_current im_start 
				= im_out
				{ 
				bl_mask    = convsep (matrix_blur _blur) (get_image m_current?0);
				blended_im  = im_blend bl_mask (m_current?1).value im_start.value;
				im_out      = Image (clip2fmt im_start.format blended_im);
				}			
			
			// Process for building scale and offset image. 
			process_2 current p_start 
				= p_out
				{ 
				im_s = if ((current?0) > 128) then current?1 else _blank;
				im_o = if ((current?0) > 128) then current?2 else _blank;
				
				im_s' = convsep (matrix_blur _blur) (im_s != 0);
				im_o' = convsep (matrix_blur _blur) (im_o != 0);
				
				im_s'' = im_blend im_s'.value im_s.value p_start?0;
				im_o'' = im_blend im_o'.value im_o.value p_start?1;
				
				p_out  = [im_s'', im_o''];
				}
		}
	}
	
	////////////////////////////////////////////////////////////////////////////////////
	Balance_apply_item = class 
		Menuaction "_Apply Values" 
			 "apply scale and offset corrections, defined as image maps, to a given image" 
			 /* Outputs the balanced image. Eg. Balance the secondary structure in an X-ray image.  Takes an 
			  * X-ray image an 32-bit float scale image and a 32-bit offset image.
			  */
	{
		action im_in scale_im offset_im = class
			Image value 
			{
			_vislevel = 1;

			xfactor = im_in.width/scale_im.width;
			yfactor = im_in.height/scale_im.height;
			
			_scale_im = resize xfactor yfactor 1 scale_im;
			_offset_im = resize xfactor yfactor 1 offset_im;
			
			value = get_image ( clip2fmt im_in.format ( ( im_in * _scale_im ) +  _offset_im ) ); 	
			}
		}
}

    Tilt_item = Filter_tilt_item;

	sep2 = Menuseparator;

	Rebuild_item = class 
		Menuaction "_Rebuild" 
			"disassemble mosaic, substitute image files and reassemble" {
		action x = class 
			_result {
			_vislevel = 3;
	
			old = String "In each filename, replace" "foo";
			new = String "With" "bar";
	
			_result
				= map_unary remosaic x
			{
				remosaic image 
					= Image (im_remosaic image.value old.value new.value);
			}
		}
	}

	sep3 = Menuseparator;

Clone_area_item = class
   Menuaction "_Clone Area"
       "replace dark or light section of im1 with pixels from im2"
   {
   action im1 im2 = class
       _result {
       _check_args = [
           [im1, "im1", check_Image],
           [im2, "im2", check_Image]
       ];
                 _vislevel = 3;                            /* Region on first
image placed in the top left hand corner,
        * positioned and size relative to the height and width of im1.
        */
       r1 = Region_relative im1 0.05 0.05 0.05 0.05;
             /* Mark on second image placed in the top left hand corner,
        * positioned relative to the height and width of im2. Used to
        * define _r2, the region from which the section of image is cloned
        * from.
        */
       p2 = Mark_relative im2 0.05 0.05;              _r2 = Region im2 p2.left
p2.top r1.width r1.height;
             mask = [r1 <= Options.scale_cutoff, r1 >=
Options.scale_cutoff]?(Options.replace);
                 Options = class
           {
           _vislevel = 3;
                     pause = Toggle "Pause process" true;
                         /* Option toggle used to define whether the user is
            * replacing a dark or a light area.
            */
           replace = Option "Replace" [ "A Dark Area", "A Light Area" ] 1;

           // Used to select the area to be replaced.
            scale_cutoff = Slider 0.01 mx (mx / 2)
               {mx = Image_format.maxval im1.format;}
             //Allows replacement with scale&offset balanced gaussian noise.
           balance = Toggle "Balance cloned data to match surroundings." true;
                             //Allows replacement with scale&offset balanced
                             //gaussian noise.
           process = Toggle "Replace area with Gaussian noise." false;
           }
                     _result    = im1, Options.pause
               = Image (im_insert im1.value patch r1.left r1.top)
           {              r2 = Region im2 p2.left p2.top r1.width r1.height;
           ref_meanmax = so_meanmax (if mask then 0 else r1);
                     mask8 = Matrix_mor [[255, 255, 255], [255, 255, 255],
[255, 255, 255]];
           mask_a = map_unary (dilate mask8) mask;
           mask_b = convsep (matrix_blur 2) mask_a;
                     patch = so_balance ref_meanmax r1 r2 mask_b
Options.process, Options.balance
                 = so_balance ref_meanmax r1 r2 mask_b Options.process,
Options.process
                 = im_blend (get_image mask_b) (get_image r2) (get_image r1);
           }
       }
   } 
}

Tasks_frame_item = Frame_item;

Tasks_print_item = class
	Menupullright "_Print" "useful stuff for image output" {

	Rotate_item = Image_transform_item.Rotate_item;

	Flip_item = Image_transform_item.Flip_item;

	Resize_item = Image_transform_item.Resize_item;

	Tone_item = class 
		Menuaction "_Adjust Tone Curve" "adjust tone curve on L*" {
		action x = class 
			_result {
			_vislevel = 3;

			auto = Option "Set black and white point" [
				"Manually",
				"Automatically from image histogram"
			] 0;
			black = Slider 0 100 0;
			white = Slider 0 100 100;

			shadow_point = Slider 0.1 0.3 0.2;
			mid_point = Slider 0.4 0.6 0.5;
			highlight_point = Slider 0.7 0.9 0.8;

			shadow_adjust = Slider (-15) 15 0;
			mid_adjust = Slider (-30) 30 0;
			highlight_adjust = Slider (-15) 15 0;

			preview_curve = Image (im_tone_build black.value white.value
				shadow_point.value mid_point.value highlight_point.value
				shadow_adjust.value mid_adjust.value highlight_adjust.value);

			_result
				= map_unary process x
			{
				process image
					= tone_map curve lab 
				{
					lab = colour_transform_to Image_type.LABQ image;
					curve 
						= preview_curve, auto == 0
						= tone_analyse 
							shadow_point mid_point highlight_point
							shadow_adjust mid_adjust highlight_adjust
							lab;
				}
			}
		}
	}

	Sharpen_item = class 
		Menuaction "_Sharpen" 
			"unsharp filter tuned for typical inkjet printers" {
		action x = class 
			_result {
			_vislevel = 3;
	
			// strange order forced on us by need to keep numbering backwards
			// compatible though 7.10
			target_dpi = Option "Sharpen for print at" [
				"300 dpi",
				"150 dpi",
				"75 dpi",
				"400 dpi"
			] 0;
	
			_result
				= map_unary process x
			{
				process image
					= sharpen params?0 params?1 
						params?2 params?3 params?4 params?5
						(colour_transform_to Image_type.LABQ image)
				{
					// sharpen params for various dpi
					// just change the size of the area we search
					param_table = [
						[7, 2.5, 40, 20, 0.5, 1.5],
						[5, 2.5, 40, 20, 0.5, 1.5],
						[3, 2.5, 40, 20, 0.5, 1.5],
						[11, 2.5, 40, 20, 0.5, 1.5]
					];
					params = param_table?target_dpi;
				}
			}
		}
	}

	sep1 = Menuseparator;

	Temp_item = Colour_temperature_item;

	ICC_item = Colour_icc_item;
}
