1 /* im_measure.c
2  *
3  * Modified:
4  * 19/8/94 JC
5  *	- now uses doubles for addressing
6  *	- could miss by up to h pixels previously!
7  *	- ANSIfied
8  *	- now issues warning if any deviations are greater than 20% of the
9  *	  mean
10  * 31/10/95 JC
11  *	- more careful about warning for averages <0, or averages near zero
12  *	- can get these cases with im_measure() of IM_TYPE_LAB images
13  * 28/10/02 JC
14  *	- number bands from zero in error messages
15  * 7/7/04
16  *	- works on labq
17  * 18/8/08
18  * 	- add gtkdoc comments
19  * 	- remove deprecated im_extract()
20  * 30/11/09
21  * 	- changes for im_extract() broke averaging
22  * 9/11/11
23  * 	- moved to deprecated, the new VipsMeasure does not have the
24  * 	  select-patches thing, so we have to keep this around
25  */
26 
27 /*
28 
29     This file is part of VIPS.
30 
31     VIPS is free software; you can redistribute it and/or modify
32     it under the terms of the GNU Lesser General Public License as published by
33     the Free Software Foundation; either version 2 of the License, or
34     (at your option) any later version.
35 
36     This program is distributed in the hope that it will be useful,
37     but WITHOUT ANY WARRANTY; without even the implied warranty of
38     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
39     GNU Lesser General Public License for more details.
40 
41     You should have received a copy of the GNU Lesser General Public License
42     along with this program; if not, write to the Free Software
43     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
44     02110-1301  USA
45 
46  */
47 
48 /*
49 
50     These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
51 
52  */
53 
54 #ifdef HAVE_CONFIG_H
55 #include <config.h>
56 #endif /*HAVE_CONFIG_H*/
57 #include <vips/intl.h>
58 
59 #include <stdio.h>
60 #include <math.h>
61 
62 #include <vips/vips.h>
63 #include <vips/vips7compat.h>
64 
65 /* Measure into array.
66  */
67 static int
measure_patches(IMAGE * im,double * coeff,int left,int top,int width,int height,int u,int v,int * sel,int nsel)68 measure_patches( IMAGE *im, double *coeff,
69 	int left, int top, int width, int height,
70 	int u, int v, int *sel, int nsel )
71 {
72 	IMAGE *tmp;
73 	int patch;
74 	int i, j;
75 	int m, n;
76 	double avg, dev;
77 	int x, y, w, h;
78 
79 	/* How large are the patches we are to measure?
80 	 */
81 	double pw = (double) width / (double) u;
82 	double ph = (double) height / (double) v;
83 
84 	/* Set up sub to be the size we need for a patch.
85 	 */
86 	w = (pw + 1) / 2;
87 	h = (ph + 1) / 2;
88 
89 	/* Loop through sel, picking out areas to measure.
90 	 */
91 	for( j = 0, patch = 0; patch < nsel; patch++ ) {
92 		/* Sanity check. Is the patch number sensible?
93 		 */
94 		if( sel[patch] <= 0 || sel[patch] > u * v ) {
95 			im_error( "im_measure",
96 				_( "patch %d is out of range" ),
97 				sel[patch] );
98 			return( 1 );
99 		}
100 
101 		/* Patch coordinates.
102 		 */
103 		m = (sel[patch] - 1) % u;
104 		n = (sel[patch] - 1) / u;
105 
106 		/* Move sub to correct position.
107 		 */
108 		x = left + m * pw + (pw + 2) / 4;
109 		y = top + n * ph + (ph + 2) / 4;
110 
111 		/* Loop through bands.
112 		 */
113 		for( i = 0; i < im->Bands; i++, j++ ) {
114 			/* Make temp buffer to extract to.
115 			 */
116 			if( !(tmp = im_open( "patch", "t" )) )
117 				return( -1 );
118 
119 			/* Extract and measure.
120 			 */
121 			if( im_extract_areabands( im, tmp, x, y, w, h, i, 1 ) ||
122 				im_avg( tmp, &avg ) ||
123 				im_deviate( tmp, &dev ) ) {
124 				im_close( tmp );
125 				return( -1 );
126 			}
127 			im_close( tmp );
128 
129 			/* Is the deviation large compared with the average?
130 			 * This could be a clue that our parameters have
131 			 * caused us to miss the patch. Look out for averages
132 			 * <0, or averages near zero (can get these if use
133 			 * im_measure() on IM_TYPE_LAB images).
134 			 */
135 			if( dev * 5 > fabs( avg ) && fabs( avg ) > 3 )
136 				im_warn( "im_measure",
137 					_( "patch %d, band %d: "
138 						"avg = %g, sdev = %g" ),
139 					patch, i, avg, dev );
140 
141 			/* Save results.
142 			 */
143 			coeff[j] = avg;
144 		}
145 	}
146 
147 	return( 0 );
148 }
149 
150 static DOUBLEMASK *
internal_im_measure_area(IMAGE * im,int left,int top,int width,int height,int u,int v,int * sel,int nsel,const char * name)151 internal_im_measure_area( IMAGE *im,
152 	int left, int top, int width, int height,
153 	int u, int v,
154 	int *sel, int nsel, const char *name )
155 {
156 	DOUBLEMASK *mask;
157 
158 	if( im_check_uncoded( "im_measure", im ) ||
159 		im_check_noncomplex( "im_measure", im ) )
160 		return( NULL );
161 
162 	/* Default to all patches if sel == NULL.
163 	 */
164 	if( sel == NULL ) {
165 		int i;
166 
167 		nsel = u * v;
168 		if( !(sel = IM_ARRAY( im, nsel, int )) )
169 			return( NULL );
170 		for( i = 0; i < nsel; i++ )
171 			sel[i] = i + 1;
172 	}
173 
174 	/* What size mask do we need?
175 	 */
176 	if( !(mask = im_create_dmask( name, im->Bands, nsel )) )
177 		return( NULL );
178 
179 	/* Perform measure and return.
180 	 */
181 	if( measure_patches( im, mask->coeff, left, top, width, height,
182 		u, v, sel, nsel ) ) {
183 		im_free_dmask( mask );
184 		return( NULL );
185 	}
186 
187 	return( mask );
188 }
189 
190 DOUBLEMASK *
im_measure_area(IMAGE * im,int left,int top,int width,int height,int u,int v,int * sel,int nsel,const char * name)191 im_measure_area( IMAGE *im,
192 	int left, int top, int width, int height,
193 	int u, int v,
194 	int *sel, int nsel, const char *name )
195 {
196 	DOUBLEMASK *mask;
197 	VipsImage *t;
198 
199 	/* The old im_measure() worked on labq.
200 	 */
201 	if( im->Coding == IM_CODING_LABQ ) {
202 		if( !(t = im_open( "measure-temp", "p" )) )
203 			return( NULL );
204 		if( im_LabQ2Lab( im, t ) ||
205 			!(mask = im_measure_area( t,
206 				left, top, width, height,
207 				u, v,
208 				sel, nsel, name )) ) {
209 			g_object_unref( t );
210 			return( NULL );
211 		}
212 		g_object_unref( t );
213 
214 		return( mask );
215 	}
216 
217 	if( sel )
218 		return( internal_im_measure_area( im,
219 			left, top, width, height, u, v, sel, nsel, name ) );
220 	else {
221 		if( vips_measure( im, &t, u, v,
222 			"left", left,
223 			"top", top,
224 			"width", width,
225 			"height", height,
226 			NULL ) )
227 			return( NULL );
228 		if( !(mask = im_vips2mask( t, name )) ) {
229 			g_object_unref( t );
230 			return( NULL );
231 		}
232 		g_object_unref( t );
233 
234 		return( mask );
235 	}
236 }
237