| assets | ||
| js | ||
| .DS_Store | ||
| .gitattributes | ||
| index.html | ||
| README.md | ||
| style.css | ||
Image to ASCII Art
A browser-based tool that converts images into colored ASCII art with edge-detected glow effects, real-time animations, and multi-format export. Built with vanilla HTML, CSS, and JavaScript -- no frameworks, no build tools, no npm.
Table of Contents
- Features
- Getting Started
- File Structure
- Controls Reference
- Performance
- Technical Details
- Browser Support
- External Dependencies
Features
- Image to ASCII conversion with per-character color sampled from the source image
- 6 character sets including blocks, binary, and fully custom ramps
- Brightness, contrast, invert, and monochrome adjustments with custom dark/light color blending
- Edge-detected glow in uniform or per-character mode, applied only at contrast boundaries
- 9 combinable animation effects, each with independent intensity, speed, and (where applicable) color controls
- Per-effect parameter panel for fine-grained control over every animation parameter
- GIF export with transparent background, seamless loop detection, and configurable FPS/duration
- Image export as PNG, JPEG, or WEBP with quality control and frame selection for animated scenes
- Custom-styled scrollbars and a cohesive dark UI theme throughout
- Responsive two-panel layout that adapts to smaller screens
- Zero dependencies at build time -- single CDN library (gif.js) loaded at runtime for GIF encoding
Getting Started
No installation required. Open index.html in any modern browser:
open index.html
Or serve locally:
python3 -m http.server 8000
Upload an image via the drop zone (click, drag-and-drop, or paste with Ctrl+V) and the ASCII art renders instantly.
File Structure
image_to_ascii_art/
index.html -- Layout: two-panel UI with all controls
style.css -- Dark theme, custom scrollbars, responsive grid
assets/
preview.png -- Application preview screenshot
js/
main.js -- Entry point, wires modules on DOMContentLoaded
image-processor.js -- Image loading, canvas pixel extraction
ascii-converter.js -- Luminance mapping, character ramps, color modes
glow-engine.js -- Edge detection, multi-layer text-shadow, LUT caching
animation-engine.js -- 9 effects with per-effect params, composition pipeline
gif-exporter.js -- Canvas rendering, gif.js integration, image export
ui-controller.js -- DOM bindings, event wiring, state management
Controls Reference
Output
| Control | Range | Default | Description |
|---|---|---|---|
| Width | 40 -- 200 | 100 | Character count per row. Adjusts automatically with font size to maintain visual size. |
| Font Size | 4 -- 20 px | 8 | Display size of characters. Effective width = width * (8 / fontSize). |
Adjustments
| Control | Range | Default | Description |
|---|---|---|---|
| Brightness | -100 -- +100 | 0 | Shifts luminance values up or down. |
| Contrast | -100 -- +100 | 0 | Quadratic scaling around midpoint for a natural feel. |
| Invert | on/off | off | Reverses luminance and inverts RGB colors. |
| Monochrome | on/off | off | Maps pixels to a dark-to-light color gradient. |
When Monochrome is enabled, two color pickers appear for custom dark (#000000) and light (#ffffff) endpoints. Colors are linearly interpolated based on luminance.
Character Sets
| Name | Characters | Description |
|---|---|---|
| Standard | 72 chars (space to $) |
Full ASCII gradient for maximum detail |
| Blocks | Unicode block elements | Clean and minimal |
| Detailed | .,- ~:;=!*#$@ |
Balanced detail and readability |
| Simple | .:*#@ |
High contrast, few characters |
| Binary | 01 |
Digital / matrix aesthetic |
| Custom | User-defined | Enter any characters ordered dark to light |
Glow
Glow is applied only at contrast edges where neighboring characters have significant luminance differences, computed via 4-neighbor edge detection with a threshold of 30/255.
| Mode | Description |
|---|---|
| Off | No glow |
| Uniform | Single glow color for all edge characters |
| Per-Character | Glow color derived from each character's own color, boosted for visibility |
| Control | Range | Default |
|---|---|---|
| Color | hex | #ffffff |
| Intensity | 0 -- 100 | 50 |
| Spread | 1 -- 30 px | 8 |
Animations
All 9 effects are checkbox-toggleable and fully combinable. They are applied in a fixed composition order to ensure consistent results.
Effects
| # | Effect | Default Speed | Description |
|---|---|---|---|
| 1 | Character Cycle | 2 | Characters morph through the ramp using sine-based noise |
| 2 | Wave | 3 | Rows shift horizontally in a sinusoidal pattern |
| 3 | Glow Pulse | 3 | Glow intensity pulsates between 30% and 100% |
| 4 | Matrix Rain | 1 | Vertical streams of colored characters fall down columns |
| 5 | Reveal | 4 | Characters appear progressively left-to-right, top-to-bottom |
| 6 | Glitch | 3 | Burst-style row band distortions with colored artifacts |
| 7 | Color Wave | 2 | Hue rotation wave sweeps across the grid |
| 8 | VHS | 1 | Old TV scan lines and diagonal tracking band distortions |
| 9 | Breathe | 1.5 | Gentle global opacity pulsation |
Composition Order
Reveal -> Matrix Rain -> Glitch -> Character Cycle -> Wave -> VHS -> Color Wave -> Glow Pulse -> Breathe
Structural effects run first (reveal, rain, glitch), then character mutations, spatial distortions, color modifications, and finally global modifiers.
Global Controls
| Control | Range | Default | Description |
|---|---|---|---|
| Speed | 0.1x -- 3.0x | 1.0x | Time multiplier for all effects |
| Intensity | 0 -- 100 | 50 | Global intensity (syncs with per-effect sliders) |
| Play / Pause | -- | -- | Start/stop the animation loop (30 fps cap) |
Advanced Animation Panel
Click Advanced to expand the per-effect control panel. Each effect has its own group with independent controls:
All effects have:
- Intensity slider (0--100) -- overrides the global intensity for that specific effect
- Speed slider -- controls the animation speed for that individual effect
Matrix Rain additionally has:
- Color picker -- changes the rain color (default:
#00ff00green)
Glitch additionally has:
- Color picker -- changes the glitch artifact color (default:
#ff0000red)
Color Wave additionally has:
- Hue Range slider (0.05--1.0) -- controls the magnitude of hue shifting (default: 0.3)
Changing the global Intensity slider resets all per-effect intensity sliders to the same value. Speed and color controls are independent and persist.
GIF Export
| Control | Range | Default | Description |
|---|---|---|---|
| Seamless Loop | on/off | off | Auto-calculates loop duration from active effects via LCM |
| Duration | 1 -- 10s | 3s | Manual duration (disabled when Seamless Loop is on) |
| FPS | 5 -- 30 | 15 | Frames per second |
| Transparent | on/off | on | Transparent background (green chroma key internally) |
| Background Color | -- | #1a1a2e |
Solid background when Transparent is off |
Frames are rendered to a hidden <canvas> using fillText with shadowColor/shadowBlur for glow. gif.js encodes the frames, with progress reported on the button. The resulting GIF auto-downloads.
When Seamless Loop is enabled, the export duration equals the least common multiple of all active effects' cycle durations divided by the current speed, accounting for per-effect speed overrides.
Image Export
Export a single frame as a static image file.
| Control | Options | Default | Description |
|---|---|---|---|
| Format | PNG / JPEG / WEBP | PNG | Output format |
| Quality | 0.1 -- 1.0 | 0.92 | Compression quality (JPEG and WEBP only, hidden for PNG) |
| Frame | 0 -- max | 0s | Select which animation frame to export (visible only when animations are active) |
| Capture Current Frame | -- | -- | Sets the frame slider to the current playback position |
PNG and WEBP support transparent backgrounds. JPEG does not support transparency and will render with a black background when Transparent is enabled.
Performance
- Edge map caching -- computed once per image conversion, not per frame
- Glow LUT caching -- uniform mode uses a 10-step quantized lookup table; per-character mode pre-computes all glow strings
- 2-layer text-shadow during animation versus 4 layers for static rendering
- String array building -- HTML is constructed via array
join('')with a singleinnerHTMLassignment - 30 fps cap on the animation loop via
requestAnimationFramethrottling - 100ms debounce on conversion-triggering controls
Technical Details
Luminance
Rec. 601 formula: L = 0.299R + 0.587G + 0.114B
Used for character selection, edge detection, and monochrome conversion.
Aspect Ratio Correction
Monospace characters are roughly 2x taller than wide. The output height is corrected:
outputHeight = outputWidth * (imageHeight / imageWidth) * 0.5
Font Size / Width Relationship
Changing font size re-converts the image with an adjusted character count to maintain consistent visual dimensions:
effectiveWidth = widthSlider * (8 / fontSize)
Module System
All modules are IIFEs attached to window.*. No ES modules, no bundler. Load order in index.html ensures dependencies are available.
Browser Support
Works in any modern browser (Chrome, Firefox, Safari, Edge). Requires:
- Canvas API (
getImageData,fillText,shadowBlur) requestAnimationFrame- ES5+ (uses
var, no arrow functions in core modules) - Fetch API (for gif.js worker)
canvas.toBlob(for image export)
External Dependencies
| Library | Version | Source | Purpose |
|---|---|---|---|
| gif.js | 0.2.0 | CDN (cdnjs) | GIF encoding |
No npm packages. No build step. Single CDN dependency loaded at runtime.
License
MIT
