1 /* defish0r.c
2
3 * Copyright (C) 2010 Marko Cebokli http://lea.hamradio.si/~s57uuu
4 * This file is a Frei0r plugin.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21
22
23 //compile: gcc -Wall -std=c99 -c -fPIC defish0r.c -o defish0r.o
24
25 //link: gcc -lm -shared -o defish0r.so defish0r.o
26
27 //skaliranje za center=1 se ne dela!!!!
28
29 #include <stdlib.h>
30 #include <stdio.h>
31 #include <math.h>
32
33 #include <frei0r.h>
34
35 #include "interp.h"
36
37
38 double PI=3.14159265358979;
39
40 //---------------------------------------------------------
41 // r = 0...1 izhod = 0...maxr
42 //ta funkcija da popacenje v odvisnosti od r
fish(int n,float r,float f)43 float fish(int n, float r, float f)
44 {
45 float rr,ff;
46
47 //printf("ff=%f\n",ff);
48 switch (n)
49 {
50 case 0: //equidistant
51 ff=f*2.0/PI;
52 rr=tanf(r/ff);
53 break;
54 case 1: //ortographic
55 ff=r/f;
56 if (ff>1.0)
57 rr=-1.0;
58 else
59 rr=tanf(asinf(ff));
60 break;
61 case 2: //equiarea
62 ff=r/2.0/f;
63 if (ff>1.0)
64 rr=-1.0;
65 else
66 rr=tanf(2.0*asinf(r/2.0/f));
67 break;
68 case 3: //stereographic
69 ff=f*2.0/PI;
70 rr=tanf(2.0*atanf(r/2.0/ff));
71 break;
72 default:
73 // printf("Neznana fishitvena funkcija %d\n",n);
74 break;
75 }
76 return rr;
77 }
78
79 //---------------------------------------------------------
80 //ta funkcija da popacenje v odvisnosti od r
81 // r = 0...1 izhod = 0...1
defish(int n,float r,float f,float mr)82 float defish(int n, float r, float f, float mr)
83 {
84 float rr;
85
86 switch (n)
87 {
88 case 0: //equidistant
89 rr=f*2.0/PI*atanf(r*mr);
90 break;
91 case 1: //ortographic
92 rr=f*sinf(atanf(r*mr));
93 break;
94 case 2: //equiarea
95 rr=2.0*f*sinf(atanf(r*mr)/2.0);
96 break;
97 case 3: //stereographic
98 rr=f*4.0/PI*tanf(atanf(r*mr)/2.0);
99 break;
100 default:
101 // printf("Neznana fishitvena funkcija %d\n",n);
102 break;
103 }
104 return rr;
105 }
106
107 #if defined(_MSC_VER)
108 #define hypotf _hypotf
109 #endif
110
111 //----------------------------------------------------------------
112 //nafila array map s polozaji pikslov
113 //locena funkcija, da jo poklicem samo enkrat na zacetku,
114 //array map[] potem uporablja funkcija remap()
115 //tako ni treba za vsak frame znova racunat teh sinusov itd...
116 //wi,hi,wo ho = input.output image width/height
117 //n = 0..3 function select
118 //f = focal ratio (amount of distortion)
119 //scal = scaling factor
120 //pari, paro = pixel aspect ratio (input / output)
121 //dx, dy offset on input (for non-cosited chroma subsampling)
fishmap(int wi,int hi,int wo,int ho,int n,float f,float scal,float pari,float paro,float dx,float dy,float * map)122 void fishmap(int wi, int hi, int wo, int ho, int n, float f, float scal, float pari, float paro, float dx, float dy, float *map)
123 {
124 float rmax,maxr,r,kot,x,y,imax;
125 int i,j,ww,wi2,hi2,wo2,ho2;
126 float ii,jj,sc;
127
128 rmax=hypotf(ho/2.0,wo/2.0*paro);
129 maxr=fish(n,1.0,f);
130 imax=hypotf(hi/2.0,wi/2.0*pari);
131 sc=imax/maxr;
132
133 //printf("Fishmap: F=%5.2f Rmax= %7.2f Maxr=%6.2f sc=%6.2f scal=%6.2f\n",f,rmax,maxr,sc,scal);
134
135 wi2=wi/2; hi2=hi/2; wo2=wo/2; ho2=ho/2;
136 for (i=0;i<ho;i++)
137 {
138 ii=i-ho2;
139 for (j=0;j<wo;j++)
140 {
141 jj=(j-wo2)*paro;
142 r=hypotf(ii,jj);
143 kot=atan2f(ii,jj);
144 r=fish(n,r/rmax*scal,f)*sc;
145 ww=2*(wo*i+j);
146 if (r<0.0)
147 {
148 map[ww]=-1;
149 map[ww+1]=-1;
150 }
151 else
152 {
153 x=wi2+r*cosf(kot)/pari;
154 y=hi2+r*sinf(kot);
155 if ((x>0)&(x<(wi-1))&(y>0)&(y<(hi-1)))
156 {
157 map[ww]=x+dx;
158 map[ww+1]=y+dy;
159 }
160 else
161 {
162 map[ww]=-1;
163 map[ww+1]=-1;
164 }
165 }
166 }
167 }
168
169 }
170
171 //----------------------------------------------------------------
172 //nafila array map s polozaji pikslov
173 //locena funkcija, da jo poklicem samo enkrat na zacetku,
174 //array map[] potem uporablja funkcija remap()
175 //tako ni treba za vsak frame znova racunat teh sinusov itd...
176 //wi,hi,wo ho = input.output image width/height
177 //n = 0..3 function select
178 //f = focal ratio (amount of distortion)
179 //scal = scaling factor
180 //pari,paro = pixel aspect ratio (input / output)
181 //dx, dy offset on input (for non-cosited chroma subsampling)
defishmap(int wi,int hi,int wo,int ho,int n,float f,float scal,float pari,float paro,float dx,float dy,float * map)182 void defishmap(int wi, int hi, int wo, int ho, int n, float f, float scal, float pari, float paro, float dx, float dy, float *map)
183 {
184 float rmax,maxr,r,kot,x,y,imax;
185 int i,j,ww,wi2,hi2,wo2,ho2;
186 float ii,jj,sc;
187
188 rmax=hypotf(ho/2.0,wo/2.0*paro);
189 maxr=fish(n,1.0,f);
190 imax=hypotf(hi/2.0,wi/2.0*pari);
191 sc=imax/maxr;
192
193 //printf("Defishmap: F=%f rmax= %f Maxr=%f sc=%6.2f scal=%6.2f\n",f,rmax,maxr,sc,scal);
194
195 wi2=wi/2; hi2=hi/2; wo2=wo/2; ho2=ho/2;
196 for (i=0;i<ho;i++)
197 {
198 ii=i-ho2;
199 for (j=0;j<wo;j++)
200 {
201 jj=(j-wo2)*paro; //aspect....
202 r=hypotf(ii,jj)/scal;
203 kot=atan2f(ii,jj);
204 ww=2*(wo*i+j);
205 r=defish(n,r/sc,f,1.0)*rmax;
206 if (r<0.0)
207 {
208 map[ww]=-1;
209 map[ww+1]=-1;
210 }
211 else
212 {
213 x=wi2+r*cosf(kot)/pari;
214 y=hi2+r*sinf(kot);
215 if ((x>0)&(x<(wi-1))&(y>0)&(y<(hi-1)))
216 {
217 map[ww]=x;
218 map[ww+1]=y;
219 }
220 else
221 {
222 map[ww]=-1;
223 map[ww+1]=-1;
224 }
225 }
226 }
227 }
228 }
229
230 //=====================================================
231 //kao instanca frei0r
232 //w,h: image dimensions in pixels
233 //f: focal ratio
234 //dir: 0=defish 1=fish
235 //type: 0..3 equidistant, ortographic, equiarea, stereographic
236 //scal: 0..3 image to fill, keep center scale, image to fit, manu
237 //intp: 0..6 type of interpolator
238 //aspt: 0..4 aspect type square, PAL, NTSC, HDV, manual
239 //par: pixel aspect ratio
240 typedef struct
241 {
242 int w;
243 int h;
244 float f;
245 int dir;
246 int type;
247 int scal;
248 int intp;
249 float mscale;
250 int aspt;
251 float mpar;
252 float par;
253 float *map;
254 interpp interpol;
255 } param;
256
257
258
259 //-------------------------------------------------------
set_intp(param p)260 interpp set_intp(param p)
261 {
262 switch (p.intp) //katero interpolacijo bo uporabil
263 {
264 // case -1:return interpNNpr_b; //nearest neighbor+print
265 case 0: return interpNN_b32; //nearest neighbor
266 case 1: return interpBL_b32; //bilinear
267 case 2: return interpBC_b32; //bicubic smooth
268 case 3: return interpBC2_b32; //bicibic sharp
269 case 4: return interpSP4_b32; //spline 4x4
270 case 5: return interpSP6_b32; //spline 6x6
271 case 6: return interpSC16_b32; //lanczos 8x8
272 default: return NULL;
273 }
274 }
275
276 //--------------------------------------------------------
make_map(param p)277 void make_map(param p)
278 {
279 float rmax,maxr,imax,fscal,dscal;
280
281 rmax=hypotf(p.h/2.0,p.w/2.0*p.par);
282 maxr=fish(p.type,1.0,p.f);
283 imax=hypotf(p.h/2.0,p.w/2.0*p.par);
284
285 if (p.dir==0) //defish
286 {
287 switch (p.scal)
288 {
289 case 0: //fill
290 dscal=maxr*p.h/2.0/rmax/fish(p.type,p.h/2.0/rmax,p.f);
291 break;
292 case 1: //keep
293 dscal=maxr*p.f;
294 if ((p.type==0)||(p.type==3)) dscal=dscal/PI*2.0;break;
295 case 2: //fit
296 dscal=1.0; break;
297 case 3: //manual
298 dscal=p.mscale; break;
299 }
300 defishmap(p.w ,p.h ,p.w ,p.h, p.type, p.f, dscal, p.par, p.par, 0.0, 0.0, p.map);
301 }
302 else //fish
303 {
304 switch (p.scal)
305 {
306 case 0: //fill
307 fscal=1.0;break;
308 case 1: //keep
309 fscal=maxr*p.f;
310 if ((p.type==0)||(p.type==3)) fscal=fscal/PI*2.0;
311 break;
312 case 2: //fit
313 fscal=2.0*defish(p.type,p.h/2.0*maxr/imax,p.f,1.0)/p.h*rmax;
314 break;
315 case 3: //manual
316 fscal=1.0/p.mscale; break;
317 }
318 fishmap(p.w, p.h, p.w ,p.h, p.type, p.f, fscal, p.par, p.par, 0.0, 0.0, p.map);
319 }
320
321 }
322
323 //*********************************************************
324 // OBVEZNE FREI0R FUNKCIJE
325
326 //-----------------------------------------------
f0r_init()327 int f0r_init()
328 {
329 return 1;
330 }
331
332 //------------------------------------------------
f0r_deinit()333 void f0r_deinit()
334 {
335 }
336
337 //-----------------------------------------------
f0r_get_plugin_info(f0r_plugin_info_t * info)338 void f0r_get_plugin_info(f0r_plugin_info_t* info)
339 {
340
341 info->name="Defish0r";
342 info->author="Marko Cebokli";
343 info->plugin_type=F0R_PLUGIN_TYPE_FILTER;
344 info->color_model=F0R_COLOR_MODEL_RGBA8888;
345 info->frei0r_version=FREI0R_MAJOR_VERSION;
346 info->major_version=0;
347 info->minor_version=3;
348 info->num_params=8;
349 info->explanation="Non rectilinear lens mappings";
350 }
351
352 //--------------------------------------------------
f0r_get_param_info(f0r_param_info_t * info,int param_index)353 void f0r_get_param_info(f0r_param_info_t* info, int param_index)
354 {
355 switch(param_index)
356 {
357 case 0:
358 info->name = "Amount";
359 info->type = F0R_PARAM_DOUBLE;
360 info->explanation = "Focal Ratio";
361 break;
362 case 1:
363 info->name = "DeFish";
364 info->type = F0R_PARAM_BOOL;
365 info->explanation = "Fish or Defish";
366 break;
367 case 2:
368 info->name = "Type";
369 info->type = F0R_PARAM_DOUBLE;
370 info->explanation = "Mapping function";
371 break;
372 case 3:
373 info->name = "Scaling";
374 info->type = F0R_PARAM_DOUBLE;
375 info->explanation = "Scaling method";
376 break;
377 case 4:
378 info->name = "Manual Scale";
379 info->type = F0R_PARAM_DOUBLE;
380 info->explanation = "Manual Scale";
381 break;
382 case 5:
383 info->name = "Interpolator";
384 info->type = F0R_PARAM_DOUBLE;
385 info->explanation = "Quality of interpolation";
386 break;
387 case 6:
388 info->name = "Aspect type";
389 info->type = F0R_PARAM_DOUBLE;
390 info->explanation = "Pixel aspect ratio presets";
391 break;
392 case 7:
393 info->name = "Manual Aspect";
394 info->type = F0R_PARAM_DOUBLE;
395 info->explanation = "Manual Pixel Aspect ratio";
396 break;
397 }
398
399 }
400
401 //--------------------------------------------------------
402 //kao constructor za frei0r
f0r_construct(unsigned int width,unsigned int height)403 f0r_instance_t f0r_construct(unsigned int width, unsigned int height)
404 {
405 param *p;
406
407 p=(param*)calloc(1, sizeof(param));
408
409 p->w=width;
410 p->h=height;
411 p->f=20.0; //defaults (not used??)
412 p->dir=1;
413 p->type=2;
414 p->scal=2;
415 p->intp=1;
416 p->mscale=1.0;
417 p->aspt=0; //square pixels
418 p->par=1.0; //square pixels
419 p->mpar=1.0;
420
421 p->map=(float*)calloc(1, sizeof(float)*(p->w*p->h*2+2));
422 p->interpol=set_intp(*p);
423
424 make_map(*p);
425
426 //printf("Construct, w=%d h=%d\n",width,height);
427
428 return (f0r_instance_t)p;
429 }
430
431 //---------------------------------------------------
f0r_destruct(f0r_instance_t instance)432 void f0r_destruct(f0r_instance_t instance)
433 {
434 param *p;
435 p=(param*)instance;
436
437 free(p->map);
438 free(instance);
439 }
440
441 //----------------------------------------------------
442 //not used in frei0r plugin
change_param(param * p,int w,int h,float f,int dir,int type,int scal,int intp)443 void change_param(param *p, int w, int h, float f, int dir, int type, int scal, int intp)
444 {
445 p->f=f;
446 p->dir=dir;
447 p->type=type;
448 p->scal=scal;
449 p->intp=intp;
450
451 if ((w!=p->w)||(h!=p->h))
452 {
453 free(p->map);
454 p->map=(float*)calloc(1, sizeof(float)*(w*h*2+2));
455 p->w=w;
456 p->h=h;
457 }
458
459 p->interpol=set_intp(*p);
460 make_map(*p);
461 }
462
463 //-----------------------------------------------------
print_param(param p)464 void print_param(param p)
465 //not used in frei0r plugin
466 {
467 printf("Param: w=%d h=%d f=%f dir=%d",p.w, p.h, p.f, p.dir);
468 printf(" type=%d scal=%d intp=%d",p.type, p.scal, p.intp);
469 printf(" mscale=%f par=%f mpar=%f\n",p.mscale, p.par, p.mpar);
470 }
471
472 //------------------------------------------------------
473 //computes x to the power p
474 //only for positive x
pwr(float x,float p)475 float pwr(float x, float p)
476 {
477 if (x<=0) return 0;
478 //printf("exp(%f)=%f\n",x,expf(p*logf(x)));
479 return expf(p*logf(x));
480 }
481
482 //-----------------------------------------------------
483 //stretch [0...1] to parameter range [min...max] logarithmic
484 //min and max must be positive!
map_value_forward_log(double v,float min,float max)485 float map_value_forward_log(double v, float min, float max)
486 {
487 float sr,k;
488
489 sr=sqrtf(min*max);
490 k=2.0*log(max/sr);
491 return sr*expf(k*(v-0.5));
492 }
493
494 //-----------------------------------------------------
495 //collapse from parameter range [min...max] to [0...1] logarithmic
496 //min and max must be positive!
map_value_backward_log(float v,float min,float max)497 double map_value_backward_log(float v, float min, float max)
498 {
499 float sr,k;
500
501 sr=sqrtf(min*max);
502 k=2.0*log(max/sr);
503 return logf(v/sr)/k+0.5;
504 }
505
506 //-----------------------------------------------------
507 //stretch [0...1] to parameter range [min...max] linear
map_value_forward(double v,float min,float max)508 float map_value_forward(double v, float min, float max)
509 {
510 return min+(max-min)*v;
511 }
512
513 //-----------------------------------------------------
514 //collapse from parameter range [min...max] to [0...1] linear
map_value_backward(float v,float min,float max)515 double map_value_backward(float v, float min, float max)
516 {
517 return (v-min)/(max-min);
518 }
519
520 //-----------------------------------------------------
521 //smisele vrednosti za parameter f: (za fish)
522 // tip 0: (0.3) 1.001...10; tip 1: 1.000...10
523 // tip 2: (0.5) 0.75...10.0 tip 3: (0.1) 0.78...10
524 //za defish:
525 // tip 0: 0.1...10 tip 1: 1.0...10
526 // tip 2: 0.5...10 tip 3: (0.1) 0.5...10
f0r_set_param_value(f0r_instance_t instance,f0r_param_t parm,int param_index)527 void f0r_set_param_value(f0r_instance_t instance, f0r_param_t parm, int param_index)
528 {
529 param *p;
530 int chg,tmpi;
531 float tmpf;
532
533 p=(param*)instance;
534
535 //printf("set parm: index=%d, value=%f\n",param_index,*(float*)parm);
536 chg=0;
537 switch(param_index)
538 {
539 case 0: //f
540 tmpf=pwr(*((double*)parm),1.0/5.0);
541 // tmpf=map_value_forward(*((double*)parm), 10.0, 0.1);
542 tmpf=map_value_forward(tmpf, 20.0, 0.1);
543 if (p->f != tmpf) chg=1;
544 p->f=tmpf;
545 break;
546 case 1: //fish
547 tmpi=map_value_forward(*((double*)parm), 1.0, 0.0);//BOOL!!
548 if (p->dir != tmpi) chg=1;
549 p->dir=tmpi;
550 break;
551 case 2: //type
552 tmpi=map_value_forward(*((double*)parm), 0.0, 3.999);
553 if (p->type != tmpi) chg=1;
554 p->type=tmpi;
555 break;
556 case 3: //scaling
557 tmpi=map_value_forward(*((double*)parm), 0.0, 3.999);
558 if (p->scal != tmpi) chg=1;
559 p->scal=tmpi;
560 break;
561 case 4: //manual scale
562 tmpf=map_value_forward_log(*((double*)parm), 0.01, 100.0);
563 if (p->mscale != tmpf) chg=1;
564 p->mscale=tmpf;
565 break;
566 case 5: //interpolator
567 tmpi=map_value_forward(*((double*)parm), 0.0, 6.999);
568 if (p->intp != tmpi) chg=1;
569 p->intp=tmpi;
570 break;
571 case 6: //aspect type
572 tmpi=map_value_forward(*((double*)parm), 0.0, 4.999);
573 if (p->aspt != tmpi) chg=1;
574 p->aspt=tmpi;
575 break;
576 case 7: //manual aspect
577 tmpf=map_value_forward_log(*((double*)parm), 0.5, 2.0);
578 if (p->mpar != tmpf) chg=1;
579 p->mpar=tmpf;
580 break;
581 }
582
583 if (chg!=0)
584 {
585 switch (p->aspt) //pixel aspect ratio
586 {
587 case 0: p->par=1.000;break; //square pixels
588 case 1: p->par=1.067;break; //PAL DV
589 case 2: p->par=0.889;break; //NTSC DV
590 case 3: p->par=1.333;break; //HDV
591 case 4: p->par=p->mpar;break; //manual
592 }
593 p->interpol=set_intp(*p);
594 make_map(*p);
595 }
596
597 //print_param(*p);
598 }
599
600 //--------------------------------------------------
f0r_get_param_value(f0r_instance_t instance,f0r_param_t parm,int param_index)601 void f0r_get_param_value(f0r_instance_t instance, f0r_param_t parm, int param_index)
602 {
603 param *p;
604 float tmpf;
605
606 p=(param*)instance;
607
608 switch(param_index)
609 {
610 case 0: //f
611 // *((double*)parm)=map_value_backward(p->f, 10.0, 0.1);
612 tmpf=map_value_backward(p->f, 20.0, 0.1);
613 *((double*)parm)=pwr(tmpf, 5.0);
614 break;
615 case 1: //fish
616 *((double*)parm)=map_value_backward(p->dir, 1.0, 0.0); //BOOL!!
617 break;
618 case 2: //type
619 *((double*)parm)=map_value_backward(p->type, 0.0, 3.0);
620 break;
621 case 3: //scaling
622 *((double*)parm)=map_value_backward(p->scal, 0.0, 3.0);
623 break;
624 case 4: //manual scale
625 *((double*)parm)=map_value_backward_log(p->mscale, 0.01, 100.0);
626 break;
627 case 5: //interpolator
628 *((double*)parm)=map_value_backward(p->intp, 0.0, 6.0);
629 break;
630 case 6: //aspect type
631 *((double*)parm)=map_value_backward(p->aspt, 0.0, 4.999);
632 break;
633 case 7: //manual aspect
634 *((double*)parm)=map_value_backward_log(p->mpar, 0.5, 2.0);
635 break;
636 }
637 }
638
639 //-------------------------------------------------
f0r_update(f0r_instance_t instance,double time,const uint32_t * inframe,uint32_t * outframe)640 void f0r_update(f0r_instance_t instance, double time, const uint32_t* inframe, uint32_t* outframe)
641 {
642 param *p;
643
644 p=(param*)instance;
645
646 remap32(p->w, p->h, p->w, p->h, (unsigned char*) inframe, (unsigned char*) outframe, p->map, 0, p->interpol);
647
648 }
649