Glitch Art Filters?

Might be the default settings themselves.

I think we’ll just settle on your version.

I now realize the interpolation on my own version was transferred as a blending mode on the other version. The one on my own version did interpolation for making details more apparent, but the self-blending mode on my own version has it own blending mode utilizing the resulting image after the main. So, I guess to finish it up, interpolation could be it own blending mode called post-processing, and then the self-blending mode comes after.

So basically:
21. Chroma/Hue/Luminosity Post-Processing Control Blend
22. Opacity
23. Self-Blend
24. Opacity

That is what I think that’s different that been bothering me a bit.

The low pass filter works by turning the image data into a continuous signal, which it then runs a low pass filter on.

I don’t remember whether the channels get separately filtered, so it may be the channel interlacing that produces unexpected results.

As an aside, I was up until 5am last night working on a generic FM modulation/demodulation library for float sample arrays. It is now working and I plan to utilise it to produce a number of analogue-like glitch effects, and perhaps some more ambitious effects like SSTV mod-demod with noise.

1 Like

I’d love to know how it all works so I can get something up and running in G’MIC. I’m really happy with the Butterworth bandpass I have and I’ll try to get other filters in like the Papoulis and Chebyshev ones. I also want to eventually move on to interactive windows for GUIs so that I’m not confined by the plugin interface.

Hmm, are you thinking of something like the Android glitching apps where you touch and make the glitch? I don’t see the issue with the current system besides that.

The current plugin GUI has no option to allow for variable numbers of sliders, checkboxes and other elements. Many of the filters made here easily surpass 20 options and I know of two which go beyond 60.

Oh that. I’d imagine that ideally there would be a way to do it. New users wouldn’t appreciate seeing so many sliders. That’s not a problem for those with experience.

Hell, you could give me a filter with 200 sliders and I would be fine with it.

I hope that’s not a challenge! In the meantime, have an improved Butterworth BP filter. The makeup gain is now actually a makeup gain. The last thing to add for now would be a way to mess with the phases but I don’t know how to do this yet. The maths is tricky.

#@gui Butterworth Bandpass: fx_butterworth_bp, fx_butterworth_bp_preview(0)
#@gui : note = note("Lowpass and highpass  zero-phase Butterworth filters.")
#@gui : sep = separator()
#@gui : LP Frequency Power = float(3,0,12)
#@gui : LP Order Power = float(2,0,10)
#@gui : HP Frequency Power = float(4,0,12)
#@gui : HP Order Power = float(2,0,10)
#@gui : Colour Space= choice("RGB","sRGB","CMYK","CMY","HSV8","HSV","HSL8","HSL","HSI8","HSI","LCH8","LCH","Lab8","Lab","YCbCr","YCbCrGLIC","YIQ8","YIQ","YUV8","YUV","Bayer","HCY","XYZ8","XYZ")
#@gui : Alpha = bool(0)
#@gui : Absolute = bool(1)
#@gui : Makeup Gain = bool(1)

_butterworth_bp :
v -
100%,100%,100% f. "scale=max(w,h,d);vx=(x-w/2)/scale;vy=(y-h/2)/scale;vz=(z-d/2)/scale;rad=(vx^2+vy^2+vz^2)^0.5;func=(1/((1+((rad/(2^$1))*scale)^($2*2^($2/2)))^0.5))*(1/((1+(((rad/(2^$3))*scale)^($4*(2^($4/2)))^-1))^0.5));func"
shift. {int(w/2)},{int(h/2)},{int(d/2)},0,2 *. 2
fft.. *... . *[-2,-1] ifft rm[-1]
v +
fx_butterworth_bp:
repeat $! l[$>]
if {!$6} split_opacity fi
l[0]
gain={iM} csswap 0,1,0,$5
_butterworth_bp ${1-4} 
csswap $5,1,0,0 if $7 abs fi if $8 * {$gain/iM} fi
endl
if {!$6} a c fi
endl done

fx_butterworth_bp_preview :
fx_butterworth_bp $*

image

1 Like

Ok, the FM library is now running fully parallel and can process a sample arrays equivalent to a 3000x3000 pixel image in approximately 3 seconds. Right now it’s processing audio data, but I’ll hopefully get it to run with image data in the next few hours.

This also gave me another idea: using the NAudio library to perform lossy audio compression on image data. An image can be easily turned into a set of sample values of the form -1.0 to 1.0, using split planes (R data, then G data, then B data). I think there may be some interesting results.

