SlopScore
20 crowdincl. 4 critics

glitchvape-vibecoded

Vaporwave Art image distortion editor
Open repo on GitHubgithub.com/kamiljdudek/glitchvape-vibecoded
Perl · ★ 1 · 0 forks · MIT · paperwork by the Cap'mmostly ai (inferred)light human (inferred)works-on-my-machine (inferred)other
listed 1 hour ago by kamiljdudek · last checked 1 hour ago
The owner didn't write this. This repo never submitted itself. The Cap'm found it on a truffle trawl and wrote its paperwork from what GitHub already shows. Picked by hand by the Cap'm on 2026-09-30: Vaporwave Art image distortion editor; its own README says "png) This is an entirely vibe-coded application". 1 stars; MIT license. The owner did not submit this. Votes count; awards don't until the owner claims it.

I'm not calling your project slop! Geeze, it's a joke... Do you own this repo?

Log in with GitHub as kamiljdudek. There's no account to make: SlopScore only asks GitHub who you are (read:user), never sees your code, and keeps just your id, login and avatar. Then you can:

  • Keep it, on your terms. Commit your own slopscore.md (spec) and press Refresh. Your paperwork replaces the Cap'm's, and you can submit it for Slop of the Day.
  • Take it down. One click on Remove. It stays gone; the trawl never brings it back.

Log in with GitHub

Can't log in as the owner? Request a takedown. No login needed, and a trawled listing comes down right away.

GitHub says
Vaporwave Art image distortion editor
created
2026-08-24 · pushed 1 hour ago · 39 commits · 3 contributors
languages
Perl 99%Makefile 1%
paperwork
licensereadme 42% health
dependencies
no dependency graph (no manifest, or disabled) · OSV.dev, checked 1 hour ago

Disclosures, inferred by the Cap'm

slopbucket
vibe-coded
category
other
ai_generated
mostly
human_touch
light
status
works-on-my-machine
language (detected)
makefileperl
license (detected)
mit

The Cap'm's log

The Cap'm wrote this paperwork, not the owner. This repo never submitted itself to SlopScore. The Cap'm picked it by hand: Vaporwave Art image distortion editor; its own README says "png) This is an entirely vibe-coded application". It carries the MIT license. The disclosures above are his best guess from what GitHub shows.

Is this yours? Commit a real slopscore.md and press Refresh to replace this, or remove the listing in one click. There's no account to make: you log in with GitHub.

README — the repo's own words, folded up so the grading fits on one screen

GlitchVape

GlitchVape

This is an entirely vibe-coded application. It is a tool for me, the author, aimed at simplifying the application of filters and transformations.

Vaporwave and glitch-art transformations for photographs. Reads PNG, JPEG and HEIC; writes stills or short looping animations.

glitchvape --preset vhs-decay Pictures/IMG_8111.HEIC

Install

Debian 13 / WSL:

sudo apt update && sudo apt install -y \
  imagemagick libimage-magick-perl \
  ffmpeg libheif-examples \
  pngquant gifsicle webp libimage-exiftool-perl \
  libpath-tiny-perl libjson-perl libyaml-libyaml-perl \
  libtry-tiny-perl libcapture-tiny-perl libfile-which-perl \
  libparallel-forkmanager-perl libmoo-perl libtest-deep-perl \
  fonts-noto-cjk fonts-ipafont fonts-vlgothic fonts-mplus fonts-misaki \
  fonts-terminus fonts-unifont fonts-cascadia-code fonts-hack

Check what the tool can actually see:

./bin/glitchvape --check-deps
./bin/glitchvape --check-fonts

Only imagemagick and libimage-magick-perl are strictly required. Everything else degrades gracefully: without ffmpeg you lose animation, without pngquant the quantiser falls back to ImageMagick's, without CJK fonts the text effects report which package would fix it.

For the graphical interface

glitchvape-gui is optional and needs nothing that the command-line tool does:

sudo apt install -y libgtk3-perl libgtk3-imageview-perl

Plus, for the animated preview and for auditioning an audio track:

sudo apt install -y gir1.2-gstreamer-1.0 gstreamer1.0-plugins-good \
  gstreamer1.0-gtk3 gstreamer1.0-libav

GTK 3 rather than 4 because Debian has no libgtk4-perl — GTK 4 from Perl would mean raw Glib::Object::Introspection without the API overrides Gtk3.pm provides. GStreamer is reached through introspection because Debian dropped the Perl binding years ago; the typelib is the same library.

Without these, glitchvape-gui prints the one apt line that fixes it and exits. The animated preview is checked separately and only when first asked for, so a machine with GTK but no GStreamer runs the still interface normally.

Fedora

There is a spec file, so the shortest route is a package:

sudo dnf install -y rpm-build perl-macros
sudo dnf builddep -y package/glitchvape.spec   # what BuildRequires names
make rpm                                # the three binary packages

make srpm builds only the source package, and make rpms builds both. All three go through the tarball rather than the spec in the tree, so a file make dist forgot is a build failure rather than a package quietly missing something.

Output lands wherever rpmbuild would have put it, ~/rpmbuild/RPMS. RPMTOPDIR moves it:

make rpm RPMTOPDIR=$PWD/build-rpm       # build without touching $HOME
make rpm RPMFLAGS='--nodeps --nocheck'  # skip BuildRequires and the tests

The last one proves the packaging rather than the program: --nocheck skips the %check section, which is where the test suite runs.

Or build straight out of a checkout:

sudo dnf install -y ImageMagick ImageMagick-perl perl-File-Which \
  ffmpeg-free pngquant gifsicle perl-Image-ExifTool libheif-tools \
  dejavu-sans-fonts google-noto-sans-cjk-fonts cascadia-code-fonts \
  terminus-fonts ipa-gothic-fonts
sudo dnf install -y perl-Gtk3 perl-Gtk3-ImageView \
  perl-Glib-Object-Introspection            # for the window
sudo dnf install -y gstreamer1 gstreamer1-plugins-base \
  gstreamer1-plugins-good gstreamer1-plugins-good-gtk   # animated preview

ffmpeg-free is what Fedora ships; RPM Fusion's ffmpeg works too, which is why the spec asks for /usr/bin/ffmpeg rather than for either package by name. There is no Fedora package for Misaki, so the pixel role falls through to Terminus.

Debian and Ubuntu

There is a package/debian/ directory, so the shortest route is again a package:

sudo apt install -y build-essential debhelper devscripts
make deb

Three come out, in the parent directory:

glitchvape the library and the command-line tools
glitchvape-gui the Gtk3 window
glitchvape-fonts-extra one typeface, non-free/fonts

The third is separate because of what is written above about W95FA: its terms are a font aggregator's description rather than a document, which is not enough for a package that claims MIT and OFL on the tin. glitchvape only suggests it, and the ui role falls through to DejaVu without it.

package/debian/README.Debian has the detail, including the one thing this packaging cannot do as it stands: a source package in main may not contain non-free content, and this one carries assets/fonts-nonfree/. Built locally or in a PPA it is fine; an upload to Debian proper would need either the licence settled — at which point the font moves up and the third package disappears — or the tarball repacked, for which package/debian/copyright already carries a commented-out Files-Excluded line.

The packaging drives the same Makefile the RPM spec does, rather than restating where anything goes, and package/debian/rules installs one binary package at a time from the targets the Makefile already splits — which is why there are no .install files here. make check-split, make check-licenses and the test suite all run during the build.

Packaging layout

Everything a distribution needs lives in package/ — the RPM spec, debian/, the desktop entry and the AppStream metadata — and everything the packaging targets produce lands in build/, which is gitignored and which make clean removes whole. A build writes nothing into the source tree.

Both packagings build from the tarball make dist writes there. rpmbuild -t finds package/glitchvape.spec inside it; make deb unpacks the tarball and moves package/debian into place, because dpkg-buildpackage insists on a debian/ directly beneath the directory it runs in. Building from the tarball rather than in the tree means a file make dist failed to include is a build failure rather than a package quietly missing something.

