PNG, JPEG, GIF, WebP, BMP, SVG, TIFF · Max 20 MB
Compare all 7 built-in character sets: glyph count, density range, monotonicity (whether density strictly increases from light to dark). Helps select the optimal charset for your source material.
Runs 10 render iterations with the current settings and reports average, min, max, and spread.
ASCII Standard (ANSI X3.4-1986 / ISO 646)
ASCII (American Standard Code for Information Interchange) defines 128 characters: 33 non-printing control codes and 95 printable characters (space through tilde). Standardised as ANSI X3.4-1986 and internationally as ISO/IEC 646:1991.
ASCII art uses the 95 printable characters (0x20–0x7E) as a visual medium, mapping pixel brightness to character darkness (ink density). The technique dates to the 1960s when line printers were the primary output device.
Key constraint: Each character occupies a fixed-width cell, making monospaced fonts essential. Character width-to-height ratio (typically ~0.5) defines the aspect correction needed for accurate reproductions.
Unicode Block Elements (U+2580–U+259F) & Braille Patterns
Block Elements (U+2580–U+259F): 32 characters providing quarter-cell and eighth-cell resolution patterns: ░ (light shade, ~25%), ▒ (medium, ~50%), ▓ (dark, ~75%), █ (full block). Defined in Unicode 1.1 (1993).
Braille Patterns (U+2800–U+28FF): 256 characters representing all combinations of an 8-dot (2×4) Braille cell. Each character encodes a unique 2×4 binary pattern, providing 8× sub-cell resolution. Used for high-resolution terminal graphics.
Box Drawing (U+2500–U+257F): 128 characters for line drawing: single/double/heavy horizontal, vertical, and corner pieces. Used for structural ASCII art and framing.
Image Sampling Theory (Nyquist-Shannon)
Nyquist-Shannon sampling theorem: To accurately represent a signal, the sampling rate must be at least twice the highest frequency component. In image-to-ASCII conversion, each output character cell samples a rectangular region of the source image.
Area averaging (SAT): Uses summed-area tables (Crow 1984) for O(1) computation of the mean value of any rectangular region. This is the highest-quality downsampling method as it integrates all pixels in the cell.
Bilinear interpolation: Samples 4 neighbouring pixels and linearly interpolates. Faster than area averaging but introduces blur.
Point/Nearest: Samples the single nearest pixel. Fastest but prone to aliasing - fine details may be missed or misrepresented.
Dithering Theory (Floyd-Steinberg & Bayer)
Error diffusion (Floyd-Steinberg 1976): After quantising each pixel to the nearest available level, the quantisation error is distributed to unprocessed neighbouring pixels using a specific kernel. This creates the illusion of intermediate tones using only the available character set.
Floyd-Steinberg kernel: Distributes error: 7/16 right, 3/16 below-left, 5/16 below, 1/16 below-right. Total weights sum to 1.0. Serpentine (alternating left-right) scanning reduces directional artefacts.
Ordered dithering (Bayer 1973): Uses a threshold matrix (Bayer matrix) to decide quantisation per pixel. The matrix is tiled across the image. Bayer 4×4 has 16 threshold levels; 8×8 has 64 levels. Produces a regular cross-hatch pattern rather than the organic texture of error diffusion.
Trade-off: Error diffusion produces higher visual quality but is sequential (each pixel depends on previous errors). Ordered dithering is fully parallel and cache-friendly but produces visible patterning.
Edge Detection (Sobel Operator)
Sobel operator (Sobel & Feldman 1968): A discrete differentiation operator computing the gradient magnitude of image intensity. Uses two 3×3 convolution kernels (Gx for horizontal, Gy for vertical edges).
In ASCII art, edge detection is used for edge-aware glyph selection: at positions with strong edges, characters with directional strokes (|, -, /, \) are preferred over density-only characters, improving structural fidelity.
Linear-light luminance: Edge detection should operate on linearised (gamma-decoded) luminance to avoid gamma-induced artifacts near shadow boundaries.
Luminance & Brightness Standards
Rec. 601 luminance: Y = 0.299R + 0.587G + 0.114B. Used for standard-definition video. The most common brightness algorithm for ASCII art due to its perceptual accuracy.
Rec. 709 luminance: Y = 0.2126R + 0.7152G + 0.0722B. Used for HD video and sRGB displays. This tool's Sobel edge detector uses Rec. 709 for linear-light computation.
HSL Lightness: L = (max(R,G,B) + min(R,G,B)) / 2. Simple but less perceptually accurate - treats all hues equally regardless of human sensitivity differences.
Average: Y = (R + G + B) / 3. Mathematically simple, perceptually inaccurate. Overweights blue and underweights green compared to human perception.
Gamma Correction (sRGB / IEC 61966-2-1)
sRGB gamma (IEC 61966-2-1:1999): Display devices have a non-linear transfer function. sRGB defines a piecewise gamma: linear below 0.0031308, and C^(1/2.4) scaled above. The effective gamma is approximately 2.2.
In ASCII art: Gamma correction adjusts the brightness-to-character mapping curve. Gamma <1.0 brightens (lifts shadows), gamma >1.0 darkens (crushes shadows). Default gamma = 1.0 (no correction). For best results with photographic images, try gamma = 1.1–1.4 to compensate for the discrete nature of character brightness.
Brightness / Luminance Algorithms:
Y = 0.299 * R + 0.587 * G + 0.114 * B
Rec. 709 Luminance (used in Sobel):
Y = 0.2126 * R + 0.7152 * G + 0.0722 * B
Average:
Y = (R + G + B) / 3
HSL Lightness:
L = (max(R, G, B) + min(R, G, B)) / 2
Character mapping:
index = floor(Y / 255 * (charset.length - 1))
char = charset[index]
(Optionally inverted: index = charset.length - 1 - index)
Floyd-Steinberg Error Diffusion (1976):
1. Quantise: q = nearest_char_brightness(pixel)
2. Error: e = pixel - q
3. Diffuse error to neighbours:
pixel[x+1, y ] += e * 7/16
pixel[x-1, y+1] += e * 3/16
pixel[x , y+1] += e * 5/16
pixel[x+1, y+1] += e * 1/16
Kernel (normalised by 16):
[ . * 7 ]
[ 3 5 1 ]
Properties:
- Sequential (each pixel depends on prior errors)
- Serpentine scanning reduces directional bias
- Produces organic, noise-like texture
- Sum of weights = 16/16 = 1.0 (energy-preserving)
Bayer Ordered Dithering Matrix:
B(1) = [0]
B(2n) = [ 4*B(n)+0 4*B(n)+2 ]
[ 4*B(n)+3 4*B(n)+1 ]
Bayer 4×4 (normalised to [0,1]):
| 0/16 8/16 2/16 10/16 |
| 12/16 4/16 14/16 6/16 |
| 3/16 11/16 1/16 9/16 |
| 15/16 7/16 13/16 5/16 |
Bayer 8×8: 64 threshold levels (8×8 matrix)
Constructed recursively from B(4). Each cell provides
a threshold: if pixel_brightness > threshold, use
brighter char, else darker char.
Application in ASCII:
threshold = bayer[y % n][x % n] / (n*n)
adjusted = brightness + (threshold - 0.5) * spread
char = charset[quantise(adjusted)]
Sobel Edge Detection Operator:
| -1 0 +1 |
| -2 0 +2 |
| -1 0 +1 |
Vertical gradient kernel (Gy):
| -1 -2 -1 |
| 0 0 0 |
| +1 +2 +1 |
Gradient magnitude:
G = sqrt(Gx^2 + Gy^2)
Gradient direction:
theta = atan2(Gy, Gx)
Edge-aware ASCII:
If G > threshold * edgeStrength:
Select directional glyph based on theta:
0° or 180° → '-' (horizontal edge)
90° or 270° → '|' (vertical edge)
45° or 225° → '/' (diagonal)
135° or 315° → '\' (anti-diagonal)
Else:
Use standard density-based character mapping
Linear-light requirement:
Apply inverse sRGB gamma before Sobel to avoid
gradient bias in dark regions.
Gamma Correction:
output = input^gamma
gamma < 1.0 → brightens (lifts shadows, expands dark range)
gamma = 1.0 → linear (no change)
gamma > 1.0 → darkens (crushes shadows, expands highlight range)
sRGB Transfer Function (IEC 61966-2-1):
if C_linear <= 0.0031308:
C_srgb = 12.92 * C_linear
else:
C_srgb = 1.055 * C_linear^(1/2.4) - 0.055
Inverse sRGB (decode):
if C_srgb <= 0.04045:
C_linear = C_srgb / 12.92
else:
C_linear = ((C_srgb + 0.055) / 1.055)^2.4
Effective gamma: sRGB approx 2.2
In this tool: Gamma slider applies power-law
correction AFTER brightness computation, BEFORE
character mapping.
Image Sampling Methods:
SAT construction (Crow 1984):
SAT[x,y] = I[x,y] + SAT[x-1,y] + SAT[x,y-1] - SAT[x-1,y-1]
Area sum for rect (x1,y1)→(x2,y2):
S = SAT[x2,y2] - SAT[x1-1,y2] - SAT[x2,y1-1] + SAT[x1-1,y1-1]
Mean = S / ((x2-x1+1) * (y2-y1+1))
O(W*H) build, O(1) per cell query. Best for downsampling.
Bilinear Interpolation:
Sample 4 pixels at cell centre:
f(x,y) = f(0,0)(1-dx)(1-dy) + f(1,0)dx(1-dy)
+ f(0,1)(1-dx)dy + f(1,1)dx*dy
where dx, dy = fractional part of sample position.
Point / Nearest Neighbour:
f(x,y) = I[round(sx), round(sy)]
where (sx,sy) = centre of the character cell in the source.
Fastest, but aliasing-prone.
Character Density Calibration:
For each character in the charset:
1. Render glyph on 32×32 canvas (24px monospace)
2. Read ImageData alpha channel
3. Count pixels with alpha > 128 ("ink pixels")
4. Density = ink_pixels / (32 * 32)
Sort order:
Characters sorted by density ascending (light → dark).
Space (' ') typically has density ≈ 0.000
'@' or '█' typically has density ≈ 0.25–1.00
Mapping:
brightness (0-1) → charset_index:
index = floor(normalised_brightness * (n-1))
Font dependency:
Density values change with font family, size, and weight.
This tool recalibrates on each render when font changes.
Monotonicity requirement:
Ideal charset has strictly increasing density from first
to last character. Non-monotonic charsets create
brightness inversion artefacts.
Limitations & Constraints:
- Resolution: ASCII output resolution is limited by column width (20–300). Each character represents a rectangular region of the source image; detail below cell size is lost.
- Aspect ratio: Characters are taller than wide (~2:1). The aspect ratio slider compensates, but exact correction depends on the output font's metrics.
- Color mode: HTML/Canvas color mode uses per-character foreground color. This requires significantly more output data and may degrade performance for high-resolution renders.
- Floyd-Steinberg: Error diffusion is sequential — cannot be parallelised. For large images (>200 columns) it may be noticeably slower than ordered dithering.
- Webcam latency: Live webcam mode introduces frame acquisition + render latency. At 150ms debounce with 100-column output, expect ~6-8 effective FPS.
- Canvas export: PNG export rasterises at the output font size. For very large renders, the canvas may exceed browser memory limits.
- Font rendering: Density calibration assumes the browser's default monospace font. Custom fonts may produce slightly different density curves, affecting character selection accuracy.
- Edge detection: Sobel operator detects 1-pixel edges in the source image. If the source is already significantly downscaled, edges may be too thick or absent for meaningful detection.
Character Encoding & ASCII Art
[2] ISO/IEC 646:1991. Information technology — ISO 7-bit coded character set for information interchange.
[3] The Unicode Consortium (2023). The Unicode Standard, Version 15.1. Block Elements (U+2580–U+259F), Braille Patterns (U+2800–U+28FF), Box Drawing (U+2500–U+257F).
[4] Carlini, N. & Wagner, D. (2017). Adversarial examples are not easily detected: Bypassing ten detection methods. Proc. ACM Workshop on Artificial Intelligence and Security. (Discusses text-based visual encoding at scale.)
Image Sampling & Downscaling
[6] Shannon, C.E. (1949). Communication in the presence of noise. Proc. IRE, 37(1), 10-21. DOI: 10.1109/JRPROC.1949.232969
[7] Mitchell, D.P. & Netravali, A.N. (1988). Reconstruction filters in computer graphics. Proc. SIGGRAPH '88, 221-228. ACM.
Dithering & Quantisation
[9] Bayer, B.E. (1973). An optimum method for two-level rendition of continuous-tone pictures. Proc. IEEE International Conference on Communications, 26, 11-15.
[10] Ulichney, R.A. (1987). Digital Halftoning. MIT Press. ISBN: 978-0-262-21009-7
[11] Knuth, D.E. (1987). Digital halftones by dot diffusion. ACM Transactions on Graphics, 6(4), 245-273.
Edge Detection & Image Processing
[13] Canny, J. (1986). A computational approach to edge detection. IEEE Trans. Pattern Analysis and Machine Intelligence, 8(6), 679-698. DOI: 10.1109/TPAMI.1986.4767851
[14] Gonzalez, R.C. & Woods, R.E. (2018). Digital Image Processing, 4th Ed. Pearson. ISBN: 978-0-13-335672-4
Color Science & Display Standards
[16] ITU-R BT.601-7. Studio encoding parameters of digital television for standard 4:3 and wide-screen 16:9 aspect ratios.
[17] ITU-R BT.709-6. Parameter values for the HDTV standards for production and international programme exchange.
About this tool
This tool implements a research-grade ASCII art pipeline with summed-area-table sampling, Floyd-Steinberg and Bayer dithering, Sobel edge-aware glyph selection, per-font density calibration, gamma correction, 4 render modes, and multi-format export — entirely client-side (zero network). StaticFlow ASCII Engine v3.1 by Auric Artisan.
Enter multiple text strings (one per line). Each will be rendered with the current settings and benchmarked. Useful for comparing rendering performance across different inputs.
Detailed density analysis of each character in the current charset. Shows measured ink coverage, monotonicity check, and density curve linearity. Run after changing charset or font for accurate calibration data.
Research note: the edge-aware glyph selection system uses a two-stage approach — first computing Sobel gradient magnitude and direction on linear-light luminance, then selecting directional glyphs (|, -, /, \) at positions where the gradient exceeds a threshold modulated by the edge strength slider.
1. Source resolution vs output columns ratio
Higher ratio = more source pixels per cell = better edge detection
2. Linear-light conversion before Sobel
Avoids gamma-induced false edges in shadow regions
3. Edge strength threshold (0.0 - 1.0)
0.0 = all positions treated as edges (structural only)
0.65 = default balanced setting
1.0 = only strongest edges trigger directional selection
4. Character set coverage
Requires directional glyphs: | - / \ + for meaningful edge rendering
Block and Braille charsets have limited directional information
The compression slider (0.0–0.95) applies glyph thinning by probabilistically replacing characters with spaces. This creates a sparse, minimalist aesthetic while preserving high-contrast features.
For each output character position:
brightness = cell_brightness (0-1, normalised)
threshold = 1.0 - compression_level
rand = xorshift32(seed++) / 2^32
if brightness < threshold AND rand < compression_level:
output = ' ' (space — suppress glyph)
else:
output = normal_char_mapping(brightness)
Properties:
- Deterministic via xorshift32 PRNG (seed: 2654435769)
- Preserves high-brightness features (dark areas in output)
- Creates organic stippling effect at compression 0.3–0.6
- Above 0.8 only strongest features survive
function xorshift32(state):
state ^= state << 13
state ^= state >>> 17
state ^= state << 5
return state
Period: 2^32 - 1
Default seed: 2654435769 (Knuth multiplicative constant)
Used for: temporal dithering, noise filter, compression.
Same seed + same input = identical output (reproducible).