I tested the Bandpass filter. The blur looks nicer than Guassian Blur in some cases, like a lot nicer. For example, the PDN glitch test picture.

Are these filters going to be on PDN? Actually, @Joan_Rake1 and myself would like to have the source code in that case to make the filter accessible on G’MIC. Speaking of which, G’MIC is accessible by PDN.

I will be making these filters open-source on GitHub.

Here’s an example of some FM glitch effect output using a combination of pre-filter reflections, EQs, post-filter reflections, and signal noise.

And here’s an example of what happens if you slow the demodulation clock by 0.5%:

Finally, here’s a more artistic blending of some of the effects to produce what looks like a bad TV signal:

3 Likes

At this point we’re gonna need some new hardcoded functions in G’MIC to allow it to mess with image data as a plugin rather than only through the command line. I’ll have to find a way to implement more maths functions and get to the point where I can use an interactive GUI to implement more filters. I’d need a command with variable numbers of parameters to pull it off.

Scratch the previous version of this post. I’m trying to get a complex calculation so that the phase response will work as well. I want to use the same formula to do it without copying it and putting it somewhere else, but I can only iterate over each pixel within a fill command and I don’t know of anything which will let me make variables from within the stack of a fill command global.

Okay, Joan Rake and I have agreed that the ECB filter is done. I have done what Joan Rake has done, but also separating the interpolation from the self-blending mode. We are collaborating with each other via PM. And we are going to work on looper and the row shifter.

