Glitch Art Filters?

I forgot to remove a display command in there.

QAM glitch filter is done and updated.

#@gui QAM Glitch: fx_qam_glitch, fx_qam_glitch_preview(0)
#@gui : note = note("Emulates a faulty Quadrature Amplitude Modulator.")
#@gui : sep = separator()
#@gui : note = note("<b>Modulation</b>")
#@gui : 1. Amplitude = float(1,0,10)
#@gui : 2. Period = float(20,0,100)
#@gui : 3. Phase Offset = float(0,-180,180)
#@gui : 4. Angle = float(0,-180,180)
#@gui : 5. Amplitude Offset = float(127.5,0,255)
#@gui : 6. Channel(s) = choice(7,"All","RGBA [all]","RGB [all]","RGB [red]","RGB [green]","RGB [blue]","RGBA [alpha]","Linear RGB [all]","Linear RGB [red]","Linear RGB [green]","Linear RGB [blue]","YCbCr [luminance]","YCbCr [blue-red chrominances]","YCbCr [blue chrominance]","YCbCr [red chrominance]","YCbCr [green chrominance]","Lab [lightness]","Lab [ab-chrominances]","Lab [a-chrominance]","Lab [b-chrominance]","Lch [ch-chrominances]","Lch [c-chrominance]","Lch [h-chrominance]","HSV [hue]","HSV [saturation]","HSV [value]","HSI [intensity]","HSL [lightness]","CMYK [cyan]","CMYK [magenta]","CMYK [yellow]","CMYK [key]")
#@gui : 7. Value Action = choice("None","Cut","Normalize")
#@gui : sep = separator()
#@gui : note = note("<b>Scanlines</b>")
#@gui : 8. Amplitude = float(2,0,255)
#@gui : 9. Bandwidth = float(5,0,20)
#@gui : 10. Shape = choice(0,"Bloc","Triangle","Sine","Sine+","Random")
#@gui : 11. Angle Offset = float(0,-180,180)
#@gui : 12. Offset = float(0,0,500)
#@gui : 13. Blur = float(2,0,10)
#@gui : 14. Amplitude Shift = float(0.5,0,1)
#@gui : 15. Phase Shift = float(0.5,0,1)
#@gui : sep = separator(), 16-18. 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)

fx_qam_glitch :
repeat $! l[$>]
ac "100%,100%,1,1 scanlines. ${8-10},{(90-$4+$11)},$12 b. $13
*. 2 -. $8
f.. "line=i(#-1\,x\,y\,z\,0);ang=$4*pi/180;(((1+line*5*$14/255)*$1)*(i*sin(((x-w/2)*sin(ang)+(y-h/2)*cos(ang))/$2+($3+(line*$2*$15/10)/255*360)*pi/180))+($5*$1))%255"
rm.",$6,$7
endl done
fx_qam_glitch_preview :
gui_split_preview "fx_qam_glitch $*",${-3--1}

image

It doesn’t actually emulate the one like in PDN, but I believe that has the potential to be so much better. And speaking of which, I do think there should be a option to use 2 channels like the PDN version. Like, say you want Red Channel to be Phase 1, and the Blue Channel to be Phase 2, and the result affects one or the other channel or both.

Also, the ECB of yours has certain issues like sometimes, I don’t get as much contrast as the one in my version. And if I disable equalize before the self-blend with xor. Preview time-out. Actually, I’m close enough to implementing your idea to my own version.

Here- This is my own version with Joan’s addition of options

#@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>ECB Pattern Key Generator</b>")
#@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 : Lighting Balance Final ECB Processing = bool(1)
#@gui : Pseudo-Coloring = bool(1)
#@gui : sep = separator()
#@gui : Double Gradient? = bool(1)
#@gui : Length of Gradient#1 = float(3,0,32)
#@gui : ECB Angle#1 = float(0,0,360)
#@gui : ECB Inversion#1 = bool(0)
#@gui : Length of Gradient#2 = float(3,0,32)
#@gui : ECB Angle#2 = 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(5,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 image with ECB filter with different blend mode.</i>")
#@gui : Activate Self-Image Post-Processing = bool(0)
#@gui : Equalize ECB Processing = bool(1)
#@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>2018/12/28</i>.</small>")

