'Glitch' Art Filters - again

Is that the aftermath image after the applied filter? It seems that you’re close, but I can’t help as I don’t know about JPEG enough to find a solution for you. Other than that I like it better than the one you want to recreate.

No, it’s a real screwed up JPEG from the Snorpey site again. I’m not going for the exact effect but I want to capture this thing with the pattern of tiles. Why high-frequency vertical ones in particular?

I don’t know how to get this Fisher-Yates shuffle to work properly:

rm
8,1,1,1,"x"
f "begin(shuffle(vv)=
(nn=size(vv);for(ii=(nn-1),ii>0,ii-=1,jj=floor(u(0,ii+1-1e-8));swap(vv[ii],vv[jj]));vv));
ref(crop(0,0,8,1),src);
shuffle(src);
draw(src);"
d

You taught me how to do that with bit-plane shuffler, right? What’s different here if that’s the case.

I’ve found something workable. I also need to make the thing detect edges to emulate an error in the Huffman tables…

Edit: maybe shuffling isn’t the right idea. Huffman table errors can be extremely abrasive and I want to emulate them very well and in a more configurable way. I’ve found a site where I can easily edit JPEGs and see what happens - there, I made the two images by changing some Huffman table values:

Edit: here is the current state of this mess. I will add a new part just for the Huffman table error emulation.

#@gui JPEG Encoder: fx_jpeg_preview
#@gui : sep = separator()
#@gui : 1. Quality=float(80,0,100)
#@gui : 2. Bias=float(0,-5,5)
#@gui : 3. Colour Space = choice(21,"RGB","sRGB","CMY","RYB","Ohta8","Ohta","YES8","YES","Kodak1-8","Kodak1","Lab8","Lab","Oklab","LUV","Jzazbz","YIQ8","YIQ","YUV8","YUV","YCbCr","YCbCrGLIC","YCbCrJPEG","YPbPr","YDbDr","YCoCg","LC1C2","LMS","XYZ8","XYZ","HSV8","HSV","HSL8","HSL","HSI8","HSI","HWB8","HWB","LCH8","LCH","Oklch","LCHuv","JzCzHz","HCY")
#@gui : 4. Channel 1 Block Width = int(8,2,32)
#@gui : 5. Channel 1 Block Height = int(8,2,32)
#@gui : 6. Channel 2 Block Width = int(16,2,32)
#@gui : 7. Channel 2 Block Height = int(16,2,32)
#@gui : 8. Channel 3 Block Width = int(16,2,32)
#@gui : 9. Channel 3 Block Height = int(16,2,32)
#@gui : 10. Mirror = choice("None","X","Y","XY")
#@gui : 11. Rotate = choice("None,"90 clockwise","180","90 anticlockwise")
#@gui : sep = separator()
#@gui : Toggle Block Offsets = bool(0)
#@gui : 12. Channel 1 Block X Offset = int(0,-32,32)
#@gui : 13. Channel 1 Block Y Offset = int(0,-32,32)
#@gui : 14. Channel 2 Block X Offset = int(0,-32,32)
#@gui : 15. Channel 2 Block Y Offset = int(0,-32,32)
#@gui : 16. Channel 3 Block X Offset = int(0,-32,32)
#@gui : 17. Channel 3 Block Y Offset = int(0,-32,32)
#@gui : sep = separator()
#@gui : Toggle Distortion Glitch = bool(0)
#@gui : 18. Glitch Start = float(0.2,0,1)
#@gui : 19. Glitch Min Distance = float(0.2,0,1)
#@gui : 20. Glitch Max Distance = float(0.8,0,1)
#@gui : 21. Glitch Frequency Skew = float(-0.5,-1,1)
#@gui : 22. Glitch Min Length = int(1,1,10)
#@gui : 23. Glitch Max Length = int(5,1,10)
#@gui : 24. Discolouring Strength = float(1,0,2)
#@gui : 25. Discolouring Variation = float(1,0,2)
#@gui : 26. Discolouring Speed = float(1,0,2)
#@gui : 27. Additive Strength = float(1,0,2)
#@gui : 28. Persistent Error Strength = float(0.25,0,2)
#@gui : 29. Persistent Error Chance = float(0.25,0,1)
#@gui : 30. Tile Shift Direction = float(0.5,0,1)
#@gui : 31. Tile Shift Chance = float(0.25,0,1)
#@gui : 32. Tile Width = int(16,2,32)
#@gui : 33. Tile Height = int(16,2,32)
#@gui : 34. Tile X Offset = int(0,-32,32)
#@gui : 35. Tile Y Offset = int(0,-32,32)

fx_jpeg :
to_rgb

inum=$!
bias={2^-$2}
q=$1
cs=$3
startg=$18
ming=$19
maxg=$20
gfs=$21
glmin=$22
glmax=$23
di=$24
dv=$25
ds=$26
ai=$27
pei=$28
pec=$29
tsd=$30
tsc=$31
tstw=$32
tsth=$33
tsox={$34%$tstw}
tsoy={$35%$tsth}