#@gui Pseudo-ECB (Electronic Code Book Algorithm): pseudo_ecb, _pseudo_ecb_preview(0)
#@gui : note = note("This filter is inspired by one of the glitch plugin for Paint.NET This doesn't actually emulate how the codebook encryption algorithm actually work, but it is inspired from it.  This filter uses bomb blending mode which involves RGBA Transfer Function Mesh. See Mesh Blend filter for a link. \n\n <u>Note that the filter works best on images with large patches of single colors.</u> ")
#@gui : sep = separator()
#@gui : note = note("<b>Color Space Choice</b> \n\n <i>Keep in mind that you may not necessarily get what you imagine. Just treat those as theme. </i>")
#@gui : Colour Space = choice("RGB", "CMY", "CMYK", "HSI8", "HSL8", "HSV8", "LAB8", "LCH8", "YCbCr", "YCbCr-Glic", "YUV8", "YIQ8", "XYZ8", "Bayer")
#@gui : sep = separator()
#@gui : note = note("<b>Final Color Processing</b> \n\n <i>This refers to the how the colors are going to be processed. If you find that there's too little difference in hues or chroma or luminosity in local areas, this should be on. Sometimes, the result are better without the final processing.</i>")
#@gui : Equalize Filter = bool(0)
#@gui : Psuedo-Coloring = bool(1)
#@gui : Tonality Blend = choice(18,"add","alpha","and","average","blue","burn","darken",
#@gui : "difference","divide","dodge","exclusion","freeze",
#@gui : "grainextract","grainmerge","green","hardlight","hardmix",
#@gui : "hue","interpolation","lighten","lightness","linearburn",
#@gui : "linearlight","luminance","multiply","negation","or",
#@gui : "overlay","pinlight","red","reflect","saturation","screen",
#@gui : "shapeaverage","softburn","softdodge","softlight","stamp",
#@gui : "subtract","value","vividlight","xor")
#@gui : Tonality Blend Opacity = float(1,0,1)
#@gui : sep = separator()
#@gui : note = note("<b>ECB Pattern Key Generator</b>")
#@gui : Double Gradient? = bool(1)
#@gui : Length of Gradient#1 = float(5,0,32)
#@gui : ECB Gradient#1 Angle = float(0,0,360)
#@gui : ECB Inversion#1 = bool(0)
#@gui : Length of Gradient#2 = float(5,0,32)
#@gui : ECB Gradient#2 Angle = float(90,0,360)
#@gui : ECB Inversion#2 = bool(0)
#@gui : Gradient Blend = choice(41,"add","alpha","and","average","blue","burn","darken",
#@gui : "difference","divide","dodge","exclusion","freeze",
#@gui : "grainextract","grainmerge","green","hardlight","hardmix",
#@gui : "hue","interpolation","lighten","lightness","linearburn",
#@gui : "linearlight","luminance","multiply","negation","or",
#@gui : "overlay","pinlight","red","reflect","saturation","screen",
#@gui : "shapeaverage","softburn","softdodge","softlight","stamp",
#@gui : "subtract","value","vividlight","xor")
#@gui : Gradient Blend Opacity = float(1,0,1)
#@gui : sep = separator()
#@gui : note = note("<b>Sharpen Filtering</b>")
#@gui : Sharpening Noise Processing = float(15,0,200)
#@gui : sep = separator()
#@gui : note = note("<b>ECB Image Processing</b>")
#@gui : Transfer Mesh Size for Image (Squared) = int(256,2,256)
#@gui : Image Mesh Contrast = int(75,25,100)
#@gui : Transfer Mesh Size for Gradient (Squared) = int(16,2,256)
#@gui : Gradient Mesh Contrast = int(100,25,100)
#@gui : Double Encryption Effect = bool(1)
#@gui : Inner Blend = choice(41,"add","alpha","and","average","blue","burn","darken",
#@gui : "difference","divide","dodge","exclusion","freeze",
#@gui : "grainextract","grainmerge","green","hardlight","hardmix",
#@gui : "hue","interpolation","lighten","lightness","linearburn",
#@gui : "linearlight","luminance","multiply","negation","or",
#@gui : "overlay","pinlight","red","reflect","saturation","screen",
#@gui : "shapeaverage","softburn","softdodge","softlight","stamp",
#@gui : "subtract","value","vividlight","xor")
#@gui : Inner Blend Opacity = float(1,0,1)
#@gui : Outer Blend = choice(41,"add","alpha","and","average","blue","burn","darken",
#@gui : "difference","divide","dodge","exclusion","freeze",
#@gui : "grainextract","grainmerge","green","hardlight","hardmix",
#@gui : "hue","interpolation","lighten","lightness","linearburn",
#@gui : "linearlight","luminance","multiply","negation","or",
#@gui : "overlay","pinlight","red","reflect","saturation","screen",
#@gui : "shapeaverage","softburn","softdodge","softlight","stamp",
#@gui : "subtract","value","vividlight","xor")
#@gui : Outer Blend Opacity = float(1,0,1)
#@gui : sep = separator()
#@gui : note = note("<b>Self-Image Post-Processing</b> \n\n <i>This invokes a self-blending operation after the main psuedo-ecb has been generated with different blend mode.</i>")
#@gui : Activate Self-Image Post-Processing = bool(1)
#@gui : Equalize ECB Processing = bool(0)
#@gui : Psuedo-Coloring = bool(1)
#@gui : Self-Blend = choice(41,"add","alpha","and","average","blue","burn","darken",
#@gui : "difference","divide","dodge","exclusion","freeze",
#@gui : "grainextract","grainmerge","green","hardlight","hardmix",
#@gui : "hue","interpolation","lighten","lightness","linearburn",
#@gui : "linearlight","luminance","multiply","negation","or",
#@gui : "overlay","pinlight","red","reflect","saturation","screen",
#@gui : "shapeaverage","softburn","softdodge","softlight","stamp",
#@gui : "subtract","value","vividlight","xor")
#@gui : Self-Blend Opacity = float(1,0,1)
#@gui : sep = separator(), Preview type = choice("Full","Forward horizontal","Forward vertical","Backward horizontal","Backward vertical","Duplicate top","Duplicate left","Duplicate bottom","Duplicate right","Duplicate horizontal","Duplicate vertical","Checkered","Checkered inverse"), Preview split = point(50,50,0,0,200,200,200,0,10,0)
#@gui : sep = separator(), note = note("<small>Author : <i>Reptorian</i>      Latest update: <i>2019/01/01</i>.</small>")

pseudo_ecb:
if {$1==1} rgb2cmy
elif {$1==2} rgb2cmyk
elif {$1==3} rgb2hsi8
elif {$1==4} rgb2hsl8
elif {$1==5} rgb2hsv8
elif {$1==6} rgb2lab8
elif {$1==7} rgb2lch8
elif {$1==8} rgb2ycbcr
elif {$1==9} rgb2ycbcrglic
elif {$1==10} rgb2yuv8
elif {$1==11} rgb2yiq8
elif {$1==12} rgb2xyz8
elif {$1==13} rgb2bayer 0
fi
repeat $! l[$>]
repeat {$20+1}
pseudo_ecb_generate ${2-19},${21-29}
done
endl 
if {$1==1} cmy2rgb
elif {$1==2} cmyk2rgb
elif {$1==3} hsi82rgb
elif {$1==4} hsl82rgb
elif {$1==5} hsv82rgb
elif {$1==6} lab82rgb
elif {$1==7} lch82rgb
elif {$1==8} ycbcr2rgb
elif {$1==9} ycbcrglic2rgb
elif {$1==10} yuv82rgb
elif {$1==11} yiq82rgb
elif {$1==12} xyz82rgb
elif {$1==13} rgb2bayer 0,0,0
fi
done