pseudo_ecb:
repeat $! l[$>]
repeat {$17+1}
pseudo_ecb_generate $1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$18,$19,$20,$21,$22,$23,$24,$25,$26
done
endl 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] $4,$5,$6",rgb
if {$2==1} pseudo_c[1] fi
local[1]
if {$3==1} +ac "ecb_gradient_base[0] $7,$8,$9",rgb
pseudo_c[1]
blend ${_mode{$10+1}},$11 if {$1==1} equalize fi fi
endlocal
local[0]
sharpen $12
if {$2==1} +pseudo_c[0]
elif {$2==1} [0] fi
+fx_blend_bomb[0] 0,1,$13,$13,0,0,$14,0,0,0,1,0
blend ${_mode{$17+1}},$18
endlocal
fx_blend_bomb[1] 0,1,$15,$15,0,0,$16,0,0,0,0,0
if {$1==1} equalize[1] fi
blend ${_mode{$19+1}},$20
if {$1==1} +equalize blend interpolation fi
if {$21==1} [0] if {$22==1} equalize[1] fi if {$23==1} pseudo_c[1] fi blend ${_mode{$24+1}},$25
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_ecb_preview :
gui_split_preview "pseudo_ecb $*",${-3--1}

A example of my own version of ECB

image

image

1 Like

Your suggestion for the QAM filter sounds like it would make an extremely messy result. I’m not sure quite how it would work but I really like the sound of it. I’ve updated it and included a patched scanlines command because the offset wasn’t working in the x direction. The rotation directions for the offsets are now consistent too.

#@gui QAM Glitch: fx_qam_glitch, fx_qam_glitch_preview(0)
#@gui : note = note("Emulates a faulty Quadrature Amplitude Modulator.")
#@gui : sep = separator()
#@gui : note = note("<b>Modulation</b>")
#@gui : 1. Amplitude = float(1,0,10)
#@gui : 2. Period = float(20,0,100)
#@gui : 3. Phase Offset = float(0,-180,180)
#@gui : 4. Angle = float(0,-180,180)
#@gui : 5. Amplitude Offset = float(127.5,0,255)
#@gui : 6. Channel(s) = choice(2,"All","RGBA [all]","RGB [all]","RGB [red]","RGB [green]","RGB [blue]","RGBA [alpha]","Linear RGB [all]","Linear RGB [red]","Linear RGB [green]","Linear RGB [blue]","YCbCr [luminance]","YCbCr [blue-red chrominances]","YCbCr [blue chrominance]","YCbCr [red chrominance]","YCbCr [green chrominance]","Lab [lightness]","Lab [ab-chrominances]","Lab [a-chrominance]","Lab [b-chrominance]","Lch [ch-chrominances]","Lch [c-chrominance]","Lch [h-chrominance]","HSV [hue]","HSV [saturation]","HSV [value]","HSI [intensity]","HSL [lightness]","CMYK [cyan]","CMYK [magenta]","CMYK [yellow]","CMYK [key]")
#@gui : 7. Value Action = choice("None","Cut","Normalize")
#@gui : sep = separator()
#@gui : note = note("<b>Scanlines</b>")
#@gui : 8. Amplitude = float(2,0,255)
#@gui : 9. Bandwidth = float(5,0,20)
#@gui : 10. Shape = choice(0,"Bloc","Triangle","Sine","Sine+","Random")
#@gui : 11. Angle Offset = float(0,-180,180)
#@gui : 12. Offset = float(0,0,500)
#@gui : 13. Blur = float(2,0,10)
#@gui : 14. Amplitude Shift = float(0.5,0,1)
#@gui : 15. Phase Shift = float(0.5,0,1)
#@gui : sep = separator(), 16-18. 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)

_scanlines : skip ${1=60},${2=2},${3=0},${4=0},${5=0}
e[^-1] "Apply scanlines effect on image$?, with amplitude $1, bandwidth $2, shape $3, angle $4 deg. and offset $5."
v -
theta={$4*pi/180} C={cos($theta)} S={-sin($theta)}
repeat $! l[$>]
100%,100%,1,1,"x" -. {w/2-$5} 100%,100%,1,1,'y'
-. {h/2-$5} *.. $S *. $C +[-2,-1]
_ripple$3. $1,$2
n. {-$1},$1
+ cut 0,255
endl done v +

