diff options
Diffstat (limited to 'public/assets/js/lib/ascii')
| -rw-r--r-- | public/assets/js/lib/ascii/color.js | 251 | ||||
| -rw-r--r-- | public/assets/js/lib/ascii/photo.js | 336 |
2 files changed, 587 insertions, 0 deletions
diff --git a/public/assets/js/lib/ascii/color.js b/public/assets/js/lib/ascii/color.js new file mode 100644 index 0000000..ac90a3d --- /dev/null +++ b/public/assets/js/lib/ascii/color.js @@ -0,0 +1,251 @@ +// http://www.easyrgb.com/index.php?X=MATH&H=01#text1 + +function rgb(x,y,z){ + r=x; g=y; b=z +} +function rgbref(rgb){ + r=rgb[0]; g=rgb[1]; b=rgb[2]; +} +function black(){ rgb(0,0,0) } +function white(){ rgb(255,255,255) } +function red(){ rgb(255,0,0) } +function gray(n){ n<1&&(n*=255);rgb(n,n,n) } + +function rgb2xyz(rgb){ + var var_R = ( rgb[0] / 255 ) //R from 0 to 255 + var var_G = ( rgb[1] / 255 ) //G from 0 to 255 + var var_B = ( rgb[2] / 255 ) //B from 0 to 255 + + if ( var_R > 0.04045 ) var_R = Math.pow( ( var_R + 0.055 ) / 1.055, 2.4) + else var_R = var_R / 12.92 + if ( var_G > 0.04045 ) var_G = Math.pow( ( var_G + 0.055 ) / 1.055, 2.4) + else var_G = var_G / 12.92 + if ( var_B > 0.04045 ) var_B = Math.pow( ( var_B + 0.055 ) / 1.055, 2.4) + else var_B = var_B / 12.92 + + var_R = var_R * 100 + var_G = var_G * 100 + var_B = var_B * 100 + + //Observer. = 2°, Illuminant = D65 + var x = var_R * 0.4124 + var_G * 0.3576 + var_B * 0.1805 + var y = var_R * 0.2126 + var_G * 0.7152 + var_B * 0.0722 + var z = var_R * 0.0193 + var_G * 0.1192 + var_B * 0.9505 + return [x,y,z]; +} +function xyz2rgb(xyz){ + var var_X = xyz[0] / 100 //X from 0 to 95.047 (Observer = 2°, Illuminant = D65) + var var_Y = xyz[1] / 100 //Y from 0 to 100.000 + var var_Z = xyz[2] / 100 //Z from 0 to 108.883 + + var_R = var_X * 3.2406 + var_Y * -1.5372 + var_Z * -0.4986 + var_G = var_X * -0.9689 + var_Y * 1.8758 + var_Z * 0.0415 + var_B = var_X * 0.0557 + var_Y * -0.2040 + var_Z * 1.0570 + + if ( var_R > 0.0031308 ) var_R = 1.055 * Math.pow( var_R, 1 / 2.4 ) - 0.055 + else var_R = 12.92 * var_R + if ( var_G > 0.0031308 ) var_G = 1.055 * Math.pow( var_G, 1 / 2.4 ) - 0.055 + else var_G = 12.92 * var_G + if ( var_B > 0.0031308 ) var_B = 1.055 * Math.pow( var_B, 1 / 2.4 ) - 0.055 + else var_B = 12.92 * var_B + + var r = clamp(var_R * 255, 0, 255) + var g = clamp(var_G * 255, 0, 255) + var b = clamp(var_B * 255, 0, 255) + return [r,g,b] +} + +function xyz2hunterlab (XYZ) { + var X = XYZ[0] + var Y = XYZ[1] || 1e-6 // otherwise divide-by-zero error when converting rgb(0,0,0) + var Z = XYZ[2] + var L = 10 * sqrt( Y ) + var a = 17.5 * ( ( ( 1.02 * X ) - Y ) / sqrt( Y ) ) + var b = 7 * ( ( Y - ( 0.847 * Z ) ) / sqrt( Y ) ) + return [L,a,b] +} + +function hunterlab2xyz (Lab) { + var L = Lab[0] + var a = Lab[1] + var b = Lab[2] + var_Y = L / 10 + var_X = a / 17.5 * L / 10 + var_Z = b / 7 * L / 10 + + Y = Math.pow(var_Y, 2) + X = ( var_X + Y ) / 1.02 + Z = -( var_Z - Y ) / 0.847 + return [X,Y,Z] +} +// Daylight Illuminant (D65) +var REF_X = 95.047 +var REF_Y = 100.000 +var REF_Z = 108.883 + +function xyz2cielab (xyz) { + var var_X = xyz[0] / ref_X //ref_X = 95.047 Observer= 2°, Illuminant= D65 + var var_Y = xyz[1] / ref_Y //ref_Y = 100.000 + var var_Z = xyz[2] / ref_Z //ref_Z = 108.883 + + if ( var_X > 0.008856 ) var_X = Math.pow( var_X, 1/3 ) + else var_X = ( 7.787 * var_X ) + ( 16 / 116 ) + if ( var_Y > 0.008856 ) var_Y = Math.pow( var_Y, 1/3 ) + else var_Y = ( 7.787 * var_Y ) + ( 16 / 116 ) + if ( var_Z > 0.008856 ) var_Z = Math.pow(var_Z, 1/3 ) + else var_Z = ( 7.787 * var_Z ) + ( 16 / 116 ) + + var L = ( 116 * var_Y ) - 16 + var a = 500 * ( var_X - var_Y ) + var b = 200 * ( var_Y - var_Z ) + + return [L,a,b] +} + +function cielab2xyz (lab){ + var var_Y = ( lab[0] + 16 ) / 116 + var var_X = lab[1] / 500 + var_Y + var var_Z = var_Y - lab[2] / 200 + + if ( Math.pow(var_Y, 3) > 0.008856 ) var_Y = Math.pow(var_Y, 3) + else var_Y = ( var_Y - 16 / 116 ) / 7.787 + if ( Math.pow(var_X, 3) > 0.008856 ) var_X = Math.pow(var_X, 3) + else var_X = ( var_X - 16 / 116 ) / 7.787 + if ( Math.pow(var_Z, 3) > 0.008856 ) var_Z = Math.pow(var_Z, 3) + else var_Z = ( var_Z - 16 / 116 ) / 7.787 + + var x = REF_X * var_X //ref_X = 95.047 Observer= 2°, Illuminant= D65 + var y = REF_Y * var_Y //ref_Y = 100.000 + var z = REF_Z * var_Z //ref_Z = 108.883 + + return [x,y,z] +} + +function rgb2hsl (RGB){ + var R = RGB[0] + var G = RGB[1] + var B = RGB[2] + var var_R = ( R / 255 ) //RGB from 0 to 255 + var var_G = ( G / 255 ) + var var_B = ( B / 255 ) + + var var_Min = Math.min( var_R, var_G, var_B ) //Min. value of RGB + var var_Max = Math.max( var_R, var_G, var_B ) //Max. value of RGB + var del_Max = var_Max - var_Min //Delta RGB value + + var H,S; + var L = ( var_Max + var_Min ) / 2 + + if ( del_Max == 0 ) //This is a gray, no chroma... + { + H = 0 //HSL results from 0 to 1 + S = 0 + } + else //Chromatic data... + { + if ( L < 0.5 ) S = del_Max / ( var_Max + var_Min ) + else S = del_Max / ( 2 - var_Max - var_Min ) + + var del_R = ( ( ( var_Max - var_R ) / 6 ) + ( del_Max / 2 ) ) / del_Max + var del_G = ( ( ( var_Max - var_G ) / 6 ) + ( del_Max / 2 ) ) / del_Max + var del_B = ( ( ( var_Max - var_B ) / 6 ) + ( del_Max / 2 ) ) / del_Max + + if ( var_R == var_Max ) H = del_B - del_G + else if ( var_G == var_Max ) H = ( 1 / 3 ) + del_R - del_B + else if ( var_B == var_Max ) H = ( 2 / 3 ) + del_G - del_R + + if ( H < 0 ) H += 1 + if ( H > 1 ) H -= 1 + } + return [H,S,L] +} +function hsl2rgb (H, S, L) { + var R,G,B; + var var_1, var_2; + if ( S == 0 ) { //HSL from 0 to 1 + R = L * 255 //RGB results from 0 to 255 + G = L * 255 + B = L * 255 + } + else { + if ( L < 0.5 ) var_2 = L * ( 1 + S ) + else var_2 = ( L + S ) - ( S * L ) + + var_1 = 2 * L - var_2 + + R = 255 * hue2rgb( var_1, var_2, H + ( 1 / 3 ) ) + G = 255 * hue2rgb( var_1, var_2, H ) + B = 255 * hue2rgb( var_1, var_2, H - ( 1 / 3 ) ) + } + return [R,G,B] +} +function hue2rgb( v1, v2, vH ) { + if ( vH < 0 ) vH += 1 + if ( vH > 1 ) vH -= 1 + if ( ( 6 * vH ) < 1 ) return ( v1 + ( v2 - v1 ) * 6 * vH ) + if ( ( 2 * vH ) < 1 ) return ( v2 ) + if ( ( 3 * vH ) < 2 ) return ( v1 + ( v2 - v1 ) * ( ( 2 / 3 ) - vH ) * 6 ) + return ( v1 ) +} + +function rgb2cmy (R,G,B){ + if (R.length) { + B = R[2] + G = R[1] + R = R[0] + } + var C = 1 - ( R / 255 ) + var M = 1 - ( G / 255 ) + var Y = 1 - ( B / 255 ) + return [C,M,Y] +} +function cmy2rgb (C,M,Y){ + if (C.length) { + Y = C[2] + M = C[1] + C = C[0] + } + var R = ( 1 - C ) * 255 + var G = ( 1 - M ) * 255 + var B = ( 1 - Y ) * 255 + return [R,G,B] +} +function cmy2cmyk (C,M,Y) { + if (C.length) { + Y = C[2] + M = C[1] + C = C[0] + } + + var var_K = 1 + + if ( C < var_K ) var_K = C + if ( M < var_K ) var_K = M + if ( Y < var_K ) var_K = Y + if ( var_K == 1 ) { //Black + C = 0 + M = 0 + Y = 0 + } + else { + C = ( C - var_K ) / ( 1 - var_K ) + M = ( M - var_K ) / ( 1 - var_K ) + Y = ( Y - var_K ) / ( 1 - var_K ) + } + var K = var_K + return [C,M,Y,K] +} +function cmyk2cmy (C,M,Y,K) { + if (C.length) { + K = C[3] + Y = C[2] + M = C[1] + C = C[0] + } + var C = ( C * ( 1 - K ) + K ) + var M = ( M * ( 1 - K ) + K ) + var Y = ( Y * ( 1 - K ) + K ) + return [C,M,Y] +} + + 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 + +})() + + |