pseudo_ecb_generate:
-m "MergeChoice : $""=_mode" -MergeChoice "add","alpha","and","average","blue","burn","darken","difference","divide","dodge","exclusion","freeze","grainextract","grainmerge","green","hardlight","hardmix","hue","interpolation","lighten","lightness","linearburn","linearlight","luminance","multiply","negation","or","overlay","pinlight","red","reflect","saturation","screen","shapeaverage","softburn","softdodge","softlight","stamp","subtract","value","vividlight","xor","edges","error"
+ac "ecb_gradient_base[0] $6,$7,$8",rgb
if {$2==1} _pseudo_c[1] fi
local[1]
if {$5==1} +ac "ecb_gradient_base[0] $9,$10,$11",rgb
_pseudo_c[1]
blend ${_mode{$12+1}},$13 if {$1==1} equalize fi fi
endlocal
local[0]
sharpen $14
if {$2==1} +_pseudo_c[0]
elif {$2==1} [0] fi
+fx_blend_bomb[0] 0,1,$15,$15,0,0,$16,0,0,0,1,0
blend ${_mode{$19+1}},$20
endlocal
fx_blend_bomb[1] 0,1,$17,$17,0,0,$18,0,0,0,0,0
if {$1==1} equalize[1] fi
blend ${_mode{$21+1}},$22
if {$1==1} +equalize blend ${_mode{$3+1}},$4 fi
if {$1==0} [0] blend ${_mode{$3+1}},$4 fi
if {$23==1} [0] if {$24==1} equalize[1] fi if {$25==1} _pseudo_c[1] fi blend ${_mode{$26+1}},$27
fi

ecb_gradient_base:
f "ang=pi*$2/180;G=x*cos(ang)+y*sin(ang);G%$1" n 0,255
if {$3==1} mul -1 abs fi

_pseudo_c : v - if {s!=1} to_gray. fi {max(1,round(iM,1,1))},1,1,3,u(255) round. map.. . rm.  v +

_pseudo_ecb_preview :
gui_split_preview "pseudo_ecb $*",${-3--1}
1 Like

New idea: swapping the phase and amplitude information of FFTs. It doesn’t seem to be as simple as fft rv ifft though - that only outputs a blank image and a flipped version of the original.

I finally thought of a way to get some fake JIFF glitches. These are nothing like real glitches and I’ll change the way it works quite dramatically.