gfskew={-log(2)/(log(0.5-$gfs*0.5))}

if $10==1
mirror x
elif $10==2
mirror y
elif $10==3
mirror xy
fi
if $11
rotate {$11*90},0
fi

csswap 0,$cs

($4,$6,$8;$5,$7,$9;0,0,0;$12,$14,$16;$13,$15,$17)
nm. params

eval. "begin(index=0;list=transpose(crop(0,0,3,2),3);foundlist=vector6(0));
for(n=0,n<3,++n,
pos=n*2;
cp=list[pos,2];
(find(foundlist,cp,0,2)==-1)?(
index=find(foundlist,[0,0],0,2);
foundlist[index]=cp[0];
foundlist[index+1]=cp[1]);
i(n,2)=find(foundlist,cp,0,2)*0.5
);"

tcount=0
repeat 3
tnum={i(#$params,$>,2)}
if $tnum==$tcount
tw={i(#$params,$>,0)}
th={i(#$params,$>,1)}
dct_tileset $tw,$th
idct_tileset $tw,$th
# nm[-2,-1] "dct"$tcount"","idct"$tcount""
tcount+=1
fi
done

repeat $inum l[$>,{(-2*$tcount)-1}--1]

cw={w(#0)}
ch={h(#0)}

$cw,$ch,1,1

# distortion glitch punch card image
f. ">begin(const ming="$ming";const maxg="$maxg";count="$startg"*wh;const gfs="$gfs"; const gfskew="$gfskew";const igfskew=1/gfskew);
count-=1;
count<0?(count=(1-((1-u(ming,maxg)^gfskew)^igfskew))*wh;1):0"
nm. dpunch

# tile shift glitch
if $tsc
z[0] {-$tsox},{-$tsoy},{$cw+((-$cw)%$tstw)-1-$tsox},{$ch+((-$ch)%$tsth)-1-$tsoy},3
[0]
f[0] >"begin(const tstw="$tstw";const tsth="$tsth";const tstwh=tstw*tsth;const itstw=1/tstw;const itsth=1/tsth;const iw=1/w;const tsox="$tsox";const tsoy="$tsoy";tsc="$tsc";tsd="$tsd";ioff=0);
if (!(x%tstw) && !(y%tsth),
glitch=max(crop(#"$dpunch",x-tsox,y-tsoy,0,0,tstw,tsth,1,1));
(glitch)?((u<tsc)?(ioff+=(u<tsd)?(1):(-1)));
index=(x*itstw+y*itsth*w*itstw);
nindex=index+ioff;
ref(crop(#-1,(nindex%(w*itstw))*tstw,floor(nindex*tstw*iw)*tsth,0,0,tstw,tsth,1,3,0),src);
draw(src,x,y,0,0,tstw,tsth,1,3));
I
"
rm.
z[0] $tsox,$tsoy,{$cw-1+$tsox},{$ch-1+$tsoy},3
fi

s[0] c

repeat 3

tw={i(#$params,$>,0)}
th={i(#$params,$>,1)}
tn={i(#$params,$>,2)}
ox={-i(#$params,$>,3)%$tw}
oy={-i(#$params,$>,4)%$th}
imax=0
imin=0
l[$>]
imax={iM}
imin={im}
if $imax!=$imin
- $imin * {1/($imax-$imin)}
else
+ {1-$imax}
fi
endl

z[$>] {-$ox},{-$oy},{$cw+((-$cw)%$tw)-1-$ox},{$ch+((-$ch)%$th)-1-$oy},3
[$>]

# dct
f[$>] :"
begin(const tw="$tw";const th="$th";const twh=tw*th;const tn="$tn";const tileset=(tn-"$tcount")*2-2);
if (!(x%tw) && !(y%th),
res=vector(#twh,0);
ref(crop(x,y,tw,th),src);
for (l = 0, l<th, ++l, for (k = 0, k<tw, ++k,
off = k + tw*l;
res += src[off]*crop(#tileset,k*tw,l*th,tw,th,1)));
draw(#-1,res,x,y,0,0,tw,th);
); i"

# distortion glitch

if ($di||$ai||$pei)&&(1-$startg)&&((1-$ming)||(1-$maxg))
f. >"begin(const tw="$tw";const th="$th";const twh=tw*th;const itw=1/tw;const ith=1/th;const itwh=itw*ith;const ox="$ox";const oy="$oy";const di="$di";const dv="$dv";const ds="$ds";const ai="$ai";const pei="$pei";const pec="$pec"; const gfskew="$gfskew";const igfskew=1/gfskew;const glmin="$glmin";const glmax="$glmax";const glitchf=sqrt(max(twh/wh,(1-((1-avg("$ming","$maxg")^gfskew)^igfskew)))/avg(glmin,glmax));glitchdm=vector(#twh,1);first=1;gcount=0;glitchdc=0;glitchdv=0;glitcha=vector(#twh,0);aswitch=0;pswitch=0;ioff=0;shuf=vector(#twh,0);for(nn=0,nn<twh,nn++,shuf[nn]=nn);sswitch=0);
if (!(x%tw) && !(y%th),
ref(crop(x,y,0,0,tw,th,1,1,0),src);
res=(vector(#twh,0));
glitch=max(crop(#"$dpunch",x-ox,y-oy,0,0,tw,th,1,1,1));
(glitch)?(first?((glitchdc=u(-1,1)*glitchf);first=0;
#(u<0.25)?(sswitch=1; for(ii=(twh-1),ii>0,ii--,jj=floor(u(0,ii+1-1e-8));swap(shuf[ii],shuf[jj]))):(sswitch=0)
);
glitchcount=int(u(glmin,glmax+1-1e-8)));
(glitchcount)?(glitchcount-=1;aswitch=1;pswitch=((u<pec)?1:0);
glitchdv=(glitchdv+(u(-1,1)*glitchf*(ds^2)));
amult=ai^2;
):(amult=20^2);
(aswitch&&(!pswitch))?(for(n=1,n<twh,++n,
l=n-int(n*itw)*tw;k=int(n*itw);
glitcha[n]=(1/((l+1)*(k+1)))*(amult)*u(-1,1)));
#(sswitch)?(for(nn=0,nn<twh,nn++,res[nn]=src[shuf[nn]]);0):(res=src;0);
res=src+glitcha;
res[0]=lerp(res[0],sin(asin(res[0]*itwh*pi*0.5)+(glitchdc*10+glitchdv*(dv^2))*0.01*pi)*twh*2/pi,di^2);
draw(res,x,y,0,0,tw,th);
(pswitch==0)?(aswitch=0;
glitcha=vector(#twh,0);0));
i
"
fi

# very lazy compression emulation
f. :"begin(const factor=sqrt("$tw"*"$th");const invfactor=1/factor; const qual=(1-("$q"*0.01))^4;const pow="$bias"; const invpow=1/pow);sign(i)*(factor*round((abs(i)^(invpow))*invfactor,qual))^pow"

# idct
f. :"
begin(const tw="$tw";const th="$th";const twh=tw*th;const tn="$tn";const tileset=(tn-"$tcount")*2-1);
if (!(x%tw) && !(y%th),
res=vector(#twh,0);
ref(crop(x,y,tw,th),src);
for (l = 0, l<th, ++l, for (k = 0, k<tw, ++k,
off = k + tw*l;
res += src[off]*crop(#tileset,k*tw,l*th,tw,th,1)));
draw(#"$>",res,x,y,0,0,tw,th);
); i"
rm.


l[$>]
c 0,1
if $imax!=$imin
* {($imax-$imin)} + $imin
else
+ {$imax-1}
fi
endl

z[$>] $ox,$oy,{$cw-1+$ox},{$ch-1+$oy},3

done
a[0-2] c

endl done

rm[{(-2*$tcount)-2}--1]

csswap $cs,0

if $11
rotate {-$11*90},0
fi
if $10==1
mirror x
elif $10==2
mirror y
elif $10==3
mirror xy
fi

fx_jpeg_preview:

if $12
o0,o1,o2,o3,o4,o5=${13-18}
else
repeat 6
o$>=0
done
fi

if $19
g0,g1,g2,g3,g4,g5,g6,g7,g8,g9,g10,g11,g12,g13,g14,g15,g16,g17=${20-37}
else
repeat 18
g$>=0
done
fi

fx_jpeg ${1-11},$o0,$o1,$o2,$o3,$o4,$o5,$g0,$g1,$g2,$g3,$g4,$g5,$g6,$g7,$g8,$g9,$g10,$g11,$g12,$g13,$g14,$g15,$g16,$g17

u "{$1}"\
"{$2}"\
"{$3}"\
"{$4}"\
"{$5}"\
"{$6}"\
"{$7}"\
"{$8}"\
"{$9}"\
"{$10}"\
"{$11}"\
"{$12}"\
"{$13}_"{$12?2:0}\
"{$14}_"{$12?2:0}\
"{$15}_"{$12?2:0}\
"{$16}_"{$12?2:0}\
"{$17}_"{$12?2:0}\
"{$18}_"{$12?2:0}\
"{$19}"\
"{$20}_"{$19?2:0}\
"{$21}_"{$19?2:0}\
"{$22}_"{$19?2:0}\
"{$23}_"{$19?2:0}\
"{$24}_"{$19?2:0}\
"{$25}_"{$19?2:0}\
"{$26}_"{$19?2:0}\
"{$27}_"{$19?2:0}\
"{$28}_"{$19?2:0}\
"{$29}_"{$19?2:0}\
"{$30}_"{$19?2:0}\
"{$31}_"{$19?2:0}\
"{$32}_"{$19?2:0}\
"{$33}_"{$19?2:0}\
"{$34}_"{$19?2:0}\
"{$35}_"{$19?2:0}\
"{$36}_"{$19?2:0}\
"{$37}_"{$19?2:0}

1 Like

@Joan_Rake1 How’s the JPEG Encoder coming out?