1 /*
2 test_pat_L
3 This frei0r plugin generates test patterns for levels and
4 linearity checking
5 
6 Version 0.1	may 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 /***********************************************************
28 Test patterns: Levels and Linearity
29 
30 This plugin draws a set of test patterns, used for checking of
31 linearity, gamma, contrast, etc.
32 
33 The patterns are drawn into a temporary float array, for two reasons:
34 1. drawing routines are color model independent,
35 2. drawing is done only when a parameter changes.
36 
37 only the function float2color()
38 needs to care about color models, endianness, DV legality etc.
39 
40 *************************************************************/
41 
42 //compile:	gcc -Wall -c -fPIC test_pat_L.c -o test_pat_L.o
43 
44 //link: gcc -lm -shared -o test_pat_L.so test_pat_L.o
45 
46 #include <stdio.h>
47 #include <stdlib.h>
48 #include <assert.h>
49 #include <math.h>
50 
51 #include "frei0r.h"
52 
53 
54 double PI=3.14159265358979;
55 
56 
57 //----------------------------------------------------------
draw_rectangle(float * sl,int w,int h,int x,int y,int wr,int hr,float gray)58 void draw_rectangle(float *sl, int w, int h, int x, int y, int wr, int hr, float gray)
59 {
60 int i,j;
61 int zx,kx,zy,ky;
62 
63 zx=x;  if (zx<0) zx=0;
64 zy=y;  if (zy<0) zy=0;
65 kx=x+wr;  if (kx>w) kx=w;
66 ky=y+hr;  if (ky>h) ky=h;
67 for (i=zy;i<ky;i++)
68 	for (j=zx;j<kx;j++)
69 		sl[w*i+j]=gray;
70 
71 }
72 
73 //----------------------------------------------------------
74 //rectangle with gray gradient
75 //dir:  0=left to right, 1=top to bottom, 2=r to l, 3=b to t
draw_gradient(float * sl,int w,int h,int x,int y,int wr,int hr,float gray1,float gray2,int dir)76 void draw_gradient(float *sl, int w, int h, int x, int y, int wr, int hr, float gray1, float gray2, int dir)
77 {
78 int i,j;
79 int zx,kx,zy,ky;
80 float g,dg;
81 
82 if (wr<=1) return;
83 if (hr<=1) return;
84 zx=x;  if (zx<0) zx=0;
85 zy=y;  if (zy<0) zy=0;
86 kx=x+wr;  if (kx>w) kx=w;
87 ky=y+hr;  if (ky>h) ky=h;
88 switch (dir)
89 	{
90 	case 0:
91 		dg=(gray2-gray1)/(wr-1);
92 		g=gray1;
93 		for (j=zx;j<kx;j++)
94 			{
95 			for (i=zy;i<ky;i++)
96 				sl[w*i+j]=g;
97 			g=g+dg;
98 			}
99 		break;
100 	case 1:
101 		dg=(gray2-gray1)/(hr-1);
102 		g=gray1;
103 		for (i=zy;i<ky;i++)
104 			{
105 			for (j=zx;j<kx;j++)
106 				sl[w*i+j]=g;
107 			g=g+dg;
108 			}
109 		break;
110 	case 2:
111 		dg=(gray1-gray2)/(wr-1);
112 		g=gray2;
113 		for (j=zx;j<kx;j++)
114 			{
115 			for (i=zy;i<ky;i++)
116 				sl[w*i+j]=g;
117 			g=g+dg;
118 			}
119 		break;
120 	case 3:
121 		dg=(gray1-gray2)/(hr-1);
122 		g=gray2;
123 		for (i=zy;i<ky;i++)
124 			{
125 			for (j=zx;j<kx;j++)
126 				sl[w*i+j]=g;
127 			g=g+dg;
128 			}
129 	default:
130 		break;
131 	}
132 
133 }
134 
135 //-----------------------------------------------------------
136 //pocasna za velike kroge.....
draw_circle(float * sl,int w,int h,float ar,int x,int y,int rn,int rz,float gray)137 void draw_circle(float *sl, int w, int h, float ar, int x, int y, int rn, int rz, float gray)
138 {
139 int i,j;
140 int zx,kx,zy,ky;
141 float rr,rmin,rmax;
142 
143 zx=x-rz/ar-1;  if (zx<0) zx=0;
144 zy=y-rz-1;  if (zy<0) zy=0;
145 kx=x+rz/ar+1;  if (kx>w) kx=w;
146 ky=y+rz+1;  if (ky>h) ky=h;
147 rmin=(float)rn;
148 rmax=(float)rz;
149 for (i=zy;i<ky;i++)
150 	for (j=zx;j<kx;j++)
151 		{
152 		rr=sqrtf((i-y)*(i-y)+(j-x)*(j-x)*ar*ar);
153 		if ((rr>=rmin)&&(rr<=rmax)) sl[w*i+j]=gray;
154 		}
155 
156 }
157 
158 //-------------------------------------------------------
159 //draw one numerical digit, 7-segment style
160 //v=size in x direction (in y it is 2*v)
161 //d= number [0...9]
disp7s(float * sl,int w,int h,int x,int y,int v,int d,float gray)162 void disp7s(float *sl, int w, int h, int x, int y, int v, int d, float gray)
163 {
164 char seg[10]={0xEE,0x24,0xBA,0xB6,0x74,0xD6,0xDE,0xA4,0xFE,0xF6};
165 
166 if ((d<0)||(d>9)) return;
167 
168 if ((seg[d]&128)!=0) draw_rectangle(sl,w,h,x,y-2*v,v,1,gray);
169 if ((seg[d]&64)!=0) draw_rectangle(sl,w,h,x,y-2*v,1,v,gray);
170 if ((seg[d]&32)!=0) draw_rectangle(sl,w,h,x+v,y-2*v,1,v,gray);
171 if ((seg[d]&16)!=0) draw_rectangle(sl,w,h,x,y-v,v,1,gray);
172 if ((seg[d]&8)!=0) draw_rectangle(sl,w,h,x,y-v,1,v,gray);
173 if ((seg[d]&4)!=0) draw_rectangle(sl,w,h,x+v,y-v,1,v,gray);
174 if ((seg[d]&2)!=0) draw_rectangle(sl,w,h,x,y,v,1,gray);
175 }
176 
177 //----------------------------------------------------------------
178 //draw a floating point number
179 //v=size
180 //n=number
181 //f=format (as in printf)
dispF(float * sl,int w,int h,int x,int y,int v,float n,char * f,float gray)182 void dispF(float *sl, int w, int h, int x, int y, int v, float n, char *f, float gray)
183 {
184 char str[64];
185 int i;
186 
187 sprintf(str,f,n);
188 i=0;
189 while (str[i]!=0)
190 	{
191 	if (str[i]=='-')
192 		draw_rectangle(sl,w,h,x+i*(v+v/3+1),y-v,v,1,gray);
193 	else
194 		disp7s(sl,w,h,x+i*(v+v/3+1),y,v,str[i]-48,gray);
195 	i++;
196 	}
197 
198 }
199 
200 //----------------------------------------------------------
201 //gray staircase
stopnice(float * sl,int w,int h)202 void stopnice(float *sl, int w, int h)
203 {
204 int j,n;
205 float s;
206 
207 n=8;
208 for (j=0;j<n;j++)
209 	{
210 	s=(float)j/(float)(n-1);
211 	draw_rectangle(sl,w,h, j*w/n, 0, w/n, h, s);
212 	}
213 
214 }
215 
216 //----------------------------------------------------------
217 //gray staircase with contrast check
stopnice_k(float * sl,int w,int h)218 void stopnice_k(float *sl, int w, int h)
219 {
220 int j,n,w1,h1;
221 float s,s1,s2;
222 
223 	n=8;
224 	w1=w/n/3;
225 	h1=w1; if (h1>h/20) h1=h/20;
226 	for (j=0;j<n;j++)
227 		{
228 		s=((float)j+0.5)/(float)n;
229 		draw_rectangle(sl,w,h, j*w/n, 0, w/n, h, s);
230 
231 		s1=s-0.01; if (s1<0.0) s1=0.0;
232 		s2=s+0.01; if (s2>1.0) s2=1.0;
233 		draw_rectangle(sl,w,h, j*w/n+w1,1*h/16, w1,h1, s1);
234 		draw_rectangle(sl,w,h, j*w/n+w1,2*h/16, w1,h1, s2);
235 
236 		s1=s-0.02; if (s1<0.0) s1=0.0;
237 		s2=s+0.02; if (s2>1.0) s2=1.0;
238 		draw_rectangle(sl,w,h, j*w/n+w1,4*h/16, w1,h1, s1);
239 		draw_rectangle(sl,w,h, j*w/n+w1,5*h/16, w1,h1, s2);
240 
241 		s1=s-0.05; if (s1<0.0) s1=0.0;
242 		s2=s+0.05; if (s2>1.0) s2=1.0;
243 		draw_rectangle(sl,w,h, j*w/n+w1,7*h/16, w1,h1, s1);
244 		draw_rectangle(sl,w,h, j*w/n+w1,8*h/16, w1,h1, s2);
245 
246 		s1=s-0.1; if (s1<0.0) s1=0.0;
247 		s2=s+0.1; if (s2>1.0) s2=1.0;
248 		draw_rectangle(sl,w,h, j*w/n+w1,10*h/16, w1,h1, s1);
249 		draw_rectangle(sl,w,h, j*w/n+w1,11*h/16, w1,h1, s2);
250 
251 		s1=s-0.2; if (s1<0.0) s1=0.0;
252 		s2=s+0.2; if (s2>1.0) s2=1.0;
253 		draw_rectangle(sl,w,h, j*w/n+w1,13*h/16, w1,w1, s1);
254 		draw_rectangle(sl,w,h, j*w/n+w1,14*h/16, w1,w1, s2);
255 		}
256 
257 }
258 
259 //-----------------------------------------------------
260 //gray gradient
sivi_klin(float * sl,int w,int h)261 void sivi_klin(float *sl, int w, int h)
262 {
263 draw_rectangle(sl,w,h, 0, 0, w/7, h, 0.5);
264 draw_rectangle(sl,w,h, 6*w/7, 0, w/7, h, 0.5);
265 draw_gradient(sl,w,h, w/8, 0, 3*w/4, h, 0.0, 1.0, 0);
266 }
267 
268 //----------------------------------------------------
269 //256 grays
sivine256(float * sl,int w,int h)270 void sivine256(float *sl, int w, int h)
271 {
272 int i,j,w1,h1;
273 float s;
274 
275 draw_rectangle(sl,w,h, 0, 0, w, h, 0.5);
276 if (w>h) w1=h/20; else w1=w/20;
277 h1=w1-2;
278 for (i=0;i<16;i++)
279 	for (j=0;j<16;j++)
280 		{
281 		s=(float)(16*i+j)/255.0;
282 		draw_rectangle(sl,w,h, (w-h)/2+(j+2)*w1, (i+2)*w1,  h1, h1, s);
283 		}
284 }
285 
286 //------------------------------------------------------
287 //contrast bands
trakovi(float * sl,int w,int h)288 void trakovi(float *sl, int w, int h)
289 {
290 int i,h1;
291 
292 draw_rectangle(sl,w,h, 0, 0, w, h, 0.5);
293 h1=h/64;
294 for (i=0;i<4;i++)
295 	{
296 	draw_gradient(sl,w,h, w/8, (7+2*i)*h1, 3*w/4, h1, 0.0, 0.99, 0);
297 	draw_gradient(sl,w,h, w/8, (8+2*i)*h1, 3*w/4, h1, 0.01, 1.0, 0);
298 	}
299 for (i=0;i<4;i++)
300 	{
301 	draw_gradient(sl,w,h, w/8, (21+2*i)*h1, 3*w/4, h1, 0.0, 0.98, 0);
302 	draw_gradient(sl,w,h, w/8, (22+2*i)*h1, 3*w/4, h1, 0.02, 1.0, 0);
303 	}
304 for (i=0;i<4;i++)
305 	{
306 	draw_gradient(sl,w,h, w/8, (35+2*i)*h1, 3*w/4, h1, 0.0, 0.95, 0);
307 	draw_gradient(sl,w,h, w/8, (36+2*i)*h1, 3*w/4, h1, 0.05, 1.0, 0);
308 	}
309 for (i=0;i<4;i++)
310 	{
311 	draw_gradient(sl,w,h, w/8, (49+2*i)*h1, 3*w/4, h1, 0.0, 0.90, 0);
312 	draw_gradient(sl,w,h, w/8, (50+2*i)*h1, 3*w/4, h1, 0.1, 1.0, 0);
313 	}
314 
315 }
316 
317 //----------------------------------------------------------
gamatest(float * sl,int w,int h)318 void gamatest(float *sl, int w, int h)
319 {
320 int i,s,x,y;
321 float g;
322 
323 for (i=0;i<w*h;i++) sl[i]=0.5;	//gray background
324 
325 //gray patches
326 for (i=0;i<30;i++)
327 	{
328 	s=66+5*i;
329 	g=1.0/(logf((float)s/255.0)/logf(0.5));
330 	x=w/4+3*w/16*(i/10);
331 	y=(i%10+1)*h/12;
332 	draw_rectangle(sl,w,h,x,y,w/8,h/13,(float)s/255.0);
333 	s=(s<140)?240:20;
334 	dispF(sl,w,h, x+w/16-18,y+h/24+4, 6, g, "%4.2f", s/255.0);
335 	}
336 //zebra bars
337 for (i=h/16;i<15*h/16;i++)
338 	{
339 	g=(i%2==0)?1.0:0.0;
340 	draw_rectangle(sl,w,h,3*w/16,i,w/16,1,g);
341 	draw_rectangle(sl,w,h,6*w/16,i,w/16,1,g);
342 	draw_rectangle(sl,w,h,9*w/16,i,w/16,1,g);
343 	draw_rectangle(sl,w,h,12*w/16,i,w/16,1,g);
344 	}
345 //black and white level sidebars
346 draw_rectangle(sl,w,h,w/16,h/12,w/16,10*h/12,0.0);
347 draw_rectangle(sl,w,h,14*w/16,h/12,w/16,10*h/12,1.0);
348 for (i=1;i<11;i++)
349 	{
350 	g=(float)i*0.01;
351 	draw_rectangle(sl,w,h,w/16+w/48,i*h/12+h/36,w/48,h/36,g);
352 	g=(float)(100-i)*0.01;
353 	draw_rectangle(sl,w,h,14*w/16+w/48,i*h/12+h/36,w/48,h/36,g);
354 	}
355 
356 }
357 
358 //--------------------------------------------------
ortikon(float * sl,int w,int h)359 void ortikon(float *sl, int w, int h)
360 {
361 int i;
362 float s1,s2;
363 
364 draw_rectangle(sl,w,h, 0, 0, w, h, 0.6);
365 //mali krogec
366 draw_circle(sl,w,h,1.0, 0.3*w, h/8, 0, 10, 0.95);
367 //crni in beli krog
368 draw_circle(sl,w,h,1.0, 0.6*w, h/8, 0, 20, 0.95);
369 draw_circle(sl,w,h,1.0, 0.6*w+40, h/8, 0, 20, 0.05);
370 //gradient levo
371 draw_gradient(sl,w,h, 0, h/4, 0.3*w, 3*h/4, 0.84, 0.094, 1);
372 //svetel trak
373 draw_rectangle(sl,w,h, 0.13*w, h/4, w/20, 3*h/4, 0.97);
374 //svetel trak z gradientom
375 draw_gradient(sl,w,h, 17*w/40,h/4, w/20,3*h/4, 0.97,0.6, 1);
376 s1=0.9; s2=0.1;
377 for (i=h/4;i<h;i=i+h/4.5)
378 	{
379 	draw_rectangle(sl,w,h,0.6*w,i,h/9,h/9,s2);
380 	draw_rectangle(sl,w,h,0.6*w+h/9,i,h/9,h/9,s1);
381 	draw_rectangle(sl,w,h,0.6*w+2*h/9,i,h/9,h/9,s2);
382 	draw_rectangle(sl,w,h,0.6*w,i+h/9,h/9,h/9,s1);
383 	draw_rectangle(sl,w,h,0.6*w+h/9,i+h/9,h/9,h/9,s2);
384 	draw_rectangle(sl,w,h,0.6*w+2*h/9,i+h/9,h/9,h/9,s1);
385 	}
386 }
387 
388 
389 
390 //-----------------------------------------------------
391 //converts the internal monochrome float image into
392 //Frei0r rgba8888 color
393 //ch selects the channel   0=all  1=R  2=G  3=B
394 //sets alpha to opaque
float2color(float * sl,uint32_t * outframe,int w,int h,int ch)395 void float2color(float *sl, uint32_t* outframe, int w , int h, int ch)
396 {
397 int i,ri,gi,bi;
398 uint32_t p;
399 float r,g,b;
400 
401 switch (ch)
402 	{
403 	case 0:		//all (gray)
404 		for (i=0;i<w*h;i++)
405 			{
406 			p=(uint32_t)(255.0*sl[i]) & 0xFF;
407 			outframe[i] = (p<<16)+(p<<8)+p+0xFF000000;
408 			}
409 		break;
410 	case 1:		//R
411 		for (i=0;i<w*h;i++)
412 			{
413 			p=(uint32_t)(255.0*sl[i]) & 0xFF;
414 			outframe[i] = p+0xFF000000;
415 			}
416 		break;
417 	case 2:		//G
418 		for (i=0;i<w*h;i++)
419 			{
420 			p=(uint32_t)(255.0*sl[i]) & 0xFF;
421 			outframe[i] = (p<<8)+0xFF000000;
422 			}
423 		break;
424 	case 3:		//B
425 		for (i=0;i<w*h;i++)
426 			{
427 			p=(uint32_t)(255.0*sl[i]) & 0xFF;
428 			outframe[i] = (p<<16)+0xFF000000;
429 			}
430 		break;
431 	case 4:		//ccir rec 601  R-Y   on 50 gray
432 		for (i=0;i<w*h;i++)
433 			{
434 			r=sl[i];
435 			b=0.5;
436 			g=(0.5-0.299*r-0.114*b)/0.587;
437 			ri=(int)(255.0*r);
438 			gi=(int)(255.0*g);
439 			bi=(int)(255.0*b);
440 			outframe[i] = (bi<<16)+(gi<<8)+ri+0xFF000000;
441 			}
442 		break;
443 	case 5:		//ccir rec 601  B-Y   on 50% gray
444 		for (i=0;i<w*h;i++)
445 			{
446 			b=sl[i];
447 			r=0.5;
448 			g=(0.5-0.299*r-0.114*b)/0.587;
449 			ri=(int)(255.0*r);
450 			gi=(int)(255.0*g);
451 			bi=(int)(255.0*b);
452 			outframe[i] = (bi<<16)+(gi<<8)+ri+0xFF000000;
453 			}
454 		break;
455 	case 6:		//ccir rec 709  R-Y   on 50 gray
456 		for (i=0;i<w*h;i++)
457 			{
458 			r=sl[i];
459 			b=0.5;
460 			g=(0.5-0.2126*r-0.0722*b)/0.7152;
461 			ri=(int)(255.0*r);
462 			gi=(int)(255.0*g);
463 			bi=(int)(255.0*b);
464 			outframe[i] = (bi<<16)+(gi<<8)+ri+0xFF000000;
465 			}
466 		break;
467 	case 7:		//ccir rec 709  B-Y   on 50% gray
468 		for (i=0;i<w*h;i++)
469 			{
470 			b=sl[i];
471 			r=0.5;
472 			g=(0.5-0.2126*r-0.0722*b)/0.7152;
473 			ri=(int)(255.0*r);
474 			gi=(int)(255.0*g);
475 			bi=(int)(255.0*b);
476 			outframe[i] = (bi<<16)+(gi<<8)+ri+0xFF000000;
477 			}
478 		break;
479 	default:
480 		break;
481 	}
482 
483 }
484 
485 //-----------------------------------------------------
486 //stretch [0...1] to parameter range [min...max] linear
map_value_forward(double v,float min,float max)487 float map_value_forward(double v, float min, float max)
488 {
489 return min+(max-min)*v;
490 }
491 
492 //-----------------------------------------------------
493 //collapse from parameter range [min...max] to [0...1] linear
map_value_backward(float v,float min,float max)494 double map_value_backward(float v, float min, float max)
495 {
496 return (v-min)/(max-min);
497 }
498 
499 //-----------------------------------------------------
500 //stretch [0...1] to parameter range [min...max] logarithmic
501 //min and max must be positive!
map_value_forward_log(double v,float min,float max)502 float map_value_forward_log(double v, float min, float max)
503 {
504 float sr,k;
505 
506 sr=sqrtf(min*max);
507 k=2.0*log(max/sr);
508 return sr*expf(k*(v-0.5));
509 }
510 
511 //-----------------------------------------------------
512 //collapse from parameter range [min...max] to [0...1] logarithmic
513 //min and max must be positive!
map_value_backward_log(float v,float min,float max)514 double map_value_backward_log(float v, float min, float max)
515 {
516 float sr,k;
517 
518 sr=sqrtf(min*max);
519 k=2.0*log(max/sr);
520 return logf(v/sr)/k+0.5;
521 }
522 
523 //**************************************************
524 //obligatory frei0r stuff follows
525 
526 //------------------------------------------------
527 //this structure holds an instance of the test_pat_L plugin
528 typedef struct
529 {
530   unsigned int w;
531   unsigned int h;
532 
533   int type;
534   int chan;
535 
536   float *sl;
537 
538 } tp_inst_t;
539 
540 //----------------------------------------------------
f0r_init()541 int f0r_init()
542 {
543   return 1;
544 }
545 
546 //--------------------------------------------------
f0r_deinit()547 void f0r_deinit()
548 { /* no initialization required */ }
549 
550 //--------------------------------------------------
f0r_get_plugin_info(f0r_plugin_info_t * tp_info)551 void f0r_get_plugin_info(f0r_plugin_info_t* tp_info)
552 {
553   tp_info->name           = "test_pat_L";
554   tp_info->author         = "Marko Cebokli";
555   tp_info->plugin_type    = F0R_PLUGIN_TYPE_SOURCE;
556 //  tp_info->plugin_type    = F0R_PLUGIN_TYPE_FILTER;
557   tp_info->color_model    = F0R_COLOR_MODEL_RGBA8888;
558   tp_info->frei0r_version = FREI0R_MAJOR_VERSION;
559   tp_info->major_version  = 0;
560   tp_info->minor_version  = 1;
561   tp_info->num_params     = 2;
562   tp_info->explanation    = "Generates linearity checking patterns";
563 }
564 
565 //--------------------------------------------------
f0r_get_param_info(f0r_param_info_t * info,int param_index)566 void f0r_get_param_info(f0r_param_info_t* info, int param_index)
567 {
568   switch (param_index)
569     {
570     case 0:
571       info->name        = "Type";
572       info->type        = F0R_PARAM_DOUBLE;
573       info->explanation = "Type of test pattern"; break;
574     case 1:
575       info->name	="Channel";
576       info->type	= F0R_PARAM_DOUBLE;
577       info->explanation = "Into which color channel to draw";
578       break;
579     }
580 }
581 
582 //--------------------------------------------------
f0r_construct(unsigned int width,unsigned int height)583 f0r_instance_t f0r_construct(unsigned int width, unsigned int height)
584 {
585   tp_inst_t* inst = calloc(1, sizeof(*inst));
586   inst->w  = width;
587   inst->h = height;
588 
589   inst->type=0;
590   inst->chan=0;
591 
592   inst->sl=(float*)calloc(width*height,sizeof(float));
593 
594   stopnice(inst->sl, inst->w, inst->h);
595 
596   return (f0r_instance_t)inst;
597 }
598 
599 //--------------------------------------------------
f0r_destruct(f0r_instance_t instance)600 void f0r_destruct(f0r_instance_t instance)
601 {
602   tp_inst_t* inst = (tp_inst_t*)instance;
603 
604   free(inst->sl);
605   free(inst);
606 }
607 
608 //--------------------------------------------------
f0r_set_param_value(f0r_instance_t instance,f0r_param_t param,int param_index)609 void f0r_set_param_value(f0r_instance_t instance, f0r_param_t param, int param_index)
610 {
611   tp_inst_t* inst = (tp_inst_t*)instance;
612 
613   f0r_param_double* p = (f0r_param_double*) param;
614 
615   int chg,tmpi;
616   float tmpf;
617 
618   chg=0;
619   switch (param_index)
620     {
621     case 0:	//type
622       tmpf=*((double*)p);
623       if (tmpf>=1.0)
624         tmpi=(int)tmpf;
625       else
626         tmpi = map_value_forward(tmpf, 0.0, 6.9999);
627       if ((tmpi<0)||(tmpi>6.0)) break;
628       if (inst->type != tmpi) chg=1;
629       inst->type = tmpi;
630       break;
631     case 1:	//channel
632       tmpf=*((double*)p);
633       if (tmpf>=1.0)
634         tmpi=(int)tmpf;
635       else
636         tmpi = map_value_forward(tmpf, 0.0, 7.9999);
637       if ((tmpi<0)||(tmpi>7.0)) break;
638       if (inst->chan != tmpi) chg=1;
639       inst->chan = tmpi;
640     }
641 
642   if (chg==0) return;
643 
644   switch (inst->type)
645     {
646     case 0:		//gray steps
647       stopnice(inst->sl, inst->w, inst->h);
648       break;
649     case 1:		//gray steps with contrast squares
650       stopnice_k(inst->sl, inst->w, inst->h);
651       break;
652     case 2:		//gray gradient
653       sivi_klin(inst->sl, inst->w, inst->h);
654       break;
655     case 3:		//256 gray squares in a 16x16 matrix
656       sivine256(inst->sl, inst->w, inst->h);
657       break;
658     case 4:		//contrast bands
659       trakovi(inst->sl, inst->w, inst->h);
660       break;
661     case 5:		//gama ckecking chart
662       gamatest(inst->sl, inst->w, inst->h);
663       break;
664     case 6:		//for testing orthicon simulator
665       ortikon(inst->sl, inst->w, inst->h);
666       break;
667     default:
668       break;
669     }
670 
671 }
672 
673 //-------------------------------------------------
f0r_get_param_value(f0r_instance_t instance,f0r_param_t param,int param_index)674 void f0r_get_param_value(f0r_instance_t instance, f0r_param_t param, int param_index)
675 {
676   tp_inst_t* inst = (tp_inst_t*)instance;
677 
678   f0r_param_double* p = (f0r_param_double*) param;
679 
680   switch (param_index)
681     {
682     case 0:	//type
683       *p = map_value_backward(inst->type, 0.0, 6.9999);
684       break;
685     case 1:	//channel
686       *p = map_value_backward(inst->chan, 0.0, 7.9999);
687       break;
688     }
689 }
690 
691 //---------------------------------------------------
f0r_update(f0r_instance_t instance,double time,const uint32_t * inframe,uint32_t * outframe)692 void f0r_update(f0r_instance_t instance, double time, const uint32_t* inframe, uint32_t* outframe)
693 {
694 
695   assert(instance);
696   tp_inst_t* inst = (tp_inst_t*)instance;
697 
698   float2color(inst->sl, outframe, inst->w , inst->h, inst->chan);
699 
700 }
701