fx_qam_glitch :
repeat $! l[$>]
ac "100%,100%,1,1 _scanlines. ${8-10},{(90+$4+$11)},$12 b. $13
*. 2 -. $8
f.. "line=i(#-1\,x\,y\,z\,0);ang=(90+$4)*pi/180;(i+(((1+line*5*$14/255)*$1)*(i*sin(((x-w/2)*cos(ang)+(y-h/2)*sin(ang))/$2+($3+(line*$2*$15/10)/255*360)*pi/180))+($5*($1)-($1*i/2))))%255"
rm.",$6,$7
endl done
fx_qam_glitch_preview :
gui_split_preview "fx_qam_glitch $*",${-3--1}

Love the collab. Keep up the good work! :slight_smile:

Found an annoying pattern-destroying snag in the scanlines filter when the angle is cranked up high (this should be 270 degrees according to the plugin GUI but the actual scanlines are slightly off):

image

If this could be included as a legacy if there’s a fix, that would be nice to have to screw things up.

Hmm, I think how PDN QAM Filter works is that variables are swapped for another channels. So they get their own signal on those channel. This could even be extended to 3 Channels. I may explore this later on.

R-G ; G-B ; B-R . That means 3 instances of 2 Channels QAM filter for 3 channels. One may have to define a starting point though here.

For CMYK

C-M; C-Y ; C-K. 12 instances of 2 Channels QAM filter. 4 instances of 3 Channels QAM filter. Not sure if it’ll be worth it.

There is a CLI suggestion from Afre in my filter thread to make those easier.

Hi all. Polynomial here! I’m glad you’re all having fun with the plugin.

The QAM filter is a bit of a weird one - it’s actually meant to convert the image data into a stream of signal samples which are then modulated with Quadrature Amplitude Modulation (QAM), reminiscent of how the UV signal component was transmitted in PAL/NTSC video. It then adds a bunch of noise and purposefully messes up some of the decoding parameters in order to create interesting results. Unfortunately I never really got it working how I wanted for a number of reasons:

  1. The amount of data you need to properly encode the composite signal is quite high - you need a 12MHz sample rate at minimum to keep everything within the Nyquist range for the 6MHz colour burst, but for a bunch of reasons you end up needing an even higher sample rate, and for higher resolution images that quickly balloons into GB of sample data and a long processing time.
  2. Doing proper demodulation is non-trivial because you need to implement a PLL for recovering the colourburst carrier. You can cheat here and just keep the carrier osciallator running and reset the phase on each line, but a lot of the more interesting decoding failures come from the carrier recovery. I wasn’t good enough at DSP back then to make it work properly.
  3. I couldn’t get the FM demodulation for the colourburst working properly. I can’t remember what the problem was - I think it just gave garbage data.

In the end what you get in the plugin is a sort of faux modulation-demodulation error effect instead of what I originally intended. Oh well.

If you’ve got any questions about how any of the other effects work (or at least how they’re meant to) then feel free to ask.

2 Likes

I knew something was up with how quickly I put it together! The next step for this faux QAM plugin is to add more colour spaces by using something other than the ac command which is a bit lacking in terms of what colour spaces there are.

One thing I’ve been looking at is how to do a JIFF glitch. We already have a ‘JPEG artefacts’ emulator in G’MIC built by David himself and since to my knowledge it’s not possible to directly manipulate the image data (G’MIC scripts can only deal with pixel values instead), it’ll be a challenge to somehow reimplement the distortion let alone the entire encoding algorithm with all its options.

Updated the QAM filter again. It supports every colourspace that G’MIC supports apart from CMYK (which has 4 channels instead of 3).

