1Hist_new_item = class
2	Menupullright "_New" "new histogram" {
3	Hist_item = class
4		Menuaction "_Identity" "make an identity histogram" {
5		action = class
6			_result {
7			_vislevel = 3;
8
9			d = Option "Depth" ["8 bit", "16 bit"] 0;
10			_result = Plot [] ([im_identity 1, im_identity_ushort 1 65536]?d);
11		}
12	}
13
14	Hist_new_from_matrix = Matrix_buildlut_item;
15
16	Hist_from_image_item = class
17		Menuaction "Ta_g Image As Histogram" "set image Type to Histogram" {
18		action x = hist_tag x;
19	}
20
21	Tone_item = class
22		Menuaction "_Tone Curve" "make a new tone mapping curve" {
23		action = class
24			_result {
25			_vislevel = 3;
26
27			d = Option "Depth" ["8 bit", "16 bit"] 0;
28			b = Scale "Black point"  0 100 0;
29			w = Scale "White point"  0 100 100;
30
31			sp = Scale "Shadow point" 0.1 0.3 0.2;
32			mp = Scale "Mid-tone point" 0.4 0.6 0.5;
33			hp = Scale "Highlight point" 0.7 0.9 0.8;
34
35			sa = Scale "Shadow adjust" (-15) 15 0;
36			ma = Scale "Mid-tone adjust" (-30) 30 0;
37			ha = Scale "Highlight adjust" (-15) 15 0;
38
39			_result
40				= tone_build fmt b w sp mp hp sa ma ha
41			{
42				fmt = [Image_format.UCHAR, Image_format.USHORT]?d;
43			}
44		}
45	}
46}
47
48Hist_convert_to_hist_item = class
49	Menuaction "Con_vert to Histogram" "convert anything to a histogram" {
50	action x = hist_tag (to_image x);
51}
52
53Hist_find_item = class
54	Menupullright "_Find" "find a histogram" {
55	Oned_item = class
56		Menuaction "_One Dimension"
57			"for a n-band image, make an n-band 1D histogram" {
58		action x = map_unary hist_find x;
59	}
60
61	Nd_item = class
62		Menuaction "_Many Dimensions"
63			"for a n-band image, make an n-dimensional histogram" {
64		action x = class
65			_result {
66			_vislevel = 3;
67
68			// default to something small-ish
69			bins = Expression "Number of bins in each dimension" 8;
70
71			_result
72				= map_unary process x
73			{
74				process in
75					= hist_find_nD bins in;
76			}
77		}
78	}
79
80	Indexed_item = class
81		Menuaction "_Indexed"
82			"use a 1-band index image to pick bins for an n-band image" {
83		action x y
84			= map_binary map x y
85		{
86			map a b
87				= hist_find_indexed index im
88			{
89				[im, index] = sortc (const is_index) [a, b];
90
91				is_index x
92					= has_image x && b == 1 &&
93						(f == Image_format.UCHAR || f == Image_format.USHORT)
94				{
95					im = get_image x;
96					b = get_bands x;
97					f = get_format x;
98				}
99			}
100		}
101	}
102}
103
104Hist_map_item = class
105	Menuaction "_Map" "map an image through a histogram" {
106	action x y
107		= map_binary map x y
108	{
109		map a b
110			= hist_map hist im
111		{
112			[im, hist] = sortc (const is_hist) [a, b];
113		}
114	}
115}
116
117Hist_eq_item = Filter_enhance_item.Hist_equal_item;
118
119#separator
120
121Hist_cum_item = class
122	Menuaction "_Integrate"
123		"form cumulative histogram" {
124	action x = map_unary hist_cum x;
125}
126
127Hist_diff_item = class
128	Menuaction "_Differentiate"
129		"find point-to-point differences (inverse of Integrate)" {
130	action x = map_unary hist_diff x;
131}
132
133Hist_norm_item = class
134	Menuaction "N_ormalise" "normalise a histogram" {
135	action x = map_unary hist_norm x;
136}
137
138Hist_inv_item = class
139	Menuaction "In_vert" "invert a histogram" {
140	action x = map_unary hist_inv x;
141}
142
143Hist_match_item = class
144	Menuaction "Ma_tch"
145		"find LUT which will match first histogram to second" {
146	action in ref = map_binary hist_match in ref;
147}
148
149Hist_zerox_item = class
150	Menuaction "_Zero Crossings" "find zero crossings" {
151	action x = class
152		_result {
153		_vislevel = 3;
154
155		edge = Option "Direction" [
156			"Positive-going",
157			"Negative-going"
158		] 0;
159
160		_result
161			= map_unary (zerox (if edge == 0 then -1 else 1)) x;
162	}
163}
164
165#separator
166
167Hist_profile_item = class
168	Menuaction "Find _Profile"
169		"search from image edges for non-zero pixels" {
170	action x = class
171		_result {
172		_vislevel = 3;
173
174		edge = Option "Search from" [
175			"Top edge down",
176			"Left edge to right",
177			"Bottom edge up",
178			"Right edge to left"
179		] 2;
180
181		_result
182			= map_unary profile x
183		{
184			profile image
185				= (Plot_histogram @ hist_tag) [
186					profilemb 0 image.value,
187					profilemb 1 image.value,
188					profilemb 0 (fliptb image.value),
189					profilemb 1 (fliplr image.value)
190				]?edge;
191
192			// im_profile only does 1 band images :-(
193			profilemb d = bandjoin @ map (converse im_profile d) @ bandsplit;
194		}
195	}
196}
197
198Hist_project_item = class
199	Menuaction "Find Pro_jections"
200		"find horizontal and vertical projections" {
201	action x = class {
202		_vislevel = 2;
203
204		_result = map_unary project x;
205
206		// extract the result ... could be a group
207		extr n
208			= Plot_histogram _result?n, is_list _result
209			= Group (map (Plot_histogram @ converse subscript n) _result.value);
210
211		horizontal = extr 0;
212		vertical = extr 1;
213		centre = (gravity horizontal, gravity vertical);
214	}
215}
216
217#separator
218
219Hist_graph_item = class
220	Menuaction "P_lot Slice" "plot a slice along a guide or arrow" {
221	action x = class
222		_value {
223		_vislevel = 3;
224
225		width = Scale "Width" 1 40 1;
226		displace = Scale "Horizontal displace" (-50) 50 0;
227		vdisplace = Scale "Vertical displace" (-50) 50 0;
228
229		_value
230			= map_unary graph x
231		{
232			graph arrow
233				= hist_tag area'
234			{
235				area = extract_arrow
236					displace.value vdisplace.value width.value arrow;
237
238				// squish vertically to get an average
239				area' = resize Kernel_linear 1 (1 / width.value) area;
240			}
241		}
242	}
243}
244
245Extract_arrow_item = class
246	Menuaction "Extract _Arrow" "extract the area around an arrow" {
247	action x = class
248		_value {
249		_vislevel = 3;
250
251		width = Scale "Width" 1 40 1;
252		displace = Scale "Horizontal displace" (-50) 50 0;
253		vdisplace = Scale "Vertical displace" (-50) 50 0;
254
255		_value
256			= map_unary (extract_arrow
257				displace.value vdisplace.value width.value) x;
258	}
259}
260
261Hist_plot_item = class
262	Menuaction "Plot _Object"
263		"plot an object as a bar, point or line graph" {
264	action x = class
265		_result {
266		_vislevel = 3;
267
268		caption = Expression "Chart caption" "none";
269		format = Option_enum "Format" Plot_format.names "YYYY";
270		style = Option_enum "Style" Plot_style.names "Line";
271
272		auto = Toggle "Auto Range" true;
273		xmin = Expression "X range minimum" 0;
274		xmax = Expression "X range maximum" 1;
275		ymin = Expression "Y range minimum" 0;
276		ymax = Expression "Y range maximum" 1;
277		xcaption = Expression "X axis caption" "none";
278		ycaption = Expression "Y axis caption" "none";
279		series_captions = Expression "Series captions" ["Band 0"];
280
281		_result
282			= Plot options (image x)
283		{
284			options
285				= [$style => style.value, $format => format.value] ++
286					range ++ captions;
287			range
288				= [], auto
289				= [$xmin => xmin.expr, $xmax => xmax.expr,
290					$ymin => ymin.expr, $ymax => ymax.expr];
291
292			captions
293				= concat (map test caption_options) ++
294				  [$series_captions => series_captions.expr]
295			{
296				caption_options = [
297					$caption => caption.expr,
298					$xcaption => xcaption.expr,
299					$ycaption => ycaption.expr
300				];
301				test x
302					= [], value == "none"
303					= [option_name => value]
304				{
305					[option_name, value] = x;
306				}
307			}
308
309			image x
310				= image (extract_arrow 0 0 1 x), is_Arrow x
311				= get_image x, has_image x
312				= x2b im, b == 1
313				= im
314			{
315				im = get_image (to_image x);
316				w = get_width im;
317				h = get_height im;
318				b = get_bands im;
319
320				// matrix to image makes a 1-band mxn image
321				// we need to put columns into bands
322				x2b im
323					= bandjoin (map extract_col [0 .. w - 1])
324				{
325						extract_col x = extract_area x 0 1 h im;
326				}
327			}
328		}
329	}
330}
331