LScript (Layout) applies random noise in three different modes, monochrome, color, exposure and fBm noise. Exposure adds noise only to darker areas as they appear in real life photos. fBm is a perlin based noise using Fractal Brownian Motion.
Compatible with Newtek LightWave 9.6 and above.
// LScript Image Filter - www.StephenCulley.co.uk
//
// web address: http://www.stephenculley.co.uk
// email address: email@stephenculley.co.uk
/*
LScript Image Filter - Noise
Image_Noise.ls
*/
@version 2.5
@warnings
@script image
@name *Noise
// Title
sTitle = "*Noise";
// Version
sVersion = "v1.0";
aType = @"*Monochrome Noise : ","*Color Noise : ","*Exposure Noise : ","*fBm Noise : "@;
iInterpolation = 1;
iOctaves = 3;
iType = 1;
nAmount = 0.5;
nPersistence = 0.25;
nScale = 0.02;
create
{
setdesc(aType[iType] + nAmount);
}
process: ifo
{
if(iType == 1) // Monochrome
{
if(runningUnder() != SCREAMERNET) moninit(ifo.height);
for(i = 1;i <= ifo.height;++i)
{
for(j = 1;j <= ifo.width;++j)
{
nNoise = (randu() * 2 - 1) * nAmount;
ifo.red[j,i] = ifo.red[j,i] + nNoise;
ifo.green[j,i] = ifo.green[j,i] + nNoise;
ifo.blue[j,i] = ifo.blue[j,i] + nNoise;
}
if(runningUnder() != SCREAMERNET) if(monstep()) return;
}
}
else if(iType == 2) // Colour
{
if(runningUnder() != SCREAMERNET) moninit(ifo.height);
for(i = 1;i <= ifo.height;++i)
{
for(j = 1;j <= ifo.width;++j)
{
ifo.red[j,i] = ifo.red[j,i] + ((randu() * 2 - 1) * nAmount);
ifo.green[j,i] = ifo.green[j,i] + ((randu() * 2 - 1) * nAmount);
ifo.blue[j,i] = ifo.blue[j,i] + ((randu() * 2 - 1) * nAmount);
}
if(runningUnder() != SCREAMERNET) if(monstep()) return;
}
}
else if(iType == 3) // Exposure
{
if(runningUnder() != SCREAMERNET) moninit(ifo.height);
for(i = 1;i <= ifo.height;++i)
{
for(j = 1;j <= ifo.width;++j)
{
ifo.red[j,i] = ifo.red[j,i] + ((1 - ifo.red[j,i]) * ((randu() * 2 - 1) * nAmount));
ifo.green[j,i] = ifo.green[j,i] + ((1 - ifo.green[j,i]) * ((randu() * 2 - 1) * nAmount));
ifo.blue[j,i] = ifo.blue[j,i] + ((1 - ifo.blue[j,i]) * ((randu() * 2 - 1) * nAmount));
}
if(runningUnder() != SCREAMERNET) if(monstep()) return;
}
}
else if((iType == 4) && (iInterpolation == 1)) // Linear fBm
{
if(runningUnder() != SCREAMERNET) moninit(ifo.height);
noiseseed(ifo.frame); // Noise Seed
for(i = 1;i <= ifo.height;++i)
{
for(j = 1;j <= ifo.width;++j)
{
nNoise = linearfBmnoise2D( * nScale,
iOctaves,
nPersistence) * nAmount;
ifo.red[j,i] = ifo.red[j,i] + nNoise;
ifo.green[j,i] = ifo.green[j,i] + nNoise;
ifo.blue[j,i] = ifo.blue[j,i] + nNoise;
}
if(runningUnder() != SCREAMERNET) if(monstep()) return;
}
}
else if((iType == 4) && (iInterpolation == 2)) // Cosine fBm
{
if(runningUnder() != SCREAMERNET) moninit(ifo.height);
noiseseed(ifo.frame); // Noise Seed
for(i = 1;i <= ifo.height;++i)
{
for(j = 1;j <= ifo.width;++j)
{
nNoise = cosinefBmnoise2D( * nScale,
iOctaves,
nPersistence) * nAmount;
ifo.red[j,i] = ifo.red[j,i] + nNoise;
ifo.green[j,i] = ifo.green[j,i] + nNoise;
ifo.blue[j,i] = ifo.blue[j,i] + nNoise;
}
if(runningUnder() != SCREAMERNET) if(monstep()) return;
}
}
}
// INTERPOLATION
linear1D: n1,n2,i // i = interpolation point (0-1)
{
return(n1 * (1 - i) + n2 * i);
}
cosine1D: n1,n2,i // i = interpolation point (0-1)
{
i2 = (1 - cos(i * 3.1415926535)) * 0.5;
return(n1 * (1 - i2) + n2 * i2);
}
bicubic1D: n1,n2,n3,n4,i // i = interpolation point (0-1)
{
i2 = i * i;
n_01 = n4 - n3 - n1 + n2;
n_02 = n1 - n2 - n_01;
n_03 = n3 - n1;
n_04 = n2;
return(n_01 * i * i2 + n_02 * i2 + n_03 * i + n_04);
}
// NOISE
_noiseseed = 1;
_noiseresolution = 512;
_noise = nil;
_noiseoffset = nil;
_noiseperm = nil;
noiseinit
{
randomseed(_noiseseed); // Random Seed
for(iN = 1; iN <= _noiseresolution; iN++)
{
_noise[iN] = (random() * 2) - 1; // -1.0..1.0
_noiseperm[iN] = wrap(1,_noiseresolution,floor(random() * _noiseresolution));
}
for(iO = 1; iO <= 64; iO++)
{
_noiseoffset[iO] = ;
}
}
noiseseed: seed
{
_noiseseed = seed;
noiseinit(); // Init
}
noiseresolution: resolution
{
_noiseresolution = resolution;
noiseinit(); // Init
}
noiseperm1D: n // i
{
// ! if(_noiseperm == nil){noiseinit();} // Init
return(_noiseperm[wrap(1,_noiseresolution,floor(n))]);
}
noiseperm2D: v // n
{
return(noiseperm1D(v.y + noiseperm1D(v.x)));
}
noise2D: v // n
{
// ! if(_noise == nil){noiseinit();} // Init
return(_noise[noiseperm2D(v)]);
}
linearnoise2D: v // n
{
v = wrap(1,_noiseresolution,v);
vFrac = frac(v);
vInt = v - vFrac;
n1 = noise2D();
n2 = noise2D();
n3 = noise2D();
n4 = noise2D();
return(linear1D(linear1D(n1,n2,vFrac.x),linear1D(n3,n4,vFrac.x),vFrac.y));
}
cosinenoise2D: v // n
{
v = wrap(1,_noiseresolution,v);
vFrac = frac(v);
vInt = v - vFrac;
n1 = noise2D();
n2 = noise2D();
n3 = noise2D();
n4 = noise2D();
return(cosine1D(cosine1D(n1,n2,vFrac.x),cosine1D(n3,n4,vFrac.x),vFrac.y));
}
linearfBmnoise2D: v,octaves,persistence // octaves = i | persistence = n (0.25) // n
{
// ! if(_noiseoffset == nil){noiseinit();} // Init
nNoise = 0.0;
for(iO = 1; iO <= octaves; iO++)
{
nNoise += linearnoise2D(<(v.x + _noiseoffset[iO].x) * (2 * iO),(v.y + _noiseoffset[iO].y) * (2 * iO),0.0>) * (persistence / iO);
}
return(nNoise);
}
cosinefBmnoise2D: v,octaves,persistence // octaves = i | persistence = n (0.25) // n
{
// ! if(_noiseoffset == nil){noiseinit();} // Init
nNoise = 0.0;
for(iO = 1; iO <= octaves; iO++)
{
nNoise += cosinenoise2D(<(v.x + _noiseoffset[iO].x) * (2 * iO),(v.y + _noiseoffset[iO].y) * (2 * iO),0.0>) * (persistence / iO);
}
return(nNoise);
}
// RANDOM
_randomseed = 0; // n Seed
randomseed: seed
{
_randomseed = seed;
}
random
{
n = (_randomseed * 214013 + 2531011) % 2^^24;
_randomseed = n;
n /= 2^^24; // 0..1
return(n);
}
gaussianrandom
{
n1 = random();
n2 = random();
if(n1 == 0.0){n1 = 0.01;}
return(sqrt(-2.0 * log(n1)) * cos(2.0 * 3.1415926535 * n2));
}
// WRAP
wrap: min,max,n
{
n = n - floor((n - min) / (max - min)) * (max - min);
if(n < 0) n = n + max - min; // error check
return(n);
}
load: what,io
{
if(what == SCENEMODE)
{
iInterpolation = io.read().asInt();
iOctaves = io.read().asInt();
iType = io.read().asInt();
nAmount = io.read().asNum();
nPersistence = io.read().asNum();
nScale = io.read().asNum();
setdesc(aType[iType] + nAmount);
}
}
save: what,io
{
if(what == SCENEMODE)
{
io.writeln(iInterpolation);
io.writeln(iOctaves);
io.writeln(iType);
io.writeln(nAmount);
io.writeln(nPersistence);
io.writeln(nScale);
}
}
options
{
reqbegin(sTitle + " " + sVersion);
// Control
ctrl_c0 = ctlchoice("Type",iType,@"Monochrome","Color","Exposure","fBm"@); // Type
ctrl_c1 = ctlnumber("Amount",nAmount); // Amount
ctrl_c2 = ctlslider("Octaves (fBm)",iOctaves,1,64); // Octaves
ctrl_c3 = ctlnumber("Persistence (fBm)",nPersistence); // Persistence
ctrl_c4 = ctlnumber("Scale (fBm)",nScale); // Scale
ctrl_c5 = ctlchoice("Interpolation (fBm)",iInterpolation,@"Linear","Cosine"@); // Interpolation
// Developer
ctlsep();
ctrl_dev0 = ctltext("","developer: Stephen Culley","http://www.stephenculley.co.uk");
return if !reqpost();
iType = getvalue(ctrl_c0);
nAmount = getvalue(ctrl_c1);
iOctaves = getvalue(ctrl_c2);
nPersistence = getvalue(ctrl_c3);
nScale = getvalue(ctrl_c4);
iInterpolation = getvalue(ctrl_c5);
setdesc(aType[iType] + nAmount);
reqend();
}
All scripts available at my
Google Drive at
https://drive.google.com/open?id=1cR_q2GVUAJHumic1-A3eXV16acQnVTWs