#@gui Faux-QAM Glitch: fx_qam_glitch, fx_qam_glitch_preview(0)
#@gui : note = note("Tries to emulate the effect of a faulty Quadrature Amplitude Modulator.")
#@gui : sep = separator()
#@gui : note = note("<b>Channel Modulation</b>")
#@gui : 1. Amplitude = float(2,0,10)
#@gui : 2. Period = float(20,0,100)
#@gui : 3. Phase Offset = float(0,-180,180)
#@gui : 4. Angle = float(0,-180,180)
#@gui : 5. Amplitude Offset = float(1,-10,10)
#@gui : 6. Wave Offset = float(127.5,0,255)
#@gui : 7. Colour Space = choice("RGBA","sRGBA","CMYA","HSVA8","HSVA","HSLA8","HSLA","HSIA8","HSIA","LCHA8","LCHA","LabA8","LabA","YCbCrA","YCbCrAGLIC","YIQA8","YIQA","YUVA8","YUVA","BayerA","HCYA","XYZA8","XYZA")
#@gui : 8. Channel 0 = bool(1)
#@gui : 9. Channel 1 = bool(1)
#@gui : 10. Channel 2 = bool(1)
#@gui : 11. Alpha = bool(0)
#@gui : 12. Glitch Negation = bool(0)
#@gui : sep = separator()
#@gui : note = note("<b>Scanlines</b>")
#@gui : 13. Amplitude = float(20,0,255)
#@gui : 14. Bandwidth = float(5,0,20)
#@gui : 15. Shape = choice(0,"Bloc","Triangle","Sine","Sine+","Random")
#@gui : 16. Angle Offset = float(0,-180,180)
#@gui : 17. Offset = float(0,0,500)
#@gui : 18. Blur = float(2,0,10)
#@gui : 19. Amplitude Modulation = float(0.6,0,1)
#@gui : 20. Phase Modulation = float(0.05,0,1)
#@gui : sep = separator(), 21-23. 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)

_scanlines : skip ${1=60},${2=2},${3=0},${4=0},${5=0}
v -
theta={$4*pi/180} C={cos($theta)} S={-sin($theta)}
repeat $! l[$>]
100%,100%,1,1,"x" -. {w/2-$5} 100%,100%,1,1,'y'
-. {h/2-$5} *.. $S *. $C +[-2,-1]
_ripple$3. $1,$2
n. {-$1},$1
+ cut 0,255
endl done v +

_qam_glitch :

100%,100%,1,1 _scanlines. ${7-9},{(90+$4+$10)},$11 b. $12
*. 2 -. $7
f.. "line=i(#-1\,x\,y\,z\,0);ang=(90+$4)*pi/180;(i+(((1+line*5*$13/255)*($1*i/255+$5))*(i*sin(((x-w/2)*cos(ang)+(y-h/2)*sin(ang))/$2+($3+(line*$2*$14/10)/255*360)*pi/180))+($6*($1)-($1*i/2)))-i/255)%255"
rm.

fx_qam_glitch :
repeat $! l[$>]
to_rgba
if {$7>=2} cs={$7+1} else cs=$7 fi
if $12 negate fi
csswap 0,1,0,$cs
counter=0
if $8 sh[0] 0 fi
if $9 sh[0] 1 fi
if $10 sh[0] 2 fi
if $11 sh[0] 3 fi
repeat {$!-1} l[{$>+1}]
_qam_glitch ${1-6},${13-20}
endl done
rm[^0]
csswap $cs,1,0,0
if $12 negate fi
endl done
fx_qam_glitch_preview :
gui_split_preview "fx_qam_glitch $*",${-3--1}

1 run:

image

2 runs:

image

Let’s amend that knowledge then :smiley:

gmic raw:inputimage.jpg,uchar f "(i+(u>0.9999))%256" o raw:outputimage.jpg,uchar
1 Like

That should work for the CLI version but would that allow one to chop and change the bits within the plugin? The classic method to destroy a JIFF is to open it with a text editor (hex or otherwise) and muck around with a few things here and there.

Hmm in short I’d say no.

If you’re talking about treating the currently loaded image as a particular file format, you’d have to do something ugly like output as a file and re-input. That then depends on which libraries were linked building G’MIC (e.g. libjpeg).

You could add a file selector and do various things that way without being able to preview it, but imo that’s a bit dangerous and in the end not much different than a hex editor anyway.

Just tried the QAM glitch thing. I do wish that each channels has option to use blending modes though.

image

