diff options
| author | Jules Laplace <jules@okfoc.us> | 2016-11-15 17:26:44 -0500 |
|---|---|---|
| committer | Jules Laplace <jules@okfoc.us> | 2016-11-15 17:26:44 -0500 |
| commit | 9beaf2708b012b9533ca3088fbddd542a3c6c076 (patch) | |
| tree | 895c29544d96685e3812a92420ea62a8537705a2 /public/assets/js/lib/ascii/photo.js | |
| parent | 468c23aae285e8845a16e4df527d37db9fef420b (diff) | |
dumping color codes to irc
Diffstat (limited to 'public/assets/js/lib/ascii/photo.js')
| -rw-r--r-- | public/assets/js/lib/ascii/photo.js | 336 |
1 files changed, 336 insertions, 0 deletions
diff --git a/public/assets/js/lib/ascii/photo.js b/public/assets/js/lib/ascii/photo.js new file mode 100644 index 0000000..1a1c6d6 --- /dev/null +++ b/public/assets/js/lib/ascii/photo.js @@ -0,0 +1,336 @@ + +var Photo = (function(){ + var COLORS = [ + [255,255,255], + [0,0,0], + [0,0,127], + [0,147,0], + [255,0,0], + [127,0,0], + [156,0,156], + [252,127,0], + [255,255,0], + [0,252,0], + [0,147,147], + [0,255,255], + [0,0,252], + [255,0,255], + [127,127,127], + [210,210,210] + ] + var HUES = [ + [255,255,255], + [0,0,0], + [0,0,127], + [0,147,0], + [255,0,0], + [127,0,0], + [156,0,156], + [252,127,0], + [255,255,0], + [0,252,0], + [0,147,147], + [0,255,255], + [0,0,252], + [255,0,255], + null, + null, + ] + var GRAYS = [ + [255,255,255], + [0,0,0], + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + [127,127,127], + [210,210,210] + ] + var REDS = [ + [255,255,255], + [0,0,0], + null, + null, + [255,0,0], + [127,0,0], + null, + [252,127,0], + [255,255,0], + null, + null, + null, + null, + [255,0,255], + null, + null, + ] + var YELLOWS = [ + [255,255,255], + [0,0,0], + null, + [0,147,0], + null, + null, + null, + [252,127,0], + [255,255,0], + [0,252,0], + null, + [0,255,255], + null, + null, + null, + null, + ] + var BLUES = [ + [255,255,255], + [0,0,0], + [0,0,127], + null, + null, + null, + [156,0,156], + null, + null, + [0,252,0], + [0,147,147], + [0,255,255], + [0,0,252], + [255,0,255], + null, + null, + ] + var colors = COLORS, recolor_fn = null, shade_fn = null, cc_recolor_fn = null + var canvas = document.createElement("canvas"), ctx = canvas.getContext('2d'), pixels + + function set_colors (a) { + colors = a + } + function set_shade_fn (fn) { + shade_fn = fn + } + function set_recolor_fn (fn) { + recolor_fn = fn + } + function set_cc_recolor_fn (fn) { + cc_recolor_fn = fn + } + + function closest_to(pixel){ + if (recolor_fn) { + pixel = recolor_fn(pixel) + } + return colors.reduce(function(prev, curr, index) { + var d = distance(pixel, curr) + if (prev[0] > d) { + prev[0] = d + prev[1] = index + } + return prev + }, [Infinity, -1])[1] + } + + function distance(u, v){ + if (! v) return Math.Infinity + var r = u[0] - v[0] + var g = u[1] - v[1] + var b = u[2] - v[2] + return Math.sqrt(r*r+g*g+b*b) + } + + function fromImageData (pixels, cb){ + var rows = [], + pixel = new Array (4), + data = pixels.data, + t + for (var i = 0, h = pixels.height; i < h; i++) { + var row = [] + rows.push(row) + for (var j = 0, w = pixels.width; j < w; j++) { + t = (i*w+j)*4 + pixel[0] = data[t] + pixel[1] = data[t+1] + pixel[2] = data[t+2] + pixel[3] = data[t+3] + if (shade_fn) { + shade_fn(data, pixel, j, i, w, h) + } + if (Photo.denoise) { denoise_pixel(data, w, h, i, j, pixel, Photo.denoise) } + row[j] = closest_to(pixel) + if (cc_recolor_fn) row[j] = cc_recolor_fn(row[j]) + } + } + if (! cb) return rows + else cb (rows) + } + function denoise_pixel (d, w, h, x, y, pixel, exponent){ + var rr = r, gg = g, bb = b; + var color = [0,0,0] + var total = 0.0 + var xx, yy, x0, y0, weight, r, g, b, t + for (xx = -4.0; xx <= 4.0; xx += 1.0) { + x0 = x+xx + if (x0 < 0 || x0 >= w) continue + for (yy = -4.0; yy <= 4.0; yy += 1.0) { + y0 = y+yy + if (y0 < 0 || y0 >= h) continue + t = (x+xx + w*(y+yy)) * 4 + r = d[ t ] + g = d[ t+1 ] + b = d[ t+2 ] + weight = 1.0 - Math.abs( 0.25 * ((rr-r)/255 + (gg-g)/255 + (bb-b)/255) ) + weight = pow( weight, exponent ) + color[0] += r * weight + color[1] += g * weight + color[2] += b * weight + total += weight + } + } + pixel[0] = color[0] * 255 / total + pixel[1] = color[1] * 255 / total + pixel[2] = color[2] * 255 / total + } + function getNaturalDimensions (img) { + if (img.naturalWidth) { + return { naturalWidth: img.naturalWidth, naturalHeight: img.naturalHeight } + } + if (img.videoWidth) { + return { naturalWidth: img.videoWidth, naturalHeight: img.videoHeight } + } + return { naturalWidth: img.width, naturalHeight: img.height } + } + function neighbor (canvas, ctx, img) { + var dims = getNaturalDimensions(img) + var scratch = document.createElement("canvas") + var scratchCtx = scratch.getContext('2d') + scratch.width = dims.naturalWidth + scratch.height = dims.naturalHeight + scratchCtx.drawImage(img, 0, 0, dims.naturalWidth, dims.naturalHeight) + var srcImageData = scratchCtx.getImageData(0,0,scratch.width,scratch.height) + var destImageData = ctx.createImageData(canvas.width,canvas.height) + var src = srcImageData.data, dest = destImageData.data + var dt, dw = destImageData.width, dh = destImageData.height + var st, sw = srcImageData.width, sh = srcImageData.height + for (var i = 0; i < dh; i++) { + for (var j = 0; j < dw; j++) { + var y = i * sh/dh + var x = j * sw/dw + dt = ((i*dw) + j) * 4 + st = Math.floor( Math.floor(y)*sw + x ) * 4 + dest[dt] = src[st] + dest[dt+1] = src[st+1] + dest[dt+2] = src[st+2] + dest[dt+3] = src[st+3] + } + } + return destImageData + } + var img = new Image () + function fromUrl (url, cb, opt) { + img.onload = function(){ + fromCanvas(img, cb, opt) + } + if (img.src == url) { return img.onload() } + img.src = url + if (img.complete) { return img.onload() } + } + function fromCanvas (img, cb, opt) { + var dims = getNaturalDimensions(img) + if (opt.width) { + canvas.width = opt.width + if (opt.height) { + canvas.height = opt.height + } else if (opt.ratio) { + canvas.height = opt.width / opt.ratio + } else { + canvas.height = (dims.naturalHeight * width / dims.naturalWidth) / 2 + } + } + else { + canvas.width = dims.naturalWidth * 2 + canvas.height = dims.naturalHeight + } + if (opt.neighbor) { + pixels = neighbor(canvas, ctx, img) + } + else { + ctx.drawImage(img,0,0,dims.naturalWidth,dims.naturalHeight,0,0,canvas.width,canvas.height) + pixels = ctx.getImageData(0,0,canvas.width,canvas.height) + } + fromImageData(pixels, cb) + } + function ascii (rows) { + var lines = rows.map(function(str){ + var last = -1 + return str.map(function(index){ + if (last == index) return " " + last = index + return "\\x031," + index + " " + }).join("") + }).join("\\n") + var txt = '/exec -out printf "' + lines + '"\n' + return txt + } + function asciiFromUrl (url, cb, opt) { + fromUrl(url, function(rows){ + cb(ascii(rows), rows) + }, width) + } + function stringFromUrl (url, cb, opt) { + fromUrl(url, function(rows){ + cb(rows.map(function(str){ + return str.map(function(index){ return "\C-c1," + index + " " }).join("") + }).join("\n")) + }, width) + } + function mirc (rows) { + return rows.map(function(str){ + var last = -1 + return str.map(function(index){ + if (last == index) { + return " " + } + else { + last = index + return "\u00031," + index + " " + } + }).join("") + }).join("\u0003\n") + } + + var Photo = { + colors: COLORS, + hues: HUES, + grays: GRAYS, + reds: REDS, + yellows: YELLOWS, + blues: BLUES, + set_shade_fn: set_shade_fn, + set_recolor_fn: set_recolor_fn, + set_cc_recolor_fn: set_cc_recolor_fn, + set_colors: set_colors, + closest_to: closest_to, + distance: distance, + fromUrl: fromUrl, + fromCanvas: fromCanvas, + fromImageData: fromImageData, + stringFromUrl: stringFromUrl, + asciiFromUrl: asciiFromUrl, + ascii: ascii, + mirc: mirc, + neighbor: neighbor, + denoise: 0, + } + return Photo + +})() + + |