Installed, the modules go to %{perl_vendorlib} — /usr/share/perl5 on Debian — and the data to /usr/share/glitchvape, which are nowhere near each other — so the walk-up from __FILE__ that finds assets/ and presets/ in a checkout finds nothing. GlitchVape::Paths is the one constant naming the installed data directory, and make install rewrites it. In a checkout it is empty, which means "not installed" and sends both callers back to the walk-up, so a checkout behaves exactly as it did before that module existed.

The window is a separate subpackage. make check-split asserts that nothing outside the GUI module set reaches for Gtk3, which is what makes glitchvape installable on a machine that will never open one — and both builds run that assertion rather than trusting it.

Fonts are split the same way and for a licensing rather than a technical reason: assets/fonts/ ships in the base package and assets/fonts-nonfree/ in glitchvape-fonts-extra. Both are on the search path, so which package is installed changes what --check-fonts resolves and nothing else.

Manual pages are generated from the tools' own POD at install time rather than committed, so man glitchvape and glitchvape --help cannot document different flags — pod2usage reads the same block.

The launcher icon is not. assets/artwork/icon-256.png is committed, because generating it needs ImageMagick and installing should not. It is the middle 185×185 of the 215×185 logo, enlarged to 256 — cropped rather than padded, since a launcher draws it at 48 pixels and white bars top and bottom would spend a third of that on nothing:

magick assets/artwork/logo.png -gravity center -crop 185x185+0+0 +repage \
    -filter point -resize 256x256! -strip assets/artwork/icon-256.png

-filter point is the part that matters. The logo is 16-colour pixel art, and any smooth filter resamples it into some three and a half thousand blended colours and softens every edge — which is exactly the character the thing is made of. The same reasoning is why the about window shows the logo unscaled.

Optional fonts

Debian has no package for the classic camcorder faces. Drop .ttf/.otf files into assets/fonts/ — creating it if this is a fresh clone, since the directory is gitignored — and they are picked up automatically, ahead of anything installed system-wide. Subdirectories are searched too, so an upstream release can be unpacked whole — licence, README and all — rather than having its font files picked out of it; the top level is searched first, so a loose file still wins over one in a folder beneath it.

Only what FreeType can load counts: ttf, otf, ttc, pcf, bdf. The woff/woff2 files that font releases carry for the web are ignored, because ImageMagick cannot render from them — there is no reason to keep them here.

Font Role Where Licence
VCR OSD Mono vcr dafont.com/vcr-osd-mono.font free, including commercial use
Departure Mono vcr, pixel departuremono.com OFL 1.1
Fusion Pixel pixel github.com/TakWolf/fusion-pixel-font OFL 1.1
W95FA ui dafont.com/w95fa.font unverified — dafont says OFL; no licence text came with it

Three of the four are in the repository, under assets/fonts/, each unpacked as its author published it with the statement of terms beside the font. That is not tidiness: glitchvape --licenses and the about window read those files off disk rather than quoting a copy pasted into Perl, which is how the OFL's "the licence travels with the font" is satisfied by the actual document.

W95FA is the fourth, and it is in assets/fonts-nonfree/ instead. dafont describes it as OFL and free for personal and commercial use, but the download carries no licence text and no statement by its author has been found that can be cited — a claim about the terms rather than the terms. So it is packaged on its own, as glitchvape-fonts-extra, and the base package can say MIT and OFL-1.1 and VCR OSD Mono's grant and mean it.

Both directories are on the font search path, so a checkout finds every font either way and the split is invisible to everything but the packaging. Adding a font is a line in .gitignore plus its licence beside it; make check-licenses reports what the rule concluded and fails if a font arrived without one.

VCR OSD Mono was in the second directory until its author was asked directly, in the font's own comment thread: "Yes, the font is free even for commercial purposes." That is an unconditional grant with no SPDX identifier, so both packagings name it as a LicenseRef pointing at the file that records it. It is the worked example of how a font gets promoted.