@Polynomial I do have a question about Low Pass. Is it based on FFT Low-Pass filtering? The PDN one I seen seem to add a motion blur on low signal. Where did that come from?

@Joan_Rake1 The only missing feasible filter to my knowledge is Low Pass, and Spiral Transform. Raw File Import, True Glitch are ones that I’m not too sure about. The others I omitted are those I haven’t checked if they are on G’MIC for now.

We already have an FFT-based bandpass filter but it’s a near-rectangular one rather than something like a Butterworth filter. It should still be quite easy to do because it’s as simple as sticking a radial gradient with multiply as the blend mode on the result of an FFT before an inverse FFT.

I have only added color space conversion on the ECB filter I was working on. I don’t see the point of separating channels though since this is meant to emulate ECB.

#@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", "HSI", "HSL", "HSV", "LAB", "LCH", "YCbCr", "YCbCr-Glic", "YUV", "YIQ", "XYZ", "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 : Lighting Balance Final ECB Processing = bool(1)
#@gui : Psuedo-Coloring = bool(1)
#@gui : sep = separator()
#@gui : note = note("<b>ECB Pattern Key Generator</b>")
#@gui : Double Gradient? = bool(1)
#@gui : Length of Gradient#1 = int(3,0,32)
#@gui : ECB Angle#1 = float(0,0,360)
#@gui : ECB Inversion#1 = bool(0)
#@gui : Length of Gradient#2 = int(3,0,32)
#@gui : ECB Angle#2 = 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(5,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(0)
#@gui : Equalize ECB Processing = bool(1)
#@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>2018/12/30</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 {$18+1}
pseudo_ecb_generate $2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$19,$20,$21,$22,$23,$24,$25,$26,$27
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] $4,$5,$6",rgb
if {$2==1} pseudo_c[1] fi
local[1]
if {$3==1} +ac "ecb_gradient_base[0] $7,$8,$9",rgb
pseudo_c[1]
blend ${_mode{$10+1}},$11 if {$1==1} equalize fi fi
endlocal
local[0]
sharpen $12
if {$2==1} +pseudo_c[0]
elif {$2==1} [0] fi
+fx_blend_bomb[0] 0,1,$13,$13,0,0,$14,0,0,0,1,0
blend ${_mode{$17+1}},$18
endlocal
fx_blend_bomb[1] 0,1,$15,$15,0,0,$16,0,0,0,0,0
if {$1==1} equalize[1] fi
blend ${_mode{$19+1}},$20
if {$1==1} +equalize blend interpolation fi
if {$21==1} [0] if {$22==1} equalize[1] fi if {$23==1} pseudo_c[1] fi blend ${_mode{$24+1}},$25
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_ecb_preview :
gui_split_preview "pseudo_ecb $*",${-3--1}

Here’s a stab at making a Butterworth-ish bandpass. I haven’t bothered with the phase shifts that come with these filters but those could probably be implemented by screwing with the phase part of the FFT result.

#@gui Butterworth Bandpass: fx_butterworth_bp, fx_butterworth_bp_preview(0)
#@gui : note = note("Lowpass and highpass Butterworth filters.")
#@gui : sep = separator()
#@gui : LP Frequency = float(3,0,12)
#@gui : LP Order = float(2,0,10)
#@gui : HP Frequency = float(3,0,12)
#@gui : HP Order = 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))^0.5);func"
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^$3))*scale)^($4*2)^-1))^0.5);func*i"
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 min={im} n {$min},{$gain} + {abs($min/2)} fi
endl
if {!$6} a c fi
endl done

fx_butterworth_bp_preview :
fx_butterworth_bp $*

Unknown command or filename ‘fx_butterworth_bandpass’
Krita 4.2 - Windows x64


Other than that, I added ‘8’ to some of the colors in my ECB filter.

Fixed that missing command issue. I’ve also patched up a few things with your ECB filter, most notably the pseudo_c command which breaks every time the image that’s passed to it has a very low maximum value.