#@gui Fake JIFF (JPEG) Encoder : fx_jiff, fx_jiff_preview(0)
#@gui : note = note("<small>A fake JIFF encoder.</small>")
#@gui : Quality (%) = int(50,1,100)
#@gui : Encoding = choice("444","442","424","422")
#@gui : sep = separator()
#@gui : note = note("Fake Glitch")
#@gui : Power = float(0,0,5)
#@gui : Colour Distortion = float(1.25,0,10)
#@gui : Max Tile Error Length = int(5,1,10)
#@gui : Persistent Tile Error Power = float(0.25,0,1)
#@gui : sep = separator(), Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal","Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right","Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse"), Preview split = point(50,50,0,0,200,200,200,0,10,0)
#@gui : sep = separator(), note = note("<small>Author: Joan Rake, \'borrowed\' from <i><a href="https://goo.gl/Ryf7Cv">David Tschumperl&#233;</a></i>.      Latest Update: <i>2017/05/07</i>.</small>")
fx_jiff :
glitch=(0.25^(10-$3))*$3/4
cd=$4
te=$5
ste=$6
base642img "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"
base642img "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"
nm[-2,-1] dct,idct
i[Q] (16,11,10,16,24,40,51,61;12,12,14,19,26,58,60,55;14,13,16,24,40,57,69,56;14,17,22,29,51,87,80,62;18,22,37,56,68,109,103,77;24,35,55,64,81,104,113,92;49,64,78,87,103,121,120,101;72,92,95,98,112,100,103,99)
f. "const S = $1<50?5000/$1:200-2*$1; max(1,round((S*i+50)/100,1,-1))"
repeat {$!-3} l[$>,-3--1]
l[0] w,h={[w,h]} r {w+(-w%16)},{h+(-h%16)},1,100%,0,3 rgb2ycbcr s c
if {$2==1} r[-2,-1] 100%,50%,1,1,2 elif {$2==2} r[-2,-1] 50%,100%,1,1,2 elif {$2==3} r[-2,-1] 50%,50%,1,1,2 fi round. endl
repeat 3
[$>]
f[$>] "begin(boundary = 2; res = vector64(); chance = "$glitch"; val = 1; errtile = 0; tt=-1; const tlen = "$te"; const sticky = "$ste"; stuck = 0; cold = "$cd");
if (!(x%8) && !(y%8),
src = crop(x,y,8,8);
for (l = 0, l<8, ++l, for (k = 0, k<8, ++k, off = k + 8*l; u<=chance?(val=u(1-cold,1+cold);tt=u(1,tlen);(u<=sticky?stuck=1:stuck=0)); stuck==0?errtile=0; tt>=1?(errtile=u(0,64)); res[off] = sum(val*src*crop(#"$dct",0,0,(off+errtile)%64,8,8,1))));
draw(#-1,res,x,y,0,0,8,8); tt-=1;
); i"
round.
+r[Q] {$>,w},100%,1,1,0,2 /.. . round.. *[-2,-1]
f. "begin(boundary = 2; res = vector64(); chance = "$glitch"; val = 0; errtile = 0; tt=-1; const tlen = "$te"; const sticky = "$ste"; stuck = 0; cold = "$cd");
if (!(x%8) && !(y%8),
src = crop(x,y,8,8);
for (l = 0, l<8, ++l, for (k = 0, k<8, ++k, off = k + 8*l; u<=chance?(val=u(-cold,cold);tt=u(1,tlen);(u<=sticky?stuck=1:stuck=0)); stuck==0?errtile=0; tt>=1?(errtile=u(0,64)); res[off] = sum(val+src*crop(#"$idct",0,0,(off+errtile)%64,8,8,1))));
draw(#"$>",res,x,y,0,0,8,8); tt-=1;
); i"
rm.
round[$>]
done
l[^3--1] r ${-max_wh},1,1,1 a c ycbcr2rgb round. r $w,$h,1,3,0 endl
endl done
rm[dct,idct,Q]
fx_jiff_preview :
gui_split_preview "fx_jiff $*",${-3--1}

The Fake JIFF filter is slow, but however I like better than the default JPEG filter. However, it doesn’t turn out like the preview which tend to be nicer looking in term of effect. I would love to keep the glitched colors on black and white photos.

Right now I’m not working on glitch filters myself, but I wonder if my idea of multi-channel cloud filter which I"m working on would be interesting for glitches or emulating glitches considering cloud are based on noises. If it seem glitchy, I would post the result here.

Fake JIFF (Expectation Left ; Reality Right) Preview vs Reality -

I’ve tinkered with the algorithm a bit more and it looks fine but one thing I’ve noticed is that where the errors happen, the error shows up in both the luma and the chroma at the same time.

image

I’m going to have to craft a more accurate algorithm which would also have to take care of resizing interpolation issues - so how would resize(...) work in the parser if I’m going to avoid having a lot of tile images to deal with…?

Some progress. Here is a glitch pattern generator where white means begin glitching, black is ‘halt glitching’ and grey means nothing.

gp=0.01
i[G] {w},{h},1,1 f[G] ">begin(chance = "$gp"; tlmax=16; tt=-1; val=0); if (!(x%16) && !(y%16),for (l = 0, l<2, ++l, for (k = 0, k<2, ++k, (u<=chance?(val=1;tt=round(u(1,tlmax))):tt>=0?(val=0;--tt):(val=-1)); j(k*8,l*8)=val)),0);i"
k. n 0,255

Disregard the last edit; it’s because G’MIC doesn’t recognise some of the variables. This command should work in my mind but it doesn’t because it spits *** Error in ./fx_jiff_preview/fx_jiff/*repeat/*local/*repeat/ *** Command 'fill': Unrecognized item '1,1,3,1' in expression '...8,8,1,1,3,1)...'. back at me. It’s to do with resizing the cropped portions of the DCT and IDCT images and it’s having trouble recognising the variables.