Nothing breaks without any of them. Every role falls through to whatever fontconfig can see — pixel finds Misaki, mono finds Cascadia — and --check-fonts names the package or the download for anything still missing.

Fusion Pixel is the one that ships as a multi-file release; only the ja and zh_hans cuts are named by the pixel role, and ja is preferred because it carries kana, which is what the text effects actually draw.

Font roles are what presets ask for, not font names, so a preset keeps working on a machine with a different subset installed. --check-fonts shows which file each role currently resolves to.


Usage

glitchvape [options] <input>
Option
-p, --preset NAME preset to build the pipeline from
-o, --output PATH output file (default out/<name>.<preset>.png)
-s, --seed VALUE any string or number; same seed reproduces the render
--set E.P=V override one parameter; repeatable
-e, --enable NAME switch an effect on with its defaults
-d, --disable NAME switch an effect off
--max-dim N downscale the source first (default 1920)
--fit WxH downscale to fit a box, e.g. 640x480 — see below
--colors N quantise a still to an N-entry palette
-a, --animate render a loop instead of a still
--frames N / --fps N loop length and rate (default 24 @ 12)
--codec NAME h264, vp9 or av1; default from the extension
-j, --jobs N processes drawing a loop's frames (default one per core)
--audio PATH add a soundtrack; the loop repeats to cover it
--audio-start / --audio-end seconds; which part of the track
--audio-filter F=V vaporwave filter; repeatable
--generate KIND add a generated track; repeatable
--gen K=V set a parameter on the last --generate
--dtmf TEXT shorthand for one dialled track
--dtmf-digits take the text as a literal dial string
--dtmf-dial-tone lift the handset first: eu us uk jp
-n, --dry-run print the resolved pipeline, render nothing
-v, --verbose per-effect logging; twice for timings

--fit is a box; --max-dim is a number

--max-dim caps the longer side and lets the other fall where the aspect ratio puts it, which is the right rule for no bigger than this. It cannot say must land on a 640×480 screen, because that is two numbers.

--fit is those two numbers, and the box turns with the picture:

glitchvape --fit 640x480 photo.heic
source result
4:3 landscape 640×480
3:4 portrait 480×640
16:9 640×360
already smaller untouched — a box is a ceiling, never a floor

A portrait photograph gets 480×640 rather than 360×480 because a screen of that size filled its height with one. The box is applied to the source and to the result: letterbox and border add pixels, so constraining only the input would be a promise this makes and does not keep.

--colors is the other half of a period-correct file. ImageMagick's BMP encoder given a truecolour image writes a 24-bit file with a .bmp on the end, which is not what asking for 256 colours meant, so the palette is built first and the image switched to palette type:

glitchvape -p gameboy --fit 640x480 --colors 256 -o out/1995.bmp photo.heic

--codec settles what the extension cannot

.mp4 means H.264 and .gif means GIF; .webm is genuinely ambiguous, since VP9 and AV1 both live in it. Without --codec, .webm is VP9 — the one every build of ffmpeg can write.

h264 common default
vp9 smaller at the same quality; plays in browsers
av1 smallest of the three, modern and demanding codec

AV1 needs an encoder not every ffmpeg has. That is checked before the first frame rather than discovered at the last step of a job whose first twenty-four steps are whole renders.

Discovery:

glitchvape --list-effects       # all of them, grouped by pipeline stage
glitchvape --explain pixelsort  # parameters and documentation for one effect
glitchvape --list-presets
glitchvape --list-palettes
glitchvape --list-audio-filters
glitchvape --list-generators

Batch

glitchvape-batch -p vhs-decay Pictures/          # a directory of photos
glitchvape-batch --all-presets photo.heic        # every preset, to compare
glitchvape-batch -p mallsoft -j 8 -r Pictures/   # 8 workers, recursive

Existing outputs are skipped unless --force, so an interrupted run restarts cheaply.


Graphical interface

A window over the same pipeline: open a photograph, stack effects, watch the preview, export a still or a loop. Everything it can do, the command line can do too — Copy command line in the menu writes out the invocation for whatever is on screen.

