1 /*
2 measure.c
3 
4 measures video pixel and profile values with averaging
5 
6 Version 0.1	jun 2010
7 
8 Copyright (C) 2010  Marko Cebokli    http://lea.hamradio.si/~s57uuu
9 
10 
11  This program is free software; you can redistribute it and/or modify
12  it under the terms of the GNU General Public License as published by
13  the Free Software Foundation; either version 2 of the License, or
14  (at your option) any later version.
15 
16  This program is distributed in the hope that it will be useful,
17  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  GNU General Public License for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with this program; if not, write to the Free Software
23  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 
25 */
26 
27 //measurement functions for direct inclusion in pr0be.c, pr0file.c
28 
29 typedef struct		//float pixel
30 	{
31 	float r;
32 	float g;
33 	float b;
34 	float a;
35 	} float_rgba;
36 
37 typedef struct		//statistics
38 	{
39 	float avg;
40 	float rms;
41 	float min;
42 	float max;
43 	} stat;
44 
45 typedef struct		//profile data and statistics
46 	{
47 	int n;		//number of points used
48 	float r[8192];
49 	float g[8192];
50 	float b[8192];
51 	float a[8192];
52 	float y[8192];
53 	float u[8192];
54 	float v[8192];
55 	stat sr;
56 	stat sg;
57 	stat sb;
58 	stat sa;
59 	stat sy;
60 	stat su;
61 	stat sv;
62 	int xz,xk,yz,yk;	//start and end point
63 	} profdata;
64 
65 //-----------------------------------------------------
66 //luminance/luma statistics of a float_rgba pixel group
67 //color:
68 //0=use rec 601
69 //1=use rec 709
70 //w=width of image (stride)
71 //x,y=position of the center of the group in pixels
72 //sx,sy=size of the group in pixels
meri_y(float_rgba * s,stat * yy,int color,int x,int y,int w,int sx,int sy)73 void meri_y(float_rgba *s, stat *yy, int color, int x, int y, int w, int sx, int sy)
74 {
75 float wr,wg,wb,luma,nf;
76 int xp,yp;
77 float_rgba pix;
78 int i,j;
79 
80 switch (color)
81 	{
82 	case 0:		//CCIR rec 601
83 		wr=0.299;wg=0.587;wb=0.114;
84 		break;
85 	case 1:		//CCIR rec 709
86 		wr=0.2126;wg=0.7152;wb=0.0722;
87 		break;
88 	default:	//unknown color model
89 //		printf("Unknown color model %d\n",color);
90 		break;
91 	}
92 
93 yy->avg=0.0; yy->rms=0.0; yy->min=1.0E9; yy->max=-1.0E9;
94 for (i=0;i<sy;i++)
95 	for (j=0;j<sx;j++)
96 		{
97 		xp=x-sx/2+j;
98 		yp=y-sy/2+i;
99 		if (xp<0) xp=0; if (xp>=w) xp=w-1;
100 		if (yp<0) yp=0; //if (yp>=h) xp=h-1;
101 		pix=s[yp*w+xp];
102 		luma=wr*pix.r+wg*pix.g+wb*pix.b;
103 		if (luma<yy->min) yy->min=luma;
104 		if (luma>yy->max) yy->max=luma;
105 		yy->avg=yy->avg+luma;
106 		yy->rms=yy->rms+luma*luma;
107 		}
108 nf=(float)(sx*sy);
109 yy->avg=yy->avg/nf;
110 yy->rms=sqrtf((yy->rms-nf*yy->avg*yy->avg)/nf);
111 
112 }
113 
114 //-------------------------------------------------------
115 //R,G,B statistics of a float_rgba pixel group
116 //w=width of image (stride)
117 //x,y=position of the center of the group in pixels
118 //sx,sy=size of the group in pixels
meri_rgb(float_rgba * s,stat * r,stat * g,stat * b,int x,int y,int w,int sx,int sy)119 void meri_rgb(float_rgba *s, stat *r, stat *g, stat *b, int x, int y, int w, int sx, int sy)
120 {
121 float nf;
122 int xp,yp;
123 float_rgba pix;
124 int i,j;
125 
126 r->avg=0.0; r->rms=0.0; r->min=1.0E9; r->max=-1.0E9;
127 g->avg=0.0; g->rms=0.0; g->min=1.0E9; g->max=-1.0E9;
128 b->avg=0.0; b->rms=0.0; b->min=1.0E9; b->max=-1.0E9;
129 for (i=0;i<sy;i++)
130 	for (j=0;j<sx;j++)
131 		{
132 		xp=x-sx/2+j;
133 		yp=y-sy/2+i;
134 		if (xp<0) xp=0; if (xp>=w) xp=w-1;
135 		if (yp<0) yp=0; //if (yp>=h) xp=h-1;
136 		pix=s[yp*w+xp];
137 
138 		if (pix.r<r->min) r->min=pix.r;
139 		if (pix.r>r->max) r->max=pix.r;
140 		r->avg=r->avg+pix.r;
141 		r->rms=r->rms+pix.r*pix.r;
142 
143 		if (pix.g<g->min) g->min=pix.g;
144 		if (pix.g>g->max) g->max=pix.g;
145 		g->avg=g->avg+pix.g;
146 		g->rms=g->rms+pix.g*pix.g;
147 
148 		if (pix.b<b->min) b->min=pix.b;
149 		if (pix.b>b->max) b->max=pix.b;
150 		b->avg=b->avg+pix.b;
151 		b->rms=b->rms+pix.b*pix.b;
152 		}
153 nf=(float)(sx*sy);
154 
155 r->avg=r->avg/nf;
156 r->rms=sqrtf((r->rms-nf*r->avg*r->avg)/nf);
157 
158 g->avg=g->avg/nf;
159 g->rms=sqrtf((g->rms-nf*g->avg*g->avg)/nf);
160 
161 b->avg=b->avg/nf;
162 b->rms=sqrtf((b->rms-nf*b->avg*b->avg)/nf);
163 
164 }
165 
166 //--------------------------------------------------------
167 //alpha channel statistics of a float_rgba pixel group
168 //w=width of image (stride)
169 //x,y=position of the center of the group in pixels
170 //sx,sy=size of the group in pixels
meri_a(float_rgba * s,stat * a,int x,int y,int w,int sx,int sy)171 void meri_a(float_rgba *s, stat *a, int x, int y, int w, int sx, int sy)
172 {
173 float nf;
174 int xp,yp;
175 float_rgba pix;
176 int i,j;
177 
178 a->avg=0.0; a->rms=0.0; a->min=1.0E9; a->max=-1.0E9;
179 for (i=0;i<sy;i++)
180 	for (j=0;j<sx;j++)
181 		{
182 		xp=x-sx/2+j;
183 		yp=y-sy/2+i;
184 		if (xp<0) xp=0; if (xp>=w) xp=w-1;
185 		if (yp<0) yp=0; //if (yp>=h) xp=h-1;
186 		pix=s[yp*w+xp];
187 
188 		if (pix.a<a->min) a->min=pix.a;
189 		if (pix.a>a->max) a->max=pix.a;
190 		a->avg=a->avg+pix.a;
191 		a->rms=a->rms+pix.a*pix.a;
192 		}
193 nf=(float)(sx*sy);
194 
195 a->avg=a->avg/nf;
196 a->rms=sqrtf((a->rms-nf*a->avg*a->avg)/nf);
197 
198 }
199 
200 //--------------------------------------------------------
201 //R-Y, B-Y statistics of a float_rgba pixel group
202 //color:
203 //0=use rec 601
204 //1=use rec 709
205 //w=width of image (stride)
206 //x,y=position of the center of the group in pixels
207 //sx,sy=size of the group in pixels
meri_uv(float_rgba * s,stat * u,stat * v,int color,int x,int y,int w,int sx,int sy)208 void meri_uv(float_rgba *s, stat *u, stat *v, int color, int x, int y, int w, int sx, int sy)
209 {
210 float wr,wg,wb,uu,vv,nf;
211 int xp,yp;
212 float_rgba pix;
213 int i,j;
214 
215 switch (color)
216 	{
217 	case 0:		//CCIR rec 601
218 		wr=0.299;wg=0.587;wb=0.114;
219 		break;
220 	case 1:		//CCIR rec 709
221 		wr=0.2126;wg=0.7152;wb=0.0722;
222 		break;
223 	default:	//unknown color model
224 //		printf("Unknown color model %d\n",color);
225 		break;
226 	}
227 
228 u->avg=0.0; u->rms=0.0; u->min=1.0E9; u->max=-1.0E9;
229 v->avg=0.0; v->rms=0.0; v->min=1.0E9; v->max=-1.0E9;
230 for (i=0;i<sy;i++)
231 	for (j=0;j<sx;j++)
232 		{
233 		xp=x-sx/2+j;
234 		yp=y-sy/2+i;
235 		if (xp<0) xp=0; if (xp>=w) xp=w-1;
236 		if (yp<0) yp=0; //if (yp>=h) xp=h-1;
237 		pix=s[yp*w+xp];
238 
239 		//R-Y
240 		uu=(1.0-wr)*pix.r-wg*pix.g-wb*pix.b;
241 		if (uu<u->min) u->min=uu;
242 		if (uu>u->max) u->max=uu;
243 		u->avg=u->avg+uu;
244 		u->rms=u->rms+uu*uu;
245 
246 		//B-Y
247 		vv=(1.0-wb)*pix.b-wr*pix.r-wg*pix.g;
248 		if (vv<v->min) v->min=vv;
249 		if (vv>v->max) v->max=vv;
250 		v->avg=v->avg+vv;
251 		v->rms=v->rms+vv*vv;
252 		}
253 nf=(float)(sx*sy);
254 
255 u->avg=u->avg/nf;
256 u->rms=sqrtf((u->rms-nf*u->avg*u->avg)/nf);
257 
258 v->avg=v->avg/nf;
259 v->rms=sqrtf((v->rms-nf*v->avg*v->avg)/nf);
260 
261 }
262 
263 //------------------------------------------------------------
264 //statistics of a float_rgba pixel profile
265 //color:
266 //0=use rec 601
267 //1=use rec 709
268 //w,h=size of image
269 //xz,yy,xk,yk=end points of the profile line
270 //sir=width of profile in pixels (averaging)
meriprof(float_rgba * s,int w,int h,int xz,int yz,int xk,int yk,int sir,profdata * p)271 void meriprof(float_rgba *s, int w, int h, int xz, int yz, int xk, int yk, int sir, profdata *p)
272 {
273 int x,y,d,i;
274 float_rgba pix;
275 
276 d =  abs(xk-xz)>abs(yk-yz) ? abs(xk-xz) : abs(yk-yz);
277 p->n=d;
278 for (i=0;i<d;i++)
279 	{
280 	x=xz+(float)i/d*(xk-xz);
281 	y=yz+(float)i/d*(yk-yz);
282 	if ((x>=0)&&(x<w)&&(y>=0)&&(y<h))
283 		pix=s[w*y+x];
284 	else
285 		{pix.r=0.0;pix.g=0.0;pix.b=0.0;pix.a=0.0;}
286 	p->r[i]=pix.r;
287 	p->g[i]=pix.g;
288 	p->b[i]=pix.b;
289 	p->a[i]=pix.a;
290 	}
291 
292 }
293 
294 //-----------------------------------------------------
295 //c=0 rec 601      c=1 rec 709
prof_yuv(profdata * p,int color)296 void prof_yuv(profdata *p, int color)
297 {
298 int i;
299 float wr,wg,wb;
300 
301 switch (color)
302 	{
303 	case 0:		//CCIR rec 601
304 		wr=0.299;wg=0.587;wb=0.114;
305 		break;
306 	case 1:		//CCIR rec 709
307 		wr=0.2126;wg=0.7152;wb=0.0722;
308 		break;
309 	default:	//unknown color model
310 //		printf("Unknown color model %d\n",color);
311 		break;
312 	}
313 
314 for (i=0;i<p->n;i++)
315 	{
316 	p->y[i]=wr*p->r[i]+wg*p->g[i]+wb*p->b[i];
317 	p->u[i]=p->r[i]-p->y[i];
318 	p->v[i]=p->b[i]-p->y[i];
319 	}
320 }
321 
322 //---------------------------------------------------------
323 //calculates AVG, RMS, MIN, MAX
324 //for r,g,b,a,y,u,v profiles
prof_stat(profdata * p)325 void prof_stat(profdata *p)
326 {
327 int i;
328 float nf;
329 
330 p->sr.avg=0.0; p->sr.rms=0.0; p->sr.min=1.0E9; p->sr.max=-1.0E9;
331 p->sg.avg=0.0; p->sg.rms=0.0; p->sg.min=1.0E9; p->sg.max=-1.0E9;
332 p->sb.avg=0.0; p->sb.rms=0.0; p->sb.min=1.0E9; p->sb.max=-1.0E9;
333 p->sa.avg=0.0; p->sa.rms=0.0; p->sa.min=1.0E9; p->sa.max=-1.0E9;
334 p->sy.avg=0.0; p->sy.rms=0.0; p->sy.min=1.0E9; p->sy.max=-1.0E9;
335 p->su.avg=0.0; p->su.rms=0.0; p->su.min=1.0E9; p->su.max=-1.0E9;
336 p->sv.avg=0.0; p->sv.rms=0.0; p->sv.min=1.0E9; p->sv.max=-1.0E9;
337 for (i=0;i<p->n;i++)
338 	{
339 	if (p->r[i]<p->sr.min) p->sr.min=p->r[i];
340 	if (p->r[i]>p->sr.max) p->sr.max=p->r[i];
341 	p->sr.avg=p->sr.avg+p->r[i];
342 	p->sr.rms=p->sr.rms+p->r[i]*p->r[i];
343 
344 	if (p->g[i]<p->sg.min) p->sg.min=p->g[i];
345 	if (p->g[i]>p->sg.max) p->sg.max=p->g[i];
346 	p->sg.avg=p->sg.avg+p->g[i];
347 	p->sg.rms=p->sg.rms+p->g[i]*p->g[i];
348 
349 	if (p->b[i]<p->sb.min) p->sb.min=p->b[i];
350 	if (p->b[i]>p->sb.max) p->sb.max=p->b[i];
351 	p->sb.avg=p->sb.avg+p->b[i];
352 	p->sb.rms=p->sb.rms+p->b[i]*p->b[i];
353 
354 	if (p->a[i]<p->sa.min) p->sa.min=p->a[i];
355 	if (p->a[i]>p->sa.max) p->sa.max=p->a[i];
356 	p->sa.avg=p->sa.avg+p->a[i];
357 	p->sa.rms=p->sa.rms+p->a[i]*p->a[i];
358 
359 	if (p->y[i]<p->sy.min) p->sy.min=p->y[i];
360 	if (p->y[i]>p->sy.max) p->sy.max=p->y[i];
361 	p->sy.avg=p->sy.avg+p->y[i];
362 	p->sy.rms=p->sy.rms+p->y[i]*p->y[i];
363 
364 	if (p->u[i]<p->su.min) p->su.min=p->u[i];
365 	if (p->u[i]>p->su.max) p->su.max=p->u[i];
366 	p->su.avg=p->su.avg+p->u[i];
367 	p->su.rms=p->su.rms+p->u[i]*p->u[i];
368 
369 	if (p->v[i]<p->sv.min) p->sv.min=p->v[i];
370 	if (p->v[i]>p->sv.max) p->sv.max=p->v[i];
371 	p->sv.avg=p->sv.avg+p->v[i];
372 	p->sv.rms=p->sv.rms+p->v[i]*p->v[i];
373 	}
374 nf=(float)(p->n);
375 
376 p->sr.avg=p->sr.avg/nf;
377 p->sr.rms=sqrtf((p->sr.rms-nf*p->sr.avg*p->sr.avg)/nf);
378 
379 p->sg.avg=p->sg.avg/nf;
380 p->sg.rms=sqrtf((p->sg.rms-nf*p->sg.avg*p->sg.avg)/nf);
381 
382 p->sb.avg=p->sb.avg/nf;
383 p->sb.rms=sqrtf((p->sb.rms-nf*p->sb.avg*p->sb.avg)/nf);
384 
385 p->sa.avg=p->sa.avg/nf;
386 p->sa.rms=sqrtf((p->sa.rms-nf*p->sa.avg*p->sa.avg)/nf);
387 
388 p->sy.avg=p->sy.avg/nf;
389 p->sy.rms=sqrtf((p->sy.rms-nf*p->sy.avg*p->sy.avg)/nf);
390 
391 p->su.avg=p->su.avg/nf;
392 p->su.rms=sqrtf((p->su.rms-nf*p->su.avg*p->su.avg)/nf);
393 
394 p->sv.avg=p->sv.avg/nf;
395 p->sv.rms=sqrtf((p->sv.rms-nf*p->sv.avg*p->sv.avg)/nf);
396 
397 }
398 
399