Undither Functionality - z0mbieparade/cyberspace-atmospheric-modulator GitHub Wiki

Undither Functionality

Cyberspace dithers every image in the browser, with a WebGL Bayer shader in the theme's colors. The <img> only ever gets the rendered blob: PNG; the original's address never reaches the page.

The script hooks the site's dither pipeline, drawImage > texImage2D > toBlob > URL.createObjectURL, to learn which original produced each blob:. It swaps the original in while the image is hovered, focused or held.

GIFs in chat take another road: the site fetches each through /api/gif-proxy, decodes the frames itself, and dithers them onto a <canvas> frame by frame. The script notes each GIF's original and size as it is fetched, and follows the frames to the canvas they end up on. Hovering that canvas lays the original GIF over it.

The hooks run in the page itself, injected as an inline <script>. If the page does not run it, they patch unsafeWindow directly instead.

When it doesn't work

Warning: some userscript managers, such as MonkeyScript, run scripts in a sandbox apart from the page. There the hooks never see the site's images, and hovering does nothing. After a hover finds nothing to show, Settings > AtmoMod says so under Undither images. It works in Tampermonkey and Greasemonkey.

To check from the console whether the hooks reached the page, paste:

CanvasRenderingContext2D.prototype.drawImage.toString().includes('__atmoSrc')

true means they patched the page's canvas code; false means they did not.

Run the Grease/Tampermonkey menu command Dump Image Undither Diagnostics on a page with dithered images, then read the [AtmoMod|image-undither] lines in the browser console.

Line What to look for
dither hooks installed, realm Where the hooks went in: page (the injected script), unsafeWindow or window (the fallback), or none (they could not go in at all)
page hooks = no answer The hooks never ran where the page could see them
first-stage probes live Whether the load probes are in place: src, fetch, and the GIF proxy's arrayBuffer. A gif arrayBuffer of false means GIFs cannot be followed at all
hooks live Whether each hook is still in place, or the site replaced it
pipeline How many images reached each stage; the first stage at 0 is where it breaks
gifs GIFs fetched / matched to their decode canvas / canvas draws, and canvases marked with their original. fetched above tagged means a GIF's size did not match its canvas; tagged above 0 with no marked canvas means the frames never reached the visible canvas
image map size, blob imgs in DOM How many dithered images on the page have a known original

A manager with no menu can read the hooks' counters from the console instead. On a page with dithered images, paste:

document.addEventListener('atmo:stats', e => console.log(JSON.parse(e.detail)), { once: true }); document.dispatchEvent(new CustomEvent('atmo:stats-request'));

Nothing printed means the hooks never ran. Every pipelineStats count at 0, with dithered images on the page, means they run apart from the page.

Paste those lines into a Report Issue.

Next: Color Logic

⚠️ **GitHub.com Fallback** ⚠️