Skip to content

Instantly share code, notes, and snippets.

@Guevara-chan
Last active March 2, 2017 00:16
Show Gist options
  • Save Guevara-chan/689fd8a95f3996e0fd726ddb365ffbdf to your computer and use it in GitHub Desktop.
Save Guevara-chan/689fd8a95f3996e0fd726ddb365ffbdf to your computer and use it in GitHub Desktop.
# Yet another clone of http://www.text-image.com/convert/
Jimp = require('jimp')
class ascii_image
constructor: (@image, @width = 130, char_pool = "01", filters = [], random_chars = true) ->
# Bitmap downscaling.
@height = Math.max(@image.bitmap.height // (@image.bitmap.width / @width * 2.33), 1)
@image.resize(@width, @height)
# Additinal filtering.
for cmd in filters
[filter, arg] = (cmd = cmd.split(':'))
if cmd.length > 2 or (cmd.length == 2 and Number.isNaN(arg = parseFloat arg))
throw new Error("Invalid command provided: '#{cmd.join(':')}'")
if filter in ['grayscale', 'sepia', 'posterize', 'invert', 'dither565', 'contrast', 'brightness']
@image[filter](if arg then arg else 0)
else throw new Error("Unknown filter requested: '#{filter}'")
# Character generator setup.
idx = 0
char_gen = if random_chars then () -> char_pool[Math.random() * char_pool.length // 1]
else () -> char_pool[idx = (idx+1) % char_pool.length]
# Actual pixels-to-char conversion.
@ascii =
for y in [0...@height]
for x in [0...@width]
char: char_gen()
color: (@image.getPixelColor(x, y) >> 8) & 0xffffff
# Variables freezing.
for field in ['image', 'width', 'height', 'ascii']
Object.defineProperty @, field, {writable: false, configurable: false}
as_tag_list: (prefix, infix, postfix) ->
for raw_row in @ascii
# Symbol row data optimization.
prev = raw_row[0]; row = []
for symbol in raw_row[1..]
if symbol.color == prev?.color then symbol.char += prev.char else row.push prev
prev = symbol
row.push symbol
# Ascii-to-tag translation.
(for symbol in row
prefix + "000000#{symbol.color.toString(16)}"[-6..] + infix + symbol.char + postfix
).join('')
as_html: () ->
@as_tag_list("<font color='\#", "'>", "</font>").join("<br>")
as_html_image: (zoom = 1, bg_color = 'BLACK', font_size = -3) ->
"""
<table align='center' cellpadding='10' style='zoom:#{zoom}'><tbody><tr bgcolor='#{bg_color}'><td>
<font size='#{font_size}'><pre>#{@as_html()}</pre></font>
</td></tr></tbody></table>
"""
# ~/Auxilary constructor to handle async loading/~
AsciiImage = (main, args...) ->
if typeof main in ['string', 'buffer'] then Jimp.read(main).then (img) -> new ascii_image(img, args...)
else Promise.resolve(new ascii_image(main, args...))
# ==Usage sample==
new AsciiImage('/path/to/image', 250, "▓█", ['contrast:0.5'], true).then (img) ->
require('fs').writeFile 'path/to/html', img.as_html_image(0.75)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment