1
2/* is_colour_space str: is a string one of nip's colour space names
3 */
4is_colour_space str = Image_type.colour_spaces.present 0 str;
5
6/* is_colour_type n: is a number one of VIPS's colour spaces
7 */
8is_colour_type n = Image_type.colour_spaces.present 1 n;
9
10/* is_number: is a real or a complex number.
11 */
12is_number a = is_real a || is_complex a;
13
14/* is_int: is an integer
15 */
16is_int a = is_real a && a == (int) a;
17
18/* is_uint: is an unsigned integer
19 */
20is_uint a = is_int a && a >= 0;
21
22/* is_pint: is a positive integer
23 */
24is_pint a = is_int a && a > 0;
25
26/* is_preal: is a positive real
27 */
28is_preal a = is_real a && a > 0;
29
30/* is_ureal: is an unsigned real
31 */
32is_ureal a = is_real a && a >= 0;
33
34/* is_letter c: true of character c is an ASCII letter
35 *
36 * is_letter :: char -> bool
37 */
38is_letter c = ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z');
39
40/* is_digit c: true if character c is an ASCII digit
41 *
42 * is_digit :: char->bool
43 */
44is_digit x = '0' <= x && x <= '9';
45
46/* A whitespace character.
47 *
48 * is_space :: char->bool
49 */
50is_space = member " \n\t";
51
52/* is_listof p s: true if finite list with p true for every element.
53 */
54is_listof p l = is_list l && land (map p l);
55
56/* is_string s: true if finite list of char.
57 */
58is_string s = is_listof is_char s;
59
60/* is_real_list l: is l a list of real numbers ... test each element,
61 * so no infinite lists pls.
62 */
63is_real_list l = is_listof is_real l;
64
65/* is_string_list l: is l a finite list of finite strings.
66 */
67is_string_list l = is_listof is_string l;
68
69/* is_rectangular l: is l a rectangular data structure
70 */
71is_rectangular l
72	= true, !is_list l
73	= true, land (map is_obj l)
74	= true, land (map is_list l) &&
75		land (map (not @ is_obj) l) &&
76		land (map is_rectangular l) &&
77		len l > 0 &&
78		land (map (equal (hd lengths)) (tl lengths))
79	= false
80{
81	// treat strings as a base type, not [char]
82	is_obj x = !is_list x || is_string x;
83	lengths = map len l;
84}
85
86/* is_matrix l: is l a list of lists of real numbers, all the same length
87 */
88is_matrix l = is_listof is_real_list l && is_rectangular l;
89
90/* is_square_matrix l: is l a matrix with width == height
91 */
92is_square_matrix l
93      = true, l == []
94      = is_matrix l && len l == len (hd l);
95
96/* is_oddmatrix l: is l a matrix with odd-length sides
97 */
98is_oddmatrix l
99      = true, l == []
100      = is_matrix l && (len l) % 2 == 1 && (len (l?0)) % 2 == 1;
101
102/* is_odd_square_matrix l: is l a square_matrix with odd-length sides
103 */
104is_odd_square_matrix l = is_square_matrix l && (len l) % 2 == 1;
105
106/* Is an item in a column of a table?
107 */
108is_incolumn n table x = member (map (extract n) table) x;
109
110/* Is HGuide or VGuide.
111 */
112is_HGuide x = is_instanceof "HGuide" x;
113
114is_VGuide x = is_instanceof "VGuide" x;
115
116is_Guide x = is_HGuide x || is_VGuide x;
117
118is_Mark x = is_instanceof "Mark" x;
119
120is_Group x = is_instanceof "Group" x;
121
122is_Image x = is_instanceof "Image" x;
123
124is_Region x = is_instanceof "Region" x;
125
126is_Real x = is_instanceof "Real" x;
127
128is_Matrix x = is_instanceof "Matrix_base" x;
129
130is_Vector x = is_instanceof "Vector" x;
131
132is_Colour x = is_instanceof "Colour" x;
133
134is_Arrow x = is_instanceof "Arrow" x;
135
136is_Bool x = is_instanceof "Bool" x;
137
138is_Slider x = is_instanceof "Scale" x;
139
140is_Rect x = is_instanceof "Rect" x;
141
142is_Number x = is_instanceof "Number" x;
143
144is_Expression x = is_instanceof "Expression" x;
145
146is_String x = is_instanceof "String" x;
147
148/* A list of the form [[1,2],[3,4],[5,6]...]
149 */
150is_xy_list l
151	= is_list l && land (map xy l)
152{
153	xy l = is_real_list l && len l == 2;
154}
155
156/* Does an object have a sensible VIPS type?
157 */
158has_type x = is_image x || is_Image x || is_Arrow x || is_Colour x;
159
160/* Try to get a VIPS image type from an object.
161 */
162get_type x
163	= get_type_im x, is_image x
164	= get_type_im x.value, is_Image x
165	= get_type_im x.image.value, is_Arrow x
166	= Image_type.colour_spaces.lookup 0 1 x.colour_space, is_Colour x
167	// slightly odd ... but our display is always 0-255, so it makes sense for
168	// a plain number to be in the same range
169	= Image_type.sRGB, is_real x
170	= error ("get_type: unable to get type from " ++ print x)
171{
172	// get the type from a VIPS image ... but only if it makes sense with
173	// the rest of the image
174
175	// we often have Type set wrong, hence the ugly guessing :-(
176	get_type_im im
177		= Image_type.LABQ, coding == Image_coding.LABPACK
178		= Image_type.B_W, bands == 1
179		= type, bands == 3 && is_colorimetric
180		= Image_type.sRGB, bands == 3 && !is_colorimetric
181		= Image_type.MULTIBAND, bands != 3 && !is_colorimetric
182		= type
183	{
184		type = im_header_int "Type" im;
185		coding = im_header_int "Coding" im;
186		bands = im_header_int "Bands" im;
187
188		// 3-band colorimetric types we allow ... the things which the
189		// Colour/Convert To menu can make, excluding mono.
190		ok_types = [
191			Image_type.sRGB,
192			Image_type.LAB,
193			Image_type.LABQ,
194			Image_type.LABS,
195			Image_type.LCH,
196			Image_type.XYZ,
197			Image_type.YXY,
198			Image_type.UCS
199		];
200		is_colorimetric = member ok_types type;
201	}
202}
203
204has_format x = has_member "format" x || is_Arrow x || is_image x;
205
206get_format x
207	= x.format, has_member "format" x
208	= x.image.format, is_Arrow x
209	= im_header_int "BandFmt" x, is_image x
210	= error ("get_format: unable to get format from " ++ print x);
211
212has_bits x = has_member "bits" x || is_Arrow x || is_image x;
213
214get_bits x
215	= x.bits, has_member "bits" x
216	= x.image.bits, is_Arrow x
217	= im_header_int "Bbits" x, is_image x
218	= error ("get_bits: unable to get bits from " ++ print x);
219
220has_bands x = is_image x || has_member "bands" x || is_Arrow x;
221
222get_bands x
223	= x.bands, has_member "bands" x
224	= x.image.bands, is_Arrow x
225	= im_header_int "Bands" x, is_image x
226	= 1, is_real x
227	= len x, is_real_list x
228	= error ("get_bands: unable to get bands from " ++ print x);
229
230has_coding x = has_member "coding" x || is_Arrow x || is_image x;
231
232get_coding x
233	= x.coding, has_member "coding" x
234	= x.image.coding, is_Arrow x
235	= im_header_int "Coding" x, is_image x
236	= Image_coding.NOCODING, is_real x
237	= error ("get_coding: unable to get coding from " ++ print x);
238
239has_xres x = has_member "xres" x || is_Arrow x || is_image x;
240
241get_xres x
242	= x.xres, has_member "xres" x
243	= x.image.xres, is_Arrow x
244	= im_header_int "Xres" x, is_image x
245	= error ("get_xres: unable to get xres from " ++ print x);
246
247has_yres x = has_member "yres" x || is_Arrow x || is_image x;
248
249get_yres x
250	= x.yres, has_member "yres" x
251	= x.image.yres, is_Arrow x
252	= im_header_int "Yres" x, is_image x
253	= error ("get_yres: unable to get yres from " ++ print x);
254
255has_xoffset x = has_member "xoffset" x || is_Arrow x || is_image x;
256
257get_xoffset x
258	= x.xoffset, has_member "xoffset" x
259	= x.image.xoffset, is_Arrow x
260	= im_header_int "Xoffset" x, is_image x
261	= error ("get_xoffset: unable to get xoffset from " ++ print x);
262
263has_yoffset x = has_member "yoffset" x || is_Arrow x || is_image x;
264
265get_yoffset x
266	= x.yoffset, has_member "yoffset" x
267	= x.image.yoffset, is_Arrow x
268	= im_header_int "Yoffset" x, is_image x
269	= error ("get_yoffset: unable to get yoffset from " ++ print x);
270
271has_value = has_member "value";
272
273get_value x = x.value;
274
275has_image x = is_image x || is_Image x || is_Arrow x;
276
277get_image x
278	= x.value, is_Image x
279	= x.image.value, is_Arrow x
280	= x, is_image x
281	= error ("get_image: unable to get image from " ++ print x);
282
283has_number x = is_number x || is_Real x;
284
285get_number x
286	= x.value, is_Real x
287	= x, is_number x
288	= error ("get_number: unable to get number from " ++ print x);
289
290has_real x = is_real x || is_Real x;
291
292get_real x
293	= x.value, is_Real x
294	= x, is_real x
295	= error ("get_real: unable to get real from " ++ print x);
296
297has_width x = has_member "width" x || is_image x;
298
299get_width x
300	= x.width, has_member "width" x
301	= im_header_int "Xsize" x, is_image x
302	= error ("get_width: unable to get width from " ++ print x);
303
304has_height x = has_member "height" x || is_image x;
305
306get_height x
307	= x.height, has_member "height" x
308	= im_header_int "Ysize" x, is_image x
309	= error ("get_height: unable to get height from " ++ print x);
310
311has_left x = has_member "left" x;
312
313get_left x
314	= x.left, has_member "left" x
315	= error ("get_left: unable to get left from " ++ print x);
316
317has_top x = has_member "top" x;
318
319get_top x
320	= x.top, has_member "top" x
321	= error ("get_top: unable to get top from " ++ print x);
322
323// like has/get member,but first in a lst of objects
324has_member_list has objects
325	= filter has objects != [];
326
327// get a member from the first of a list of objects to have it
328get_member_list has get objects
329	= hd members, members != []
330	= error "unable to get property"
331{
332	members = map get (filter has objects);
333}
334
335is_hist x
336	= has_image x && (h == 1 || w == 1 || t == Image_type.HISTOGRAM)
337{
338	im = get_image x;
339	w = get_width im;
340	h = get_height im;
341	t = get_type im;
342}
343