induwara.lk
induwara.lkImage · Art

Image to ASCII Art — Free, In-Browser

Drop any photo, screenshot, or logo and convert it into ASCII art live in your browser. Pick from four character ramps, switch between monochrome and 24-bit colour, tune brightness and contrast, and copy or download the result. No upload, no signup, sources cited below.

By Induwara AshinsanaUpdated May 11, 2026
Image to ASCII artMonochrome or 24-bit color
Files stay on your device

Everything runs in your browser. Nothing is uploaded.

What this does

Drop a photo, logo, or screenshot above. The tool samples each block of source pixels, weights it with the ITU-R BT.709 luminance formula browsers use for greyscale conversion, and picks an ASCII character from a Paul Bourke density ramp. Output renders live as you tune width, ramp, brightness, and contrast — and you can copy the plain text or download a colour HTML snapshot.

Brightness uses ITU-R BT.709 luma (Y = 0.2126R + 0.7152G + 0.0722B); character ramps are from Paul Bourke's ASCII art reference; pixel sampling uses the W3C canvas.getImageData API. Last verified 2026-05-11.

How it works

The converter decodes your image into a local HTMLCanvasElement and reads its pixels with getImageData. From there the pipeline is three deterministic steps, each run for every output cell:

  1. Block-average the source pixels covered by the cell. The output grid is cols × rows; for a cell at (cx, cy) we average every source pixel in the rectangle from (cx × width/cols, cy × height/rows) to ((cx+1) × width/cols, (cy+1) × height/rows). Averaging preserves shading detail much better than nearest-neighbour sampling, which is what most browser-based ASCII converters use.
  2. Compute perceptual brightness using the ITU-R BT.709 luma coefficients — Y = 0.2126R + 0.7152G + 0.0722B. These are the same weights every browser, Photoshop, and video pipeline uses for sRGB → greyscale conversion, derived from the spectral sensitivity of the human eye to red, green, and blue. Optional brightness and contrast offsets are then applied around mid-grey (128) before clamping to the 0–1 range.
  3. Pick a character from the active ramp. The ramp is ordered light → dark, so for a normalised luminance L ∈ [0, 1] the index is floor(L × ramp.length), clamped to ramp.length − 1 at the bright end. When Inverted is on, the index becomes floor((1 − L) × ramp.length), which is the right pick for output rendered on a dark background.

The four built-in ramps come from Paul Bourke's ASCII art reference and a small set of Unicode block characters. Each ramp lists the glyphs ordered by perceived ink density — a space at the light end, a heavy character (@, , or $) at the dark end — so longer ramps map more tonal levels but at smaller per-glyph differences.

A monospace cell is roughly twice as tall as it is wide. The tool builds the output grid using a 0.5character aspect factor so the rendered ASCII keeps the image's proportions in a regular line-height: 1 block. For 24-bit colour output, the same block-average that produces the brightness also supplies the cell's RGB; each glyph is wrapped in a coloured span (HTML) or an ANSI truecolor escape (terminal).

As a self-check, the tool compares the mean luminance of the source pixels to the mean ramp-position of the picked characters (after undoing any Invert). A correctly-implemented converter keeps the difference within one quantisation step — about ±5% for the 10-char ramp, tighter for 70-char. That delta is shown next to the output so you can verify the maths without having to take it on faith.

Worked examples

Pure black pixel — RGB(0, 0, 0)

The darkest source value picks the lightest glyph (or the densest, when inverted).

  1. Luma709 = 0.2126·0 + 0.7152·0 + 0.0722·0 = 0
  2. Normalised L = 0/255 = 0
  3. Standard ramp index = floor(0 × 10) = 0 → ' ' (a space)
  4. Inverted: index = floor(1 × 10) = 10, clamped to 9 → '@'

Mid grey — RGB(128, 128, 128)

The exact midpoint lands four characters into the standard 10-char ramp.

  1. Luma709 = 128 (equal channels collapse to the input value)
  2. Normalised L = 128/255 ≈ 0.5020
  3. Standard ramp index = floor(0.5020 × 10) = 5 → '+'
  4. Detailed 70-char ramp: floor(0.5020 × 70) = 35 → 'n' (finer step).

Sapphire brand blue — RGB(15, 76, 117)

A predominantly blue pixel ends up in the dark band thanks to BT.709's low B coefficient.

  1. Luma709 = 0.2126·15 + 0.7152·76 + 0.0722·117
  2. = 3.19 + 54.36 + 8.45 = 65.99
  3. Normalised L ≈ 0.2588
  4. Standard ramp index = floor(0.2588 × 10) = 2 → ':'

Saffron brand amber — RGB(243, 156, 18)

A bright, warm pixel lands well into the dense end of the ramp.

  1. Luma709 = 0.2126·243 + 0.7152·156 + 0.0722·18
  2. = 51.66 + 111.57 + 1.30 = 164.53
  3. Normalised L ≈ 0.6452
  4. Standard ramp index = floor(0.6452 × 10) = 6 → '*'

Frequently asked questions

Sources & references

The luma formula and density ramps in this tool were last cross-checked against the ITU-R and Bourke references on 2026-05-11. The page is reviewed whenever ITU-R ships a successor to BT.709 for SDR content, or browsers expose wide-gamut canvases by default.

Related tools

Rate this tool
Be the first to rate

Comments & feedback

Spotted a bug or want an improvement? Tell us — our team reviews every comment, and good ideas get built. Comments are public and anonymous.

Found a bug, edge case, or want to suggest an improvement?

Email me at [email protected] — most fixes ship within 24 hours.