vango
May 29, 2026 · View on GitHub
a collection of various image manipulation effects named after Vincent van Gogh
A compact, dependency-free image processing toolkit implemented as one Go source file (vango.go).
It provides many common image operations, a fluent Pipeline API (with fusion of per-pixel ops),
context-aware parallel execution, and a small CLI in cmd/main.go.
It supports JPEG, PNG, GIF, BMP, and TIFF formats via the Go standard library.
Quick start
- Run the unit/examples and build locally:
# run tests (example tests + unit tests)
go test ./...
# build the CLI tool
go build -o vango-cli ./cmd
- Use the CLI to process an image (zsh example):
# basic CLI usage (use ; or , as separators)
./vango-cli -in demo.jpg -out demo.out.jpg -cmds "blur 1.2; contrast 1.1; sepia 0.2"
# additional effects
./vango-cli -in demo.jpg -out demo.gray_vig.jpg -cmds "grayscale, vignette 0.6, skew 0.08 0.0, resize_nearest 1200 800"
# auto modes (auto_color already includes whitebalance + auto contrast/brightness/vibrance)
./vango-cli -in demo.jpg -out demo.auto.jpg -cmds "auto_color"
# full auto enhance (whitebalance + noise reduction + auto contrast/brightness/vibrance)
./vango-cli -in demo.jpg -out demo.auto_full.jpg -cmds "auto_full"
# smart one-shot enhancement and exposure/tone automation
./vango-cli -in demo.jpg -out demo.smart.jpg -cmds "smart_enhance"
./vango-cli -in demo.jpg -out demo.scene.jpg -cmds "auto_scene"
./vango-cli -in demo.jpg -out demo.tone.jpg -cmds "auto_tone"
./vango-cli -in demo.jpg -out demo.exposure.jpg -cmds "auto_exposure"
# modern color looks (direct aliases or generic filter command)
./vango-cli -in demo.jpg -out demo.cinematic.jpg -cmds "cinematic 0.85"
./vango-cli -in demo.jpg -out demo.noir.jpg -cmds "filter noir 1.0"
./vango-cli -in demo.jpg -out demo.aurora.jpg -cmds "aurora 0.8"
./vango-cli -in demo.jpg -out demo.midnight.jpg -cmds "filter midnight 0.75"
# creative effects
./vango-cli -in demo.jpg -out demo.dreamscape.jpg -cmds "dreamscape 4 0.75"
./vango-cli -in demo.jpg -out demo.vhs.jpg -cmds "vhs 0.65"
./vango-cli -in demo.jpg -out demo.lightleak.jpg -cmds "light_leak 0.12 0.18 0.65 0.75"
./vango-cli -in demo.jpg -out demo.kaleidoscope.jpg -cmds "kaleidoscope 8"
# noise reduction (median filter, radius=1 gives 3×3 window, radius=2 gives 5×5, etc.)
./vango-cli -in demo.jpg -out demo.denoised.jpg -cmds "noise_reduction 1"
# align/collage two images side by side (horizontal or vertical)
./vango-cli -in demo.jpg -out demo.collage.jpg -cmds "collage other.jpg horizontal"
./vango-cli -in demo.jpg -out demo.collage_v.jpg -cmds "collage other.jpg vertical"
# edge detection + smart crop + watermark
./vango-cli -in demo.jpg -out demo.edge.jpg -cmds "edge; smartcrop 1200 800; watermark logo.png 20 20 0.5"
# pro adjustments
./vango-cli -in demo.jpg -out demo.adj.jpg -cmds "vibrance 0.8; dehaze 0.5; shadow_highlight 0.4 0.3"
# distortion effects
./vango-cli -in demo.jpg -out demo.twirl.jpg -cmds "twirl 1.2"
./vango-cli -in demo.jpg -out demo.wave.jpg -cmds "wave 10 8 60 50"
./vango-cli -in demo.jpg -out demo.spherize.jpg -cmds "spherize 0.7"
./vango-cli -in demo.jpg -out demo.ripple.jpg -cmds "ripple 12 45"
./vango-cli -in demo.jpg -out demo.pinch.jpg -cmds "pinch 0.6"
./vango-cli -in demo.jpg -out demo.polar.jpg -cmds "polar_coordinates to"
# dodge / burn
./vango-cli -in demo.jpg -out demo.dodge.jpg -cmds "dodge 0.4 midtones"
./vango-cli -in demo.jpg -out demo.burn.jpg -cmds "burn 0.4 shadows"
# tone curves (control points as input,output pairs in 0..1 range)
./vango-cli -in demo.jpg -out demo.curves.jpg -cmds "curves 0 0 0.5 0.65 1 1"
# gradient map (list of RRGGBB,position stops)
./vango-cli -in demo.jpg -out demo.gradmap.jpg -cmds "gradient_map 000000,0 FF6600,0.5 FFFFFF,1"
# per-channel curves (r:in,out,in,out... g:... b:...)
./vango-cli -in demo.jpg -out demo.chan_curves.jpg -cmds "channel_curves r:0,0,0.5,0.7,1,1 g:0,0,1,1 b:0,0,0.5,0.3,1,1"
# tint overlay (hex color + opacity 0..1)
./vango-cli -in demo.jpg -out demo.tinted.jpg -cmds "tint FF8800 0.25"
# content-aware seam carving resize
./vango-cli -in demo.jpg -out demo.seamcarve.jpg -cmds "seam_carve 800 600"
# perspective transform (4 source corners then output size)
./vango-cli -in demo.jpg -out demo.persp.jpg -cmds "perspective 50 30 750 10 780 570 20 590 800 600"
# ImageMagick-inspired effects
./vango-cli -in demo.jpg -out demo.charcoal.jpg -cmds "charcoal 2 1.0"
./vango-cli -in demo.jpg -out demo.sketch.jpg -cmds "sketch 1.5"
./vango-cli -in demo.jpg -out demo.normalize.jpg -cmds "normalize"
./vango-cli -in demo.jpg -out demo.sigmoidal.jpg -cmds "sigmoidal_contrast sharpen 6 0.5"
./vango-cli -in demo.jpg -out demo.kuwahara.jpg -cmds "kuwahara 3"
./vango-cli -in demo.jpg -out demo.adaptive_blur.jpg -cmds "adaptive_blur 1.5"
./vango-cli -in demo.jpg -out demo.adaptive_sharpen.jpg -cmds "adaptive_sharpen 1.5"
./vango-cli -in demo.jpg -out demo.mean_shift.jpg -cmds "mean_shift 5 0.15"
./vango-cli -in demo.jpg -out demo.roll.jpg -cmds "roll 100 50"
./vango-cli -in demo.jpg -out demo.spread.jpg -cmds "spread 4"
./vango-cli -in demo.jpg -out demo.transpose.jpg -cmds "transpose"
./vango-cli -in demo.jpg -out demo.transverse.jpg -cmds "transverse"
./vango-cli -in demo.jpg -out demo.shave.jpg -cmds "shave 20 15"
./vango-cli -in demo.jpg -out demo.extent.jpg -cmds "extent 1400 1000 center FFFFFF"
./vango-cli -in demo.jpg -out demo.ordered_dither.jpg -cmds "ordered_dither 4"
./vango-cli -in demo.jpg -out demo.selective_blur.jpg -cmds "selective_blur 2.0 0.1"
./vango-cli -in demo.jpg -out demo.auto_threshold.jpg -cmds "auto_threshold"
./vango-cli -in demo.jpg -out demo.morphology_dilate.jpg -cmds "morphology dilate 2"
./vango-cli -in demo.jpg -out demo.statistic.jpg -cmds "statistic median 2"
# save as a layered vango project file (.vango) for later editing
./vango-cli -in demo.jpg -cmds "brightness 0.1; contrast 1.1" -project-out demo.vango
# load a .vango project file and continue editing
./vango-cli -in demo.vango -out demo_final.jpg -cmds "sepia 0.2"
Generate demo outputs
- The repository includes a test that will generate demo images for every supported effect. Run:
# this writes demo.<effect>.jpg files into the repo root
go test -run TestGenerateDemos -v
Browser/WASM preparation
- A minimal browser-facing WASM entrypoint is available in
cmd/wasm. - Build it with:
GOOS=js GOARCH=wasm go build -o vango.wasm ./cmd/wasm
- Optional version injection:
GOOS=js GOARCH=wasm go build -ldflags "-X main.wasmVersion=v0.1.0" -o vango.wasm ./cmd/wasm
- In the browser, load
wasm_exec.js+vango.wasm; the module exposes a globalvangoobject with:wasm_exec.jsis available in your Go installation at$(go env GOROOT)/lib/wasm/wasm_exec.js.vango.ready(boolean)vango.version(string)vango.effects(array of supported CLI effect names)
Layered canvas & project files
vango ships a full layer system (Photoshop-style). You can create multi-layer canvases,
composite them with blend modes, apply per-layer masks and effects, and save / reload
the complete project as a JSON .vango file.
// Build a layered canvas
canvas := vango.NewCanvas(1200, 800)
bg := vango.NewSolidLayer("Background", 1200, 800, color.NRGBA{40, 40, 40, 255})
bg.ZOrder = 0
canvas.AddLayer(bg)
photo := vango.NewLayer("Photo", img)
photo.ZOrder = 1
photo.Blend = vango.BlendMultiply
photo.Opacity = 0.9
canvas.AddLayer(photo)
// Save as a layered project (images stored as base64-encoded PNGs inside JSON)
f, _ := os.Create("project.vango")
vango.SaveProject(canvas, f)
f.Close()
// Reload it later
f, _ = os.Open("project.vango")
restored, _ := vango.LoadProject(f)
f.Close()
// Flatten and export
flat := restored.FlattenAll()
out, _ := os.Create("output.png")
vango.EncodePNG(out, flat)
The .vango project format preserves:
- Canvas dimensions
- All layers (name, blend mode, opacity, visibility, offset, z-order, lock, clip, group)
- Pixel data (losslessly as embedded PNGs)
- Per-layer masks
Layer features
- Blend modes: Normal, Multiply, Screen, Overlay, Soft Light, Hard Light, Color Dodge, Color Burn, Darken, Lighten, Difference, Exclusion, Hue, Saturation, Color, Luminosity, Dissolve, Linear Burn, Linear Dodge, Vivid Light, Linear Light, Pin Light
- Non-destructive adjustment layers: Brightness/Contrast, Hue/Saturation, Levels, Curves, Color Balance, Vibrance, Threshold, Posterize, Invert, Gradient Map, Solid Color
- Layer styles: Drop Shadow, Inner Shadow, Outer/Inner Glow, Stroke, Bevel & Emboss
- Layer groups: group layers and flatten as a unit
- Layer masks: pixel-level selection masks (feathering, grow, shrink, boolean ops)
- Undo/redo: full history with
History.SaveState/Undo/Redo
Supported effects (available via Pipeline and CLI)
Core adjustments
blur <sigma>— Gaussian blurunsharp <amount> <sigma>— unsharp maskcontrast <factor>saturation <factor>brightness <delta>hue <degrees>sepia <amount>invertgamma <gamma>grayscalesolarize [cutoff]equalize— histogram equalizationtonemap <exposure>— Reinhard tone-mappinglevels <inBlack> <inWhite> <gamma> <outBlack> <outWhite>curves <in1> <out1> <in2> <out2> …— tone curve (control points 0..1)channel_curves r:in,out,… g:… b:…— per-channel tone curvescolorbalance <sR> <sG> <sB> <mR> <mG> <mB> <hR> <hG> <hB>— shadows/midtones/highlightschannelmix <rR> <rG> <rB> <gR> <gG> <gB> <bR> <bG> <bB>hsl_selective <targetHue> <range> <satFactor> <lightDelta>color_temperature <kelvin_shift>— warm/cool shiftvibrance <amount>— smart saturation boostdehaze <strength>— atmospheric dehazingshadow_highlight <shadows> <highlights>— recover shadows/highlightstint <RRGGBB> <opacity>— colour tint overlaygradient_map <RRGGBB,pos> …— gradient map effect
Sharpening & detail
sharpen <amount>— convolution sharpenunsharp <amount> <sigma>— unsharp maskhigh_pass_sharpen <amount> <radius>— high-pass sharpeningclarity <strength>— local-contrast clarity
Blur & focus
blur <sigma>motion_blur <angle> <distance>radial_blur <cx> <cy> <strength>tilt_shift <focusY> <bandWidth> <sigma>bilateral <sigmaSpatial> <sigmaRange>— edge-preserving blurnoise_reduction [radius]/denoise
Geometry
rotate <degrees>skew <sx> <sy>resize <w> <h>/resize_nearest <w> <h>crop <x0> <y0> <x1> <y1>smartcrop <w> <h>trimflipx/flipyseam_carve <w> <h>— content-aware resizeperspective <x0> <y0> <x1> <y1> <x2> <y2> <x3> <y3> <outW> <outH>
Distortions
twirl <angle> [radius]— twirl/whirlpoolspherize <amount>— spherical bulge (negative = pinch lens)wave <ampX> <ampY> <wlX> <wlY>— wave distortionripple <amplitude> <wavelength>— ripple distortionpinch <amount> [radius]— pinch distortionpolar_coordinates [to|from]— rectangular ↔ polar
Artistic & creative
emboss <strength>vignette <strength>glow <sigma> <intensity>halftone <dotSize>oil_painting <radius> <levels>chromatic_aberration <shift>add_noise <amount>dreamscape [sigma] [intensity]— soft pastel glowvhs [amount]— scanlines, chroma drift, and analog noiselight_leak [x] [y] [radius] [intensity]— warm radial film burnkaleidoscope [sectors]— mirrored radial folddither <levels>— Floyd–Steinberg ditheringordered_dither [levels]— Bayer-matrix ordered ditheringposterize <levels>threshold <cutoff>charcoal [radius] [sigma]— charcoal sketch effectsketch [sigma] [angle]— pencil sketchkuwahara [radius]— Kuwahara edge-preserving filterfilter <cinematic|teal_orange|matte|noir|lomo|chrome|fade|punch|golden_hour|moody|clean|portrait|cyberpunk|aurora|desert|midnight|candy|emerald|nebula|sunset|forest|twilight|pastel|infrared> [intensity]- direct aliases:
cinematic,teal_orange,matte,noir,lomo,chrome,fade,punch,golden_hour,moody,clean,portrait,cyberpunk,aurora,desert,midnight,candy,emerald,nebula,sunset,forest,twilight,pastel,infrared
Retouching
dodge <amount> [shadows|midtones|highlights]burn <amount> [shadows|midtones|highlights]
Auto modes
auto_contrastauto_brightnessauto_vibranceauto_exposure— percentile-based luminance stretchauto_tone— white balance + auto exposure + shadow/highlight recoverysmart_enhance— balanced auto tone + vibrance + clarityauto_scene/smart_auto— adaptive auto mode based on exposure, saturation, and dynamic rangeauto_color— white balance + equalize + auto brightness + auto vibranceauto_full— full auto enhanceauto_level— per-channel histogram stretch (alias:normalize)auto_threshold— Otsu automatic thresholding
Color normalisation
normalize— stretch each channel's histogram to the full 0–255 rangesigmoidal_contrast [sharpen|soften] <strength> [midpoint]— S-curve contrast
Blur variants (extended)
adaptive_blur <sigma>— edge-adaptive Gaussian blurselective_blur <sigma> [threshold]— blur only smooth regionsmean_shift [radius] [colorDist]— edge-preserving mean-shift denoising
Sharpening (extended)
adaptive_sharpen <sigma>— edge-adaptive unsharp mask
Morphology
morphology <dilate|erode|open|close> [radius]— morphological operations on colour images
Neighbourhood statistics
statistic <minimum|maximum|mean|median> [radius]— replace each pixel with neighbourhood statistic
Geometry (extended)
transpose— flip along the main diagonal (swap width and height)transverse— flip along the anti-diagonalroll <dx> <dy>— circular shift with wrap-aroundshave <x> [y]— remove x pixels from left/right, y from top/bottomextent <w> <h> [gravity] [RRGGBB]— expand canvas with fill colour; gravity: northwest/north/northeast/west/center/east/southwest/south/southeastspread <radius>— random pixel displacement
Utility
whitebalance [x0 y0 x1 y1]/wbcollage <file> [horizontal|vertical]watermark <file> <x> <y> <opacity>edge— Sobel edge detectiontext <string> <x> <y>apply <plugin>— registered plugin filter
Image alignment / collage
The AlignImages function (and the Collage Pipeline method) place two or more images into a
single canvas:
- horizontal (default): images are scaled to the same height and placed left-to-right.
- vertical: images are scaled to the same width and placed top-to-bottom.
// Code example – place two images side by side
result := vango.AlignImages([]image.Image{img1, img2}, "horizontal", color.NRGBA{255, 255, 255, 255})
// Fluent pipeline variant
out := vango.From(img1).Collage(img2, "vertical", color.NRGBA{0, 0, 0, 255}).Image()
CLI usage:
./vango-cli -in left.jpg -out combined.jpg -cmds "collage right.jpg horizontal"
Noise reduction
NoiseReduction applies a median filter. A larger radius removes more noise but softens edges:
denoised := vango.NoiseReduction(img, 1) // 3×3 median filter
denoised2 := vango.NoiseReduction(img, 2) // 5×5 median filter
// or via the pipeline:
out := vango.From(img).NoiseReduction(1).Image()
Selection tools
Selection provides Photoshop-style selection masks:
sel := vango.NewSelection(img.Bounds())
sel.SelectEllipse(cx, cy, rx, ry) // elliptical selection
sel.SelectByColor(img, x, y, tolerance, true) // magic wand
sel.SelectColorRange(img, r, g, b, fuzziness) // color range
sel.SelectByLuminosity(img, "highlights") // luminosity mask
sel.Feather(5) // feather edges
sel.Grow(3) // expand
sel.Shrink(3) // contract
// Apply effect only inside selection:
result := sel.ApplyToImage(original, processed)
Examples in code
- See
example_test.gofor small example usages (these are run as examples bygo test).