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 - Digital Artifacts
Image_DigitalArtifacts.ls
*/
@version 2.5
@warnings
@script image
@name *Digital Artifacts
// Title
sTitle = "*Digital Artifacts";
// Version
sVersion = "v1.0";
iBlockSize = 8;
iLifeRed = 2;
iLifeGreen = 2;
iLifeBlue = 2;
nErrorRed = 0.03;
nErrorGreen = 0.03;
nErrorBlue = 0.03;
bColorSync = false;
aBlock = nil; // Block
// Control
ctrl_pr0,ctrl_c0,ctrl_c1,ctrl_c2,ctrl_c3,ctrl_c4,ctrl_c5,ctrl_c6,ctrl_c7;
create
{
setdesc(sTitle);
}
process: ifo
{
// Error
if(ifo.width < 1 || ifo.height < 1){return;}
// Variable
iBlock = 1;
iBlockMultiplier = 1 / (iBlockSize * iBlockSize);
iGridX = floor(ifo.width / iBlockSize);
iGridY = floor(ifo.height / iBlockSize);
_nErrorRed = nErrorRed * (iBlockSize * iBlockSize);
_nErrorGreen = nErrorGreen * (iBlockSize * iBlockSize);
_nErrorBlue = nErrorBlue * (iBlockSize * iBlockSize);
// Init Block
if(aBlock.size() <> (iGridX * iGridY) || ifo.frame == 0)
{
for(b = 1; b <= (iGridX * iGridY); ++b)
{
aBlock[b,1] = 0; // Red Count
aBlock[b,2] = 0; // Green Count
aBlock[b,3] = 0; // Blue Count
aBlock[b,4] = 0.0; // Red
aBlock[b,5] = 0.0; // Green
aBlock[b,6] = 0.0; // Blue
}
}
iProgress = iGridX * iGridY;
if(runningUnder() != SCREAMERNET) moninit(iProgress);
for(gy = 0;gy <= iGridY - 1; ++gy)
{
for(gx = 0;gx <= iGridX - 1; ++gx)
{
_gx = gx * iBlockSize;
_gy = gy * iBlockSize;
r = 0;
g = 0;
b = 0;
// Average
for(i = 1;i <= iBlockSize; ++i)
{
for(j = 1;j <= iBlockSize; ++j)
{
r += ifo.red[j + _gx,i + _gy]; // Red
g += ifo.green[j + _gx,i + _gy]; // Green
b += ifo.blue[j + _gx,i + _gy]; // Blue
}
}
r *= iBlockMultiplier;
g *= iBlockMultiplier;
b *= iBlockMultiplier;
// Difference
rd = 0;
gd = 0;
bd = 0;
for(i = 1;i <= iBlockSize; ++i)
{
for(j = 1;j <= iBlockSize; ++j)
{
rd += abs(ifo.red[j + _gx,i + _gy] - r);
gd += abs(ifo.green[j + _gx,i + _gy] - g);
bd += abs(ifo.blue[j + _gx,i + _gy] - b);
}
}
// Update Block
if(bColorSync)
{
if((aBlock[iBlock,1] <= 0 && rd < _nErrorRed) ||
(aBlock[iBlock,2] <= 0 && gd < _nErrorGreen) ||
(aBlock[iBlock,3] <= 0 && bd < _nErrorBlue))
{
c = random(1,3);
aBlock[iBlock,1] = c;
aBlock[iBlock,2] = c;
aBlock[iBlock,3] = c;
}
aBlock[iBlock,4] = r;
aBlock[iBlock,5] = g;
aBlock[iBlock,6] = b;
}
else
{
if(aBlock[iBlock,1] <= 0 && rd < _nErrorRed) // Red
{
aBlock[iBlock,1] = random(1,iLifeRed);
aBlock[iBlock,4] = r;
}
if(aBlock[iBlock,2] <= 0 && gd < _nErrorGreen) // Green
{
aBlock[iBlock,2] = random(1,iLifeGreen);
aBlock[iBlock,5] = g;
}
if(aBlock[iBlock,3] <= 0 && bd < _nErrorBlue) // Blue
{
aBlock[iBlock,3] = random(1,iLifeBlue);
aBlock[iBlock,6] = b;
}
}
// Read Block
rd = aBlock[iBlock,1];
--aBlock[iBlock,1];
r = aBlock[iBlock,4];
gd = aBlock[iBlock,2];
--aBlock[iBlock,2];
g = aBlock[iBlock,5];
bd = aBlock[iBlock,3];
--aBlock[iBlock,3];
b = aBlock[iBlock,6];
// Draw Block
for(i = 1;i <= iBlockSize; ++i)
{
for(j = 1;j <= iBlockSize; ++j)
{
if(rd > 0){ifo.red[j + _gx,i + _gy] = r;}
if(gd > 0){ifo.green[j + _gx,i + _gy] = g;}
if(bd > 0){ifo.blue[j + _gx,i + _gy] = b;}
}
}
++iBlock;
if(runningUnder() != SCREAMERNET) if(monstep()) return;
}
}
}
// CLIP
clip: min,max,n
{
if(n < min) n = min;
if(n > max) n = max;
return(n);
}
load: what,io
{
if(what == SCENEMODE)
{
bColorSync = io.read().asInt();
iBlockSize = io.read().asInt();
iLifeRed = io.read().asInt();
iLifeGreen = io.read().asInt();
iLifeBlue = io.read().asInt();
nErrorRed = io.read().asNum();
nErrorGreen = io.read().asNum();
nErrorBlue = io.read().asNum();
}
}
save: what,io
{
if(what == SCENEMODE)
{
io.writeln(bColorSync);
io.writeln(iBlockSize);
io.writeln(iLifeRed);
io.writeln(iLifeGreen);
io.writeln(iLifeBlue);
io.writeln(nErrorRed);
io.writeln(nErrorGreen);
io.writeln(nErrorBlue);
}
}
options
{
reqbegin(sTitle + " " + sVersion);
// Control
ctrl_pr0 = ctlpopup("Preset",1, @"Low",
"Medium",
"High",
"Extreme"@);
ctlsep();
ctrl_c0 = ctlinteger("Block Size",iBlockSize);
ctrl_c1 = ctlcheckbox("Color Sync",bColorSync);
ctrl_c2 = ctlinteger("Life Red",iLifeRed);
ctrl_c3 = ctlinteger(" Green",iLifeGreen);
ctrl_c4 = ctlinteger(" Blue",iLifeBlue);
ctrl_c5 = ctlpercent("Error Red",nErrorRed);
ctrl_c6 = ctlpercent(" Green",nErrorGreen);
ctrl_c7 = ctlpercent(" Blue",nErrorBlue);
// Developer
ctlsep();
ctrl_dev0 = ctltext("","developer: Stephen Culley","http://www.stephenculley.co.uk");
// Refresh
ctlrefresh(ctrl_pr0,"refresh_preset"); // Preset
ctlrefresh(ctrl_c0,"refresh_c0"); // Block Size
ctlrefresh(ctrl_c2,"refresh_c2"); // Life Red
ctlrefresh(ctrl_c3,"refresh_c3"); // Life Green
ctlrefresh(ctrl_c4,"refresh_c4"); // Life Blue
ctlrefresh(ctrl_c5,"refresh_c5"); // Error Red
ctlrefresh(ctrl_c6,"refresh_c6"); // Error Green
ctlrefresh(ctrl_c7,"refresh_c7"); // Error Blue
return if !reqpost();
iBlockSize = max(1,getvalue(ctrl_c0));
bColorSync = getvalue(ctrl_c1);
iLifeRed = max(1,getvalue(ctrl_c2));
iLifeGreen = max(1,getvalue(ctrl_c3));
iLifeBlue = max(1,getvalue(ctrl_c4));
iErroRed = max(0.0,getvalue(ctrl_c5));
iErrorGreen = max(0.0,getvalue(ctrl_c6));
iErrorBlue = max(0.0,getvalue(ctrl_c7));
reqend();
}
refresh_preset:value
{
if(value == 1) // Low
{
setvalue(ctrl_c0,8); // Block Size
setvalue(ctrl_c1,0); // Sync Color
setvalue(ctrl_c2,1); // Life Red
setvalue(ctrl_c3,1); // Life Green
setvalue(ctrl_c4,1); // Life Blue
setvalue(ctrl_c5,0.02); // Error Red
setvalue(ctrl_c6,0.02); // Error Green
setvalue(ctrl_c7,0.02); // Error Blue
}
if(value == 2) // Medium
{
setvalue(ctrl_c0,8); // Block Size
setvalue(ctrl_c1,0); // Sync Color
setvalue(ctrl_c2,2); // Life Red
setvalue(ctrl_c3,2); // Life Green
setvalue(ctrl_c4,2); // Life Blue
setvalue(ctrl_c5,0.02); // Error Red
setvalue(ctrl_c6,0.03); // Error Green
setvalue(ctrl_c7,0.04); // Error Blue
}
if(value == 3) // High
{
setvalue(ctrl_c0,8); // Block Size
setvalue(ctrl_c1,0); // Sync Color
setvalue(ctrl_c2,3); // Life Red
setvalue(ctrl_c3,3); // Life Green
setvalue(ctrl_c4,3); // Life Blue
setvalue(ctrl_c5,0.02); // Error Red
setvalue(ctrl_c6,0.04); // Error Green
setvalue(ctrl_c7,0.06); // Error Blue
}
if(value == 4) // Extreme
{
setvalue(ctrl_c0,8); // Block Size
setvalue(ctrl_c1,0); // Sync Color
setvalue(ctrl_c2,9); // Life Red
setvalue(ctrl_c3,9); // Life Green
setvalue(ctrl_c4,9); // Life Blue
setvalue(ctrl_c5,0.1); // Error Red
setvalue(ctrl_c6,0.1); // Error Green
setvalue(ctrl_c7,0.1); // Error Blue
}
}
refresh_c0:value // Block Size
{
iBlockSize = max(1,value);
setvalue(ctrl_c0,iBlockSize);
}
refresh_c2:value // Life Red
{
iLifeRed = max(1,value);
setvalue(ctrl_c2,iLifeRed);
}
refresh_c3:value // Life Green
{
iLifeGreen = max(1,value);
setvalue(ctrl_c3,iLifeGreen);
}
refresh_c4:value // Life Blue
{
iLifeBlue = max(1,value);
setvalue(ctrl_c4,iLifeBlue);
}
refresh_c5:value // Error Red
{
nErrorRed = clip(0.0,1.0,value);
setvalue(ctrl_c5,nErrorRed);
}
refresh_c6:value // Error Green
{
nErrorGreen = clip(0.0,1.0,value);
setvalue(ctrl_c6,nErrorGreen);
}
refresh_c7:value // Error Blue
{
nErrorBlue = clip(0.0,1.0,value);
setvalue(ctrl_c7,nErrorBlue);
}
All scripts available at my Google Drive at
https://drive.google.com/open?id=1cR_q2GVUAJHumic1-A3eXV16acQnVTWs

Cool lscript, thank you.
ReplyDeleteWould it possible to add envelopes, to be able to animate the blockiness over time?
Do you mean opacity of the effect, or just the controls? The only control that would be difficult to change would be block size due it it needing to change array sizes and data would be lost. Otherwise, I could make it have envelopes. Maybe add opacity as well tho that will slow down processing?
DeleteStephen
It would be the size of the blocks (Block Size) that would be cool to be able to animate over time.
DeleteI guess it would be like a zoom effect into an image so the blocky pixels look like they are getting bigger.
This is an old script so what I'll do is create a quick script to generate block effects since to be able to change block size would require a slight rewrite to implement. I'll sort an example of it over tomorrow.
DeleteStephen