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