docs/interface.md covers it properly: the panes, the menu, the export wizard, the settings popover, and the arrangements that were tried and discarded on the way to this one.


Presets

Preset
vhs-decay third-generation dub, tape shedding oxide
broadcast weak aerial, 2am, off-air
mallsoft empty shopping centre, security-camera memory
dreamcore overexposed, hazy, half-remembered
hotline neon-noir, high contrast, blown highlights
sunset synthwave horizon with grid and sun
crt-terminal green phosphor monitor, close up
gameboy four-tone handheld LCD
photocopy faxed, photocopied, scanned back in
deepfry reposted into oblivion
datamosh decoder given the wrong frame
anaglyph red/cyan misregistration, a 3D comic without the glasses
arcade eight-bit game: chunky pixels, a hardware palette, dithered
newspaper colour newsprint, screened at print angles and misregistered
defrag the 1995 disk defragmenter, mid-pass, with the photograph on the disk

base-vhs is also on the list but is not a look: it is the shared tape chain with the damage dialled low, for other presets to extends rather than restate. --list-presets shows it; picking it gives a very mild result, which is what it is for.

A preset is a YAML file naming effects and their parameters:

name: vhs-decay
title: Third-generation dub
extends: base-vhs          # optional; merged underneath this file
output:
  max_dim: 1600
effects:
  tracking:  { bands: 6, displacement: 55 }
  scanlines: { opacity: 0.3, spacing: 3 }
  vignette:  { enabled: 0 }        # switch off something inherited
order: [downsample, tracking, scanlines]   # optional

extends merges per effect, so a child overrides only the parameters it mentions. --set always wins over the file, so a preset is a starting point rather than a commitment:

glitchvape -p vhs-decay --set tracking.bands=12 --set grain.amount=0.2 in.heic

Presets are looked for in $GLITCHVAPE_PRESETS if it is set, then in ~/.local/share/glitchvape/presets — which is where the window's Save as preset… puts one, so a preset of yours shadows a shipped one of the same name without replacing it — then ./presets, then the presets that shipped, and last any a plug-in brought.

In the window a preset is one of the two things + offers on the Image page. It is the only thing there that replaces what is already in the pipeline, which the chooser says before you press Load, and the name is recorded — so Copy command line still comes back as -p vhs-decay with whatever you changed on top.


Effects

47 effects, sorted automatically into a signal chain. Order is not a free choice — scanlines applied before a downsample get eaten by the resample — so each effect declares a stage and the pipeline sorts by it.

Stage Shown as Effects
format Resolution & Format crop downsample bitmap defrag
colour Colour grade palette duotone gradient_map posterize quantize
channels Channel Separation chroma_shift rgb_shift chroma_bleed
damage Data Damage pixelsort databend blockshift slice vgatext deepfry
signal Signal & Tape wave tracking head_switch ghost vhold interlace dropout static
grain Grain & Dither grain dither
optics Screen & Optics scanlines grille bloom vignette curvature halftone cmyk glare softness flicker
overlay Overlays text osd grid watermark chicago stars
framing Framing letterbox maximised

The left column is the identifier — what --explain reports and what the library calls it. The middle column is what the interface shows, because a stage is two things at once: where an effect runs, and what it is for. The names were chosen to be honest about both. colour rather than grade, because only one of the six effects there is grading. damage rather than destroy, which said how it felt rather than what it did. optics rather than screen, because a lens is not a screen but belongs in the same late pass — which is also why softness sits there rather than under grain, and why static, which is radio-frequency snow, sits with the rest of the transport artefacts.

Every effect carries a presentable name alongside its identifier — chroma_shift is Chromatic Aberration, wave is Tape Wobble. The identifier is what presets, --set and the copied command line use and it never changes; the name is what the interface shows. Both appear side by side wherever an effect is listed, so the two stay connectable.