#@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>ECB Pattern Key Generator</b>")
#@gui : 1. Colour Space = choice("RGB","sRGB","CMY","CMYK","HSI8","HSL8","HSV8","Lab8","LCH8","YCbCr","YCbCrGLIC","YUV8","YIQ8","XYZ8","Bayer")
#@gui : 2. Double Gradient = bool(0)
#@gui : 3. Length of Gradient #1 = int(5,1,32)
#@gui : 4. ECB Angle #1 = float(135,0,360)
#@gui : 5. ECB Inversion#1 = bool(0)
#@gui : 6. Length of Gradient #2 = int(5,1,32)
#@gui : 7. ECB Angle #2 = float(90,0,360)
#@gui : 8. ECB Inversion #2 = bool(0)
#@gui : 9. 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 : 10. Gradient Blend Opacity = float(1,0,1)
#@gui : sep = separator()
#@gui : note = note("<b>Sharpen Filtering</b>")
#@gui : 11. Sharpening Noise Processing = float(15,0,200)
#@gui : sep = separator()
#@gui : note = note("<b>ECB Image Processing</b>")
#@gui : 12. Transfer Mesh Size for Image (Squared) = int(256,2,256)
#@gui : 13. Image Mesh Contrast = float(100,0,100)
#@gui : 14. Transfer Mesh Size for Gradient (Squared) = int(16,2,256)
#@gui : 15. Gradient Mesh Contrast = float(100,0,100)
#@gui : 16. Double Encryption Effect = bool(0)
#@gui : 17. 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 : 18. Inner Blend Opacity = float(1,0,1)
#@gui : 19. 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 : 20. Outer Blend Opacity = float(1,0,1)
#@gui : 21. Self-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 : 22. Self-Blend Opacity = float(1,0,1)
#@gui : 23. Pseudocolouring = bool(1)
#@gui : 24. Equalise Copy Before Self-Blend = bool(1)
#@gui : sep = separator(), 25-27. 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>2018/12/28</i>.</small>")

_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:
repeat $! l[$>]
if {$1==1} rgb2srgb
elif {$1==2} rgb2cmy
elif {$1==3} rgb2cmyk
elif {$1==4} rgb2hsi8
elif {$1==5} rgb2hsl8
elif {$1==6} rgb2hsv8
elif {$1==7} rgb2lab8
elif {$1==8} rgb2lch8
elif {$1==9} rgb2ycbcr
elif {$1==10} rgb2ycbcrglic
elif {$1==11} rgb2yuv8
elif {$1==12} rgb2yiq8
elif {$1==13} rgb2xyz8
elif {$1==14} rgb2bayer 0
fi
repeat {$16+1}
pseudo_ecb_generate ${2-15},${17-24}
done
if {$1==1} srgb2rgb
elif {$1==2} cmy2rgb
elif {$1==3} cmyk2rgb
elif {$1==4} hsi82rgb
elif {$1==5} hsl82rgb
elif {$1==6} hsv82rgb
elif {$1==7} lab82rgb
elif {$1==8} lch82rgb
elif {$1==9} ycbcr2rgb
elif {$1==10} ycbcrglic2rgb
elif {$1==11} yuv82rgb
elif {$1==12} yiq82rgb
elif {$1==13} xyz82rgb
elif {$1==14} bayer2rgb 0,0,0
fi
endl done

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_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] ${2-4}",rgb
if $20 _pseudo_c[1] fi
local[1]
if {$1==1} +ac "ecb_gradient_base[0] ${5-7}",rgb
if $20 _pseudo_c[1] fi
blend ${_mode{$8+1}},$9 equalize fi
endlocal
local[0]
sharpen $10
if $20 +_pseudo_c[0] fi
+fx_blend_bomb[0] 0,1,$11,$11,0,2,$12,0,0,0,1,0
blend ${_mode{$15+1}},$16
endlocal
fx_blend_bomb[1] 0,1,$13,$13,0,2,$14,0,0,0,0,0
if $22 equalize[1] fi
blend ${_mode{$17+1}},$18
if $22 +equalize else [0] fi
blend ${_mode{$19+1}},$20

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

Actually, here’s the comparison of pictures. A little different from default though.

Double Encryption

Joan’s ECB result
image

Reptorian’s ECB result
image

PDN Codebook result
image

Something’s a little different here. Other than bugs, self-blending option is the only thing that’s pretty much different from Joan and my own.