Good people, here's the code for CodeLabs! Have fun playing with it, I hope you'll make it even cooler!
int Amount1=-20; //[-50,50] Amount per thousand(°/oo)
float [] rd = null;
int Achange=0; //To verify if there is a slider change
void Render(Surface dst, Surface src, Rectangle rect)
{
float Percent= (float)(Amount1 / 500.0f); // Distortion percent
PdnRegion selectionRegion = EnvironmentParameters.GetSelection(src.Bounds);
Rectangle selection = this.EnvironmentParameters.GetSelection(src.Bounds).GetBoundsInt();
int w,h,x0,y0,w2,h2,raymax;
float xd,yd,rdcur,ru;
w = selection.Right - selection.Left;
h = selection.Bottom - selection.Top;
x0=selection.Bottom;y0=selection.Right;
h2=h/2;w2=w/2;
raymax=(int)Math.Sqrt(h2*h2+w2*w2)+1;
if(rd == null){ //first run->alloc and init
rd = new float[raymax];
Init(raymax,Percent,w,h);
}else if(Achange!=Amount1){ //slider change->reinit
Achange=Amount1;
Init(raymax,Percent,w,h);
}
for(int y = rect.Top; y < rect.Bottom; y++){
for (int x = rect.Left+1; x < rect.Right/2+1; x++){ //BUG: if it goes from rect.Left it gives an exception
ru=(float)Math.Sqrt((float)((w2-x)*(w2-x)+(h2-y)*(h2-y)));
rdcur=rd[(int)ru]*(1-ru+(float)Math.Floor(ru)) + rd[(int)ru+1]*(ru-(float)Math.Floor(ru));
rdcur/=ru;
xd=(w2-x)*rdcur;yd=(h2-y)*rdcur;
dst[x,y] = src.GetBilinearSample(w2-xd,h2-yd);
dst[w-x,y] = src.GetBilinearSample(w2+xd,h2-yd);
} //idea of optimisation: the function is symmetrical horizontally and vertically,
//so at the same moment (x,y),(w-x,y),(x,h-y),(w-x,h-y) can be calculated
}
}
void Init(int raymax, float percent, int w, int h)
{ //We precalculate the distortion function in rd
double k,r,inc,ru1,ru0,m;
int l;
// *** Calculate K *** (k is the distortion constant based on the distortion %)
double yd1,yd2,rd2,alfa;
yd1=h/2;
yd2=yd1*(1-percent);
alfa=Math.Atan2(h,w);
rd2=yd2/Math.Sin(alfa);
k=(yd1-yd2)/(rd2*rd2*yd2-yd1*yd1*yd1);
r=0;
inc=0.1;
l=1;rd[0]=0;
while(l ru0=r+r*r*r*k;
r+=0.1;
ru1=r+r*r*r*k;
if(Math.Floor(ru0)!=Math.Floor(ru1)){
m=(ru1-ru0)/inc;
rd[l]=(float)(r-(ru1-Math.Floor(ru1))/m);
l++;
}
}
}