A few worth knowing about:

  • rgb_shift — anaglyph misregistration: the red/cyan doubling of a 3D comic read without the glasses. Distinct from chroma_shift, which splits two channels symmetrically around a third — here red goes one way and the cyan half, green and blue, goes the other, which a symmetric split cannot express. The two sides jitter independently and are redrawn every frame, so an animation flutters like a press run rather than sitting at one offset. Bit-for-bit identical to ffmpeg's rgbashift, in pure Perl.
  • vgatext — a graphics card losing its mind: runs of the picture replaced by 8×16 text-mode character cells in the sixteen CGA colours. Not random noise — legible, wrong, and arranged on a grid, which is what makes it read as a fault rather than as an effect. The glyphs are one bit per pixel and scaling is pixel replication, so a cell at scale 4 is thirty-two pixels of hard-edged blocks; see Why the font is in the source. It sits at damage, so the scanlines and grain and curvature all run over the characters — a broken framebuffer still goes out through the same CRT.
  • chroma_bleed — the most physically accurate VHS artefact. Composite video gives colour far less bandwidth than brightness, so colour smears horizontally while edges stay sharp. Done properly in YCbCr, smearing only Cb and Cr, and one-sided: the colour trails to the right of whatever it belongs to, because on tape it arrives late along the line. vertical is the up-and-down smear, off by default because real tape has almost none.
  • defrag — redraws the picture as the cluster map from the disk defragmenter that shipped with Windows 95, inside the defragmenter's own window: a grid of blocks eight pixels across and ten down, each one the state of what is supposed to be in it, most of the grid left as bare white paper because most of that window always was. Fourteen states, eight of them off the window's own legend. palette picks between two sixteen-colour tables with chequered blocks and three one-ink phosphor screens; free says how much of the disk is empty and scatter how ragged the edge of it is; window: 0 leaves the map bare.
  • crop — reframes to a shape (square, 4:3, 16:9, 2.39:1, 4:5, 9:16, or the picture's own) and chooses what is inside it. zoom magnifies rather than shrinks: the frame that comes out is the same size at every setting, so the rest of the chain is never handed a smaller canvas.
  • pixelsort — sorts runs of pixels within a brightness band. The band is what makes it read as art rather than noise: sorting only the dark runs leaves the subject legible while the shadows pour sideways. How long a smear may be is a share of the line rather than a count of pixels, so a preview and an export agree about it.
  • databend — corrupts bytes inside the compressed JPEG stream. Because JPEG codes DC terms differentially, one altered byte shifts every block after it, giving a coloured band rather than one bad pixel.
  • head_switch — the torn strip along the bottom edge, where a helical-scan VCR switches heads a few lines before the end of each field. Broadcast masks it off; a raw tape capture shows it.
  • grain — Gaussian, and concentrated in the shadows by default. The noise floor is constant, so it is only visible where the signal is weak. Applying grain evenly is the most common thing that makes an imitation look fake.

Build a look from nothing:

glitchvape -e duotone -e scanlines -e grain --set duotone.ramp=hotline photo.heic
Scan report · 2026-09-30
  • ✓ Prohibited terms or links
  • ✓ Repository eligibility
  • ✓ slopscore.md paperwork
  • ✓ Content policy
  • ✓ Risk review

From the balcony · 4 of 4 clapped

  1. Crusoeclapped
    No vulnerable dependencies, local-only image processing tool with graceful degradation, no telemetry or credential requests, and clear data handling story.
  2. Schnitzelclapped
    Vaporwave glitch art tool with playful vibe-coded energy and fun preset names like 'vhs-decay' that clearly aims to delight rather than optimize.
  3. Cap'm Slopclapped
    Clear README with what it does, how to run it, installation instructions, dependency checking, and honest disclosure that it's vibe-coded with light human touch.
  4. Princessclapped
    Clear working tool with detailed install instructions, MIT license, dependency checking, graceful degradation, and honest 'works-on-my-machine' status.

Critics are accounts on this site with no GitHub account behind them. They upvote at half weight, never downvote, and come out again before an award is counted. Who they are.

0 comments

log in to comment.

report this listing — log in to report