/*********************************************************************************** * * class: floatImage * author: Mike Chantler * purpose: Represents an image as a nxm set of floats for each colour channel * Mods: 06/12/2008 MJC Created * * CONSTRUCTOR * - floatImage() * * METHODS * - betaNoise(n:int=512, beta:Number=2.0):void * - displayOnCanvas(c:Canvas,xRepeats:Number=1, yRepeats:Number=1):void * - fold():void * - illuminate(tau:int=0, sigma:int=20, htScaling:Number=1000):void * - loadInput(inIm:floatImage):void * - loadTestImage():void * - save2file():void{ * - setSize(width:int, height:int, nChannels:int=1):void * ***********************************************************************************/ package { import flash.display.Bitmap; import flash.display.BitmapData; import mx.controls.Image; import mx.containers.Canvas; public class FloatImage { //Monochrome floating point image [Embed(source='../assets/Image15g.jpg')] private var imClass:Class; //Used for testing public var height:int, width:int; public var nChannels:int=1; //e.g. RGB image has 3 channels one for each colour private var imBitmap:Bitmap; //Flash sprite (can be displayed but no pixel access private var imBD:BitmapData; //24 or 32 bit image representation, allows acess vis getPixel() and setPixel() public var nPix:Array; //Holds image as 1D+2D number array(extra dim for colour channels) public var unitNormal:FloatImage; //Holds surface normals // CONSTRUCTOR public function FloatImage(width:int=0, height:int=0, nChannels:int=1){ if(width>0) setSize(width, height, nChannels); } // PUBLIC METHODS public function betaNoise(n:int=512, beta:Number=2.0):void{ // Method to generate 1/f Beta noise in an nxn monochrome(single channel) floatImage var ndim:int=2; //2D image var dat:Array= new Array(2*n*n); //Used to hold the whole 2D DFT var obuf:Array=new Array(n), obufI:Array=new Array(n); var nn:Array=new Array(ndim+1); setSize(n, n, 1); //Set up space for spatial domain image //Declare real, imaginary and magnitue frequency domain images //Note unswapped: so (aReal[0][0], aImag[0][0]) = d.c. var aReal:Array=new Array(n), aImag:Array=new Array(n), aMag:Array=new Array(n); for (i=0; imaxRad)maxRad=rad; aReal[i][j]=radcos; aImag[i][j]=radsin; //Now do complex conjugate if (i==0) i0=0; else i0=n-i; if (j==0) j0=0; else j0=n-j; aReal[i0][j0]= radcos; aImag[i0][j0]= -radsin; //aMag [i0][j0]= rad; } } aImag[n2][0] = aImag[0][n2] = aImag[n2][n2] = 0.0; for (i=1; i<=n2-1; i++) { for (j=1; j<=n2-1; j++) { phase = 2.0*Math.PI*Math.random() - Math.PI; p=Math.sqrt(i*i + j*j); if (p <= 1.0) p=1.0; rad = Math.pow(p,-beta); radcos = rad * Math.cos(phase); radsin = rad * Math.sin(phase); aReal[i][n-j]=radcos; aImag[i][n-j]=radsin; //aMag[i][n-j]=rad; //And complex conjugate: aReal[n-i][j]= radcos; aImag[n-i][j]= -radsin; //aMag[n-i][j]=rad; } } // Now inverse FFT: first reshuffle data into complex 1D array 'dat[]' // Real data @ ll = 1, 3, 5, ..... 2*n*n -1 // Imag data @ ll+1 = ll = 2, 4, 6, ..... 2*n*n for (i=1; i<=n; i++){ for (j=1; j<=n; j++){ l = j + (i-1)*n; // l = 1, 2, 3, ... n*n ll = 2*l-1; // ll = 1, 3, 5, ..... 2*n*n -1 dat[ll] = Number(aReal[i-1][j-1]); dat[ll+1] = Number(aImag[i-1][j-1]); } } // Do an inverse 2D transform // nn[] is an integer array holding the length of each dimension nn[1]=nn[2]=n; //note nn[0] not used as was fortran array? fourn(dat,nn,ndim, 1); for (i=1; i<=n; i++) for (j=1; j<=n; j++){ l = j + (i-1)*n; ll = 2*l-1; nPix[0][j-1][i-1] = Number(dat[ll]); } } public function getStats(channels:Array):Stats{ var s:Stats=new Stats, min:Number, max:Number=nPix[channels[0]][0][0]; min=max; for (var i:int; i= ip1) && (i2rev > ibit)) { i2rev = i2rev-ibit; ibit = ibit/2; } i2rev = i2rev+ibit; } ifp1 = ip1; while (ifp1 < ip2) { ifp2 = 2*ifp1; theta = isign*2.0*Math.PI/(ifp2/ip1); wpr = -2.0*(Math.sin(0.5*theta)*Math.sin(0.5*theta)); wpi = Math. sin(theta); wr = 1.0; wi = 0.0; for (ii3=0; ii3<=((ifp1-1)/ip1); ii3++) { i3 = 1+ii3*ip1; for (ii1=0; ii1<=((ip1-2)/2); ii1++) { i1 = i3+ii1*2; for (ii2=0; ii2<=((ip3-i1)/ifp2); ii2++) { i2 = i1+ii2*ifp2; k1 = i2; k2 = k1+ifp1; tempr = wr*data[k2] - wi*data[k2+1]; tempi = wr*data[k2+1] + wi*data[k2]; data[k2] = data[k1]-tempr; data[k2+1] = data[k1+1]-tempi; data[k1] = data[k1]+tempr; data[k1+1] = data[k1+1]+tempi; } } wtemp = wr; wr = wr*wpr-wi*wpi+wr; wi = wi*wpr+wtemp*wpi+wi; } ifp1 = ifp2; } nprev = n*nprev; } } private function populate_nPix():void{ //Note that a getter function for nPix seems to take too long when used in a 512x512 pixel loop for (var c:int=0; c