BandsEffectLib — Horizontal Bands Effect

Adds GPU-accelerated horizontal bands (scanlines) over any visual control, producing the look of a CRT monitor, VHS playback, or retro television. The effect wraps FireMonkey’s TBandsEffect with two simple properties: density (how many lines) and intensity (how visible they are). Perfect for vintage aesthetics, retro game overlays, and nostalgic photo filters. 14 functions.

CategoryCountDescription
Error Handling4bands_error, errormsg$, strerror$, clearerror
Creation & Destruction2bands# (create), bands_free (destroy)
Band Properties4density, intensity (get/set)
Effect Control4enabled, trigger (get/set)
ⓘ Meta: This documentation page itself uses a CSS scanline overlay — you’re looking through bands right now! The BandsEffectLib applies the same concept as a GPU filter on any Plan9Basic visual control.

Cross-Platform Support

PlatformStatusNotes
Windows✅ Full SupportGPU-accelerated via Direct2D
Linux✅ Full SupportSoftware rendering fallback
Android✅ Full SupportGPU-accelerated

Error Handling

All functions set an error code on failure. Check with bands_error() after operations. Error code 0 means success.

FunctionSignatureDescription
bands_error()bands_error@Returns last error code (0 = no error)
bands_errormsg$()bands_errormsg$@Returns last error message as string
bands_strerror$(code)bands_strerror$@nConverts an error code to descriptive text
bands_clearerror()bands_clearerror@Clears the error state

Error Codes

CodeConstantMeaning
0ERR_NONENo error
1ERR_NIL_EFFECTEffect pointer is nil
2ERR_INVALID_EFFECTPointer is not a valid TBandsEffect
3ERR_INVALID_VALUEProperty value out of range
4ERR_NIL_PARENTParent control pointer is nil
5ERR_INVALID_PARENTPointer is not a valid TFmxObject

Creation & Destruction

FunctionSignatureDescription
bands#(parent#)bands#@#Creates a bands effect attached to the given control. Returns the effect pointer.
bands_free(effect#)bands_free@#Destroys the effect and removes it from the parent control.

The parent# can be any visual control. The effect is applied immediately with default values (density 50, intensity 0.5).

╯ create-effect.bas
' Create bands effect on an image
let bnd# = bands#(img#)

' Later, remove the effect
bands_free(bnd#)

Band Properties

Density

Controls the number of horizontal bands drawn across the control. Higher values create finer, closer-together scanlines. Default is 50.

FunctionSignatureDescription
bands_density#(effect#, value)bands_density#@#nSets number of bands
bands_density(effect#)bands_density@#Gets current density
DensityVisual EffectUse Case
10–25Wide, clearly visible stripesDramatic retro overlay, VHS glitch art
30–60Medium scanlines (default range)Classic CRT monitor look
75–120Fine, subtle linesHigh-resolution CRT, subtle vintage
150+Very fine, almost like a textureSubtle film grain alternative

Intensity

Controls the visibility/opacity of the bands. A value of 0.0 makes them invisible; 1.0 makes them fully opaque (solid black stripes). Default is 0.5.

FunctionSignatureDescription
bands_intensity#(effect#, value)bands_intensity#@#nSets intensity (0.0–1.0)
bands_intensity(effect#)bands_intensity@#Gets current intensity
IntensityVisual Effect
0.0Invisible — no bands visible
0.1–0.3Subtle — barely visible overlay, good for photos
0.3–0.5Moderate — clearly visible CRT look (default range)
0.5–0.8Strong — prominent dark bands
1.0Maximum — solid black stripes alternating with image
╯ band-properties.bas
' CRT monitor look
bands_density#(bnd#, 75)
bands_intensity#(bnd#, 0.3)

' Heavy VHS distortion look
bands_density#(bnd#, 15)
bands_intensity#(bnd#, 0.7)

' Subtle film grain alternative
bands_density#(bnd#, 150)
bands_intensity#(bnd#, 0.15)

Effect Control

Enabled

Toggles the effect on or off without destroying it. When disabled, the control renders as if the effect does not exist.

FunctionSignatureDescription
bands_enabled#(effect#, value)bands_enabled#@#nEnables (1) or disables (0) the effect
bands_enabled(effect#)bands_enabled@#Gets enabled state (1 = on, 0 = off)

Trigger

The trigger property is a string used by FireMonkey’s animation system. Primarily used for integration with animation components.

FunctionSignatureDescription
bands_trigger#(effect#, trigger$)bands_trigger#@#$Sets trigger string
bands_trigger$(effect#)bands_trigger$@#Gets current trigger string

Complete Examples

CRT Scanline Effect

Applies a classic CRT monitor scanline overlay to an image.

╯ bands-crt.bas
let frm# = Pointer#(0)
let img# = Pointer#(0)
let bnd# = Pointer#(0)

frm# = form#("Scanline Effect", 400, 350)

img# = image#(frm#)
image_bounds#(img#, 100, 30, 200, 150)
image_load#(img#, "https://picsum.photos/200/150")

' Create bands effect - CRT style
bnd# = bands#(img#)
bands_density#(bnd#, 75)
bands_intensity#(bnd#, 0.3)

form_show(frm#)

Interactive Density & Intensity Controls

Two trackbars for real-time adjustment of density and intensity.

╯ bands-interactive.bas
let frm# = Pointer#(0)
let img# = Pointer#(0)
let bnd# = Pointer#(0)
let trkDens# = Pointer#(0)
let trkInt# = Pointer#(0)
let lblDens# = Pointer#(0)
let lblInt# = Pointer#(0)

frm# = form#("Bands Control", 450, 420)

img# = image#(frm#)
image_bounds#(img#, 125, 20, 200, 150)
image_load#(img#, "https://picsum.photos/200/150")

bnd# = bands#(img#)
bands_density#(bnd#, 50)
bands_intensity#(bnd#, 0.5)

' Density slider
lblDens# = label#(frm#, "Density: 50", 50, 190)
trkDens# = trackbar#(frm#)
trackbar_bounds#(trkDens#, 50, 220, 350, 30)
trackbar_max#(trkDens#, 200)
trackbar_value#(trkDens#, 50)
trackbar_onchange#(trkDens#, "OnDensChange")

' Intensity slider
lblInt# = label#(frm#, "Intensity: 0.50", 50, 270)
trkInt# = trackbar#(frm#)
trackbar_bounds#(trkInt#, 50, 300, 350, 30)
trackbar_max#(trkInt#, 100)
trackbar_value#(trkInt#, 50)
trackbar_onchange#(trkInt#, "OnIntChange")

form_show(frm#)

function OnDensChange(sender#) local d
  let d = trackbar_value(trkDens#)
  bands_density#(bnd#, d)
  label_text#(lblDens#, "Density: " + str$(d))
endfunction

function OnIntChange(sender#) local i
  let i = trackbar_value(trkInt#) / 100
  bands_intensity#(bnd#, i)
  label_text#(lblInt#, "Intensity: " + stri$(i, 2))
endfunction

Toggle Effect On/Off

A button toggles the bands effect without destroying it.

╯ bands-toggle.bas
let frm# = Pointer#(0)
let img# = Pointer#(0)
let bnd# = Pointer#(0)
let btn# = Pointer#(0)
let isOn = 1

frm# = form#("Toggle Bands", 400, 300)

img# = image#(frm#)
image_bounds#(img#, 100, 30, 200, 150)
image_load#(img#, "https://picsum.photos/200/150")

bnd# = bands#(img#)
bands_density#(bnd#, 100)
bands_intensity#(bnd#, 0.4)

btn# = button#(frm#, "Disable Effect")
button_bounds#(btn#, 140, 210, 120, 30)
button_onclick#(btn#, "Toggle")

form_show(frm#)

function Toggle(sender#)
  if isOn = 1 then
    bands_enabled#(bnd#, 0)
    isOn = 0
    button_text#(btn#, "Enable Effect")
  else
    bands_enabled#(bnd#, 1)
    isOn = 1
    button_text#(btn#, "Disable Effect")
  endif
endfunction

Best Practices

PracticeWhy
Use density 50–100 with intensity 0.2–0.4 for CRT lookThe classic scanline sweet spot — visible but not overwhelming
Use low density (10–20) with high intensity for VHS glitchCreates bold, dramatic horizontal stripes for distressed effects
Use high density (150+) with low intensity for subtle textureWorks as a film-grain alternative without masking the image
Combine with SepiaEffectLib for vintage photosSepia + scanlines = convincing old TV or vintage camera look
Combine with MonochromeEffectLib for B&W CRTMonochrome + bands = classic black-and-white television
Use bands_enabled# to toggle instead of bands_freeFaster than destroying and recreating for on/off scenarios
Animate intensity with FloatAnimationLibPulsating intensity creates a “signal interference” effect
Scale density relative to control heightA 300px image needs more bands than a 100px image for the same visual density

Quick Reference

FunctionSignatureDescription
ERROR HANDLING
bands_error()bands_error@Last error code
bands_errormsg$()bands_errormsg$@Last error message
bands_strerror$(code)bands_strerror$@nError code to text
bands_clearerror()bands_clearerror@Clear error state
CREATION & DESTRUCTION
bands#(parent#)bands#@#Create effect on control
bands_free(effect#)bands_free@#Destroy effect
BAND PROPERTIES
bands_density#(effect#, val)bands_density#@#nSet band count
bands_density(effect#)bands_density@#Get band count
bands_intensity#(effect#, val)bands_intensity#@#nSet intensity (0.0–1.0)
bands_intensity(effect#)bands_intensity@#Get intensity
EFFECT CONTROL
bands_enabled#(effect#, val)bands_enabled#@#nEnable (1) / disable (0)
bands_enabled(effect#)bands_enabled@#Get enabled state
bands_trigger#(effect#, str$)bands_trigger#@#$Set trigger string
bands_trigger$(effect#)bands_trigger$@#Get trigger string

14 functions. Part of the Plan9Basic visual effects library system.

See Also

  • PixelateEffectLib — Pixelation effect for retro 8-bit look
  • SepiaEffectLib — Sepia tone for vintage photo style
  • MonochromeEffectLib — Monochrome/grayscale conversion
  • ToonEffectLib — Cartoon/posterize effect
  • FloatAnimationLib — Animate intensity for pulsating scanline effects