diff options
| author | Jules Laplace <jules@okfoc.us> | 2016-03-22 11:36:42 -0400 |
|---|---|---|
| committer | Jules Laplace <jules@okfoc.us> | 2016-03-22 11:36:42 -0400 |
| commit | 6a30feead73dbee2d664b0099efcdc5106096c55 (patch) | |
| tree | 25685907394a49d2e22637f7e5c649904e09c4dc | |
| parent | 858587af95cfd02341cee1ec1f63c560f6944145 (diff) | |
| parent | b55c277f18a56cb6c6f85df968111f230e828b07 (diff) | |
Merge branch 'master' of lmno:ascii
| -rw-r--r-- | css/sally.css | 9 | ||||
| -rw-r--r-- | image.html | 2 | ||||
| -rw-r--r-- | index.html | 7 | ||||
| -rw-r--r-- | irssi.txt | 5 | ||||
| -rw-r--r-- | js/app.js | 1 | ||||
| -rw-r--r-- | js/clipboard.js | 17 | ||||
| -rw-r--r-- | js/draw.js | 7 | ||||
| -rw-r--r-- | js/lex.js | 12 | ||||
| -rw-r--r-- | js/matrix.js | 2 | ||||
| -rw-r--r-- | js/photo.js | 9 | ||||
| -rw-r--r-- | js/ui/brush.js | 4 | ||||
| -rw-r--r-- | js/ui/canvas.js | 2 | ||||
| -rw-r--r-- | js/ui/controls.js | 3 | ||||
| -rw-r--r-- | js/vendor/color.js | 251 | ||||
| -rw-r--r-- | js/vendor/text-encoder-lite.js | 141 | ||||
| -rw-r--r-- | webcam.html | 104 |
16 files changed, 531 insertions, 45 deletions
diff --git a/css/sally.css b/css/sally.css index 3422979..f360b0c 100644 --- a/css/sally.css +++ b/css/sally.css @@ -22,10 +22,10 @@ body { } a {display: block} -a:link, a:visited {text-decoration: none; color: #3b3740} +a:link, a:visited {text-decoration: none; color: #6b6760} +a:hover { text-decoration: underline } -{overflow: auto;} -.faded { color: 404040; } +.faded { color: #404040; } .rapper, .block { float: left; height:auto; @@ -74,7 +74,7 @@ a:link, a:visited {text-decoration: none; color: #3b3740} background-size: 4px 4px; } } -span { min-width: 8px; line-height: 15px; display: inline-block; } +span,a { min-width: 8px; line-height: 15px; display: inline-block; } .rapper { cursor: crosshair; } body.grid span { border-right: 1px solid #444; border-bottom: 1px solid #444; } body.grid div { border-left: 1px solid #444; } @@ -192,7 +192,6 @@ textarea { font-size:12pt; width: 37vw; height: 300px; background: #333; color: border: 1px solid #0f0; color: #0f0; width: 100%; - display: none; } #upload_button.uploading { background: transparent; @@ -35,7 +35,7 @@ label { min-width: 70px; display: inline-block; } <script src="js/vendor/jquery-2.1.4.min.js"></script> <script src="js/photo.js"></script> <script src="js/util.js"></script> -<script src="/dither/js/color.js"></script> +<script src="js/vendor/color.js"></script> <script> var basehref_partz = window.location.href.split("/") basehref_partz.pop() @@ -1,3 +1,4 @@ +<!-- http://jollo.org/licensing/public/LNT-1.txt --> <meta charset="UTF-8"> <link rel="stylesheet" href="css/sally.css" type="text/css" charset="utf-8" /> <link rel="stylesheet" href="css/ak.css" type="text/css" charset="utf-8" /> @@ -50,7 +51,9 @@ <span id="webcam_el" class="tool">webcam</span> <span id="load_el" class="tool">load</span> <span id="save_el" class="tool">save</span> - <span id="clear_el" class="tool">clear</span><br> + <span id="clear_el" class="tool">new</span> + <a href="http://asdf.us/im/gallery/?tag=ascii" target="_blank">gallery</a> + <br> </div> <div id="import_rapper"> @@ -93,6 +96,7 @@ // lex.opacity = 1 </script> <script src="js/vendor/colorcode.js"></script> +<script src="js/vendor/text-encoder-lite.js"></script> <script src="js/vendor/dataUriToBlob.js"></script> <script src="js/vendor/FileSaver.js"></script> @@ -122,3 +126,4 @@ <script src="js/ui/selection.js"></script> <script src="js/app.js"></script> + @@ -88,9 +88,10 @@ If you do not want to do the autojoin thing these are the commands you'd normall SETTING UP IRSSI TO AUTOJOIN #SALLY =================================== -First run irssi, then paste in these commands (changing yournick to your preferred nickname, etc) +First run irssi, then paste in these commands. +Please change YOUR_NICK_HERE to your preferred username! -/network add -nick yournick -user yournick -realname "your name" Jollo +/network add -nick YOUR_NICK_HERE -user YOUR_NICK_HERE -realname "YOUR NAME HERE" Jollo /server add -network Jollo -auto -ssl irc.jollo.org 9999 /channel add -auto #sally Jollo /save @@ -9,6 +9,7 @@ var focused var canvas, tools, palette, controls, brush, mode var current_tool, current_filetool, current_canvas +var mouse = { x: 0, y: 0 } function init () { build() diff --git a/js/clipboard.js b/js/clipboard.js index 7e683dc..9c3b1b2 100644 --- a/js/clipboard.js +++ b/js/clipboard.js @@ -122,7 +122,8 @@ var clipboard = (function () { lex.build() } } - + + current_filetool && current_filetool.blur() }, import_text: function () { @@ -240,6 +241,7 @@ var clipboard = (function () { } + // http...?a=1&b=2&b=3 -> {a: '1', b: ['2', '3']} function parse_url_search_params(url){ var params = {} url = url.split('?') @@ -270,7 +272,7 @@ var clipboard = (function () { function fetch_url(url, f, type){ type = type || 'arraybuffer' url = "/cgi-bin/proxy?" + url - // url = "http://198.199.72.134/cors/" + url + //url = "http://198.199.72.134/cors/" + url var xhr = new XMLHttpRequest() xhr.open('GET', url, true) xhr.responseType = type @@ -293,11 +295,20 @@ var clipboard = (function () { clipboard.import_colorcode(itxt.data, true) } } - + + function sally_url_convert(url){ + var png_regex = /^https?:\/\/jollo\.org\/den\/sallies\/([0-9]+)\/([^.]+)\.png$/ + var matches = url.match(png_regex) + if (!matches) return url + return 'http://jollo.org/den/sallies/' + matches[1] + '/raw-' + matches[2] + '?.txt' + // txt suffix to force asdf proxy + } + exports.load_from_location = function(){ var params = parse_url_search_params(window.location + '') if (!params.url) return var url = params.url + url = sally_url_convert(url) var type = get_filetype(url) switch (type){ case 'txt': @@ -43,18 +43,19 @@ var draw = (function(){ } function stamp (canvas, brush, x, y, erasing) { - hh = brush.w/2|0 + var hh = brush.w/2|0 brush.forEach(function(lex, s, t){ s = round( s + x-hh ) t = round( t + y-hh ) - if (lex.opacity > 0 && s >= 0 && s < canvas.w && t >= 0 && t < canvas.h) { + if (s >= 0 && s < canvas.w && t >= 0 && t < canvas.h) { + if (lex.opacity === 0 && lex.char === ' ') return; var aa = canvas.aa[t][s] undo.save_lex(s, t, aa) if (erasing) { aa.erase(lex) } else { - aa.paint(lex) + aa.stamp(lex, brush) } } }) @@ -65,10 +65,9 @@ Lex.prototype.assign = function (lex){ this.opacity = lex.opacity this.build() } -Lex.prototype.paint = function (lex){ - if (lex.opacity == 0) return +Lex.prototype.stamp = function (lex, brush){ if (brush.draw_fg) this.fg = lex.fg - if (brush.draw_bg) this.bg = lex.bg + if (brush.draw_bg && lex.opacity > 0) this.bg = lex.bg if (brush.draw_char) this.char = lex.char this.opacity = 1 this.build() @@ -85,13 +84,6 @@ Lex.prototype.erase = function (){ this.opacity = 1 this.build() } -Lex.prototype.fill = function(lex){ - this.fg = lex.fg - this.bg = lex.bg - this.char = lex.char - this.opacity = lex.opacity - this.build() -} Lex.prototype.eq = function(lex){ return lex && this.fg == lex.fg && this.bg == lex.bg && this.char == lex.char } diff --git a/js/matrix.js b/js/matrix.js index 4c8976c..275e6b6 100644 --- a/js/matrix.js +++ b/js/matrix.js @@ -112,7 +112,7 @@ Matrix.prototype.fill = function(lex){ this.char = lex.char this.opacity = lex.opacity this.forEach(function(el,x,y){ - el.fill(lex) + el.assign(lex) el.build() }) } diff --git a/js/photo.js b/js/photo.js index ae4558e..3f72cfc 100644 --- a/js/photo.js +++ b/js/photo.js @@ -108,12 +108,15 @@ var Photo = (function(){ null, null, ] - var colors = COLORS, recolor_fn = null + var colors = COLORS, recolor_fn = null, shade_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 } @@ -154,6 +157,9 @@ var Photo = (function(){ 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) } @@ -289,6 +295,7 @@ var Photo = (function(){ reds: REDS, yellows: YELLOWS, blues: BLUES, + set_shade_fn: set_shade_fn, set_recolor_fn: set_recolor_fn, set_colors: set_colors, closest_to: closest_to, diff --git a/js/ui/brush.js b/js/ui/brush.js index 8cc858f..668538f 100644 --- a/js/ui/brush.js +++ b/js/ui/brush.js @@ -41,7 +41,7 @@ var brush = (function(){ } else { fillColor = brush.bg - lex.fill(brush) + lex.assign(brush) } brush.focus(x, y) }) @@ -55,7 +55,7 @@ var brush = (function(){ lex.clear() } else { - lex.fill(brush) + lex.assign(brush) } brush.focus(x, y) }) diff --git a/js/ui/canvas.js b/js/ui/canvas.js index e241fd1..75b8f97 100644 --- a/js/ui/canvas.js +++ b/js/ui/canvas.js @@ -52,6 +52,8 @@ var canvas = current_canvas = (function(){ }) lex.span.addEventListener("mousemove", function(e){ + mouse.x = x + mouse.y = y if (is_mobile) return if (! dragging) return if (drawing) { diff --git a/js/ui/controls.js b/js/ui/controls.js index a21e293..c191cc2 100644 --- a/js/ui/controls.js +++ b/js/ui/controls.js @@ -72,6 +72,7 @@ var controls = (function(){ undo.new() undo.save_rect(0, 0, canvas.w, canvas.h) canvas.erase() + current_filetool && current_filetool.blur() } controls.webcam = new FileTool (webcam_el) @@ -119,9 +120,9 @@ var controls = (function(){ }) controls.save = new ClipboardTool (save_el) controls.save.use = function(){ + changed && clipboard.upload_png() clipboard.show() clipboard.export_mode() - clipboard.upload_png() } controls.load = new ClipboardTool (load_el) controls.load.use = function(){ diff --git a/js/vendor/color.js b/js/vendor/color.js new file mode 100644 index 0000000..ac90a3d --- /dev/null +++ b/js/vendor/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/js/vendor/text-encoder-lite.js b/js/vendor/text-encoder-lite.js new file mode 100644 index 0000000..957fd9b --- /dev/null +++ b/js/vendor/text-encoder-lite.js @@ -0,0 +1,141 @@ +// taken from https://github.com/coolaj86/TextEncoderLite/blob/master/index.js +// added polyfill at bottom + +function TextEncoderLite() { +} +function TextDecoderLite() { +} + +(function () { +'use strict'; + +// Taken from https://github.com/feross/buffer/blob/master/index.js +// Thanks Feross et al! :-) + +function utf8ToBytes (string, units) { + units = units || Infinity + var codePoint + var length = string.length + var leadSurrogate = null + var bytes = [] + var i = 0 + + for (; i < length; i++) { + codePoint = string.charCodeAt(i) + + // is surrogate component + if (codePoint > 0xD7FF && codePoint < 0xE000) { + // last char was a lead + if (leadSurrogate) { + // 2 leads in a row + if (codePoint < 0xDC00) { + if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) + leadSurrogate = codePoint + continue + } else { + // valid surrogate pair + codePoint = leadSurrogate - 0xD800 << 10 | codePoint - 0xDC00 | 0x10000 + leadSurrogate = null + } + } else { + // no lead yet + + if (codePoint > 0xDBFF) { + // unexpected trail + if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) + continue + } else if (i + 1 === length) { + // unpaired lead + if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) + continue + } else { + // valid lead + leadSurrogate = codePoint + continue + } + } + } else if (leadSurrogate) { + // valid bmp char, but last char was a lead + if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) + leadSurrogate = null + } + + // encode utf8 + if (codePoint < 0x80) { + if ((units -= 1) < 0) break + bytes.push(codePoint) + } else if (codePoint < 0x800) { + if ((units -= 2) < 0) break + bytes.push( + codePoint >> 0x6 | 0xC0, + codePoint & 0x3F | 0x80 + ) + } else if (codePoint < 0x10000) { + if ((units -= 3) < 0) break + bytes.push( + codePoint >> 0xC | 0xE0, + codePoint >> 0x6 & 0x3F | 0x80, + codePoint & 0x3F | 0x80 + ) + } else if (codePoint < 0x200000) { + if ((units -= 4) < 0) break + bytes.push( + codePoint >> 0x12 | 0xF0, + codePoint >> 0xC & 0x3F | 0x80, + codePoint >> 0x6 & 0x3F | 0x80, + codePoint & 0x3F | 0x80 + ) + } else { + throw new Error('Invalid code point') + } + } + + return bytes +} + +function utf8Slice (buf, start, end) { + var res = '' + var tmp = '' + end = Math.min(buf.length, end || Infinity) + start = start || 0; + + for (var i = start; i < end; i++) { + if (buf[i] <= 0x7F) { + res += decodeUtf8Char(tmp) + String.fromCharCode(buf[i]) + tmp = '' + } else { + tmp += '%' + buf[i].toString(16) + } + } + + return res + decodeUtf8Char(tmp) +} + +function decodeUtf8Char (str) { + try { + return decodeURIComponent(str) + } catch (err) { + return String.fromCharCode(0xFFFD) // UTF 8 invalid char + } +} + +TextEncoderLite.prototype.encode = function (str) { + var result; + + if ('undefined' === typeof Uint8Array) { + result = utf8ToBytes(str); + } else { + result = new Uint8Array(utf8ToBytes(str)); + } + + return result; +}; + +TextDecoderLite.prototype.decode = function (bytes) { + return utf8Slice(bytes, 0, bytes.length); +} + +}()); + +if (typeof TextEncoder === 'undefined') TextEncoder = TextEncoderLite +if (typeof TextDecoder === 'undefined') TextDecoder = TextDecoderLite diff --git a/webcam.html b/webcam.html index 7f76131..375a00d 100644 --- a/webcam.html +++ b/webcam.html @@ -2,17 +2,19 @@ <link rel="stylesheet" href="css/sally.css" type="text/css" charset="utf-8" /> <style> #controls { width: 220px; float: left; padding: 10px; } -label { min-width: 70px; display: inline-block; } +input { cursor: pointer; } +label { min-width: 70px; display: inline-block; cursor: pointer; } #text_style { width: 100px; } label.cbox { min-width: 50px; } +canvas { cursor: pointer; } </style> <body class="transparent"> <div id="controls"> <label></label> <span id="width_span"></span>x<span id="height_span"></span> <br> - <label for="width_el">width</label><input type="range" min="1" max="120" value="40" id="width_el"> + <label for="width_el">width</label><input type="range" min="1" max="120" value="80" id="width_el"> <br> - <label for="ratio_el">ratio</label><input type="range" min="0.0" max="8" value="2" step="0.005" id="ratio_el"><br> + <label for="ratio_el">ratio</label><input type="range" min="0.0" max="8" value="2.43" step="0.005" id="ratio_el"><br> <label for="hue_el">hue</label><input type="range" min="-1" max="1" value="0" step="0.005" id="hue_el"><br> <label for="sat_el">sat</label><input type="range" min="-1" max="1" value="0" step="0.005" id="sat_el"><br> <label for="lum_el">lum</label><input type="range" min="-1" max="1" value="0" step="0.005" id="lum_el"><br> @@ -39,16 +41,18 @@ label.cbox { min-width: 50px; } <div id="image_style"></div> </body> -<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script> -<script src="http://asdf.us/dither/js/color.js"></script> -<script src="http://asdf.us/dither/js/util.js"></script> +<script src="js/vendor/color.js"></script> +<script src="js/util.js"></script> <script src="js/photo.js"></script> <script> +var canvas = document.createElement("canvas"), ctx = canvas.getContext('2d') +image_style.appendChild(canvas) + var width = parseInt( width_span.innerHTML = width_el.value ) var ratio = parseFloat( ratio_el.value ) -var nn = $(nn_el).prop('checked') -var invert = $(invert_el).prop('checked') +var nn = nn_el.checked +var invert = invert_el.checked var width_timeout navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia; @@ -99,6 +103,69 @@ Photo.set_recolor_fn(function(rgb){ return rgb }) +var shader_index = 0 + +var SHADERS = [ + { name: "none", + shader: null + }, + { name: "pixelate", + shader: function(d, p, x, y, w, h){ + rgbpixel(d, p, x - (x%2), y, w, h) + } + }, + { name: "flop", + shader: function(d, p, x, y, w, h){ + rgbpixel(d, p, w-x-1, y, w, h) + } + }, + { name: "flip", + shader: function(d, p, x, y, w, h){ + rgbpixel(d, p, x, h-y-1, w, h) + } + }, + { name: "flip-flop", + shader: function(d, p, x, y, w, h){ + rgbpixel(d, p, w-x-1, h-y-1, w, h) + } + }, + { name: "left-mirror", + shader: function(d, p, x, y, w, h){ + rgbpixel(d, p, x < w/2 ? x : w-x-1, y, w, h) + } + }, + { name: "right-mirror", + shader: function(d, p, x, y, w, h){ + rgbpixel(d, p, x > w/2 ? x : w-x-1, y, w, h) + } + }, + { name: "top-mirror", + shader: function(d, p, x, y, w, h){ + rgbpixel(d, p, x, y > h/2 ? y : h-y-1, w, h) + } + }, + { name: "bottom-mirror", + shader: function(d, p, x, y, w, h){ + rgbpixel(d, p, x, y < h/2 ? y : h-y-1, w, h) + } + }, + { name: "four-corners", + shader: function(d, p, x, y, w, h){ + rgbpixel(d, p, + Math.round(Math.abs(w*(2*(x/w-0.5)))), + Math.round(Math.abs(h*(2*((y+0.5)/h-0.5)))), + w, h) + } + }, +] + +function rgbpixel(d, p, x, y, w, h) { + var t = 4 * (x + y*w) + p[0] = d[t] + p[1] = d[t+1] + p[2] = d[t+2] +} + // Photo.denoise = 2 var hue = 0, sat = 0, lum = 0, quant = 1 @@ -118,13 +185,13 @@ function save (){ } } nn_el.addEventListener('change', function(){ - nn = $(nn_el).prop('checked') + nn = nn_el.checked }) invert_el.addEventListener('change', function(){ - invert = $(invert_el).prop('checked') + invert = invert_el.checked }) palette_el.addEventListener('change', function(){ - var palette = $(palette_el).val() + var palette = palette_el.value Photo.set_colors( Photo[palette] ) }) ratio_el.addEventListener("input", function(){ @@ -143,7 +210,17 @@ function listen (el, obj, val) { obj[val] = parseFloat( el.value ) }) } -var canvas = document.createElement("canvas"), ctx = canvas.getContext('2d') +canvas.addEventListener("click", function(e){ + if (e.shiftKey) { + shader_index = (shader_index-1 + SHADERS.length) % SHADERS.length + } + else { + shader_index = (shader_index+1) % SHADERS.length + } + console.log("using shader", SHADERS[shader_index].name) + Photo.set_shade_fn(SHADERS[shader_index].shader) +}) + function toCanvas(rows){ var wpx = 6, hpx = 12 var rgb_colors = Photo.colors.map(function(c){ return "rgb(" + c + ")" }) @@ -156,8 +233,6 @@ function toCanvas(rows){ }) }) height_span.innerHTML = rows.length - image_style.innerHTML = "" - image_style.appendChild(canvas) } timer_el.addEventListener("click", function(){ var secs = 5; @@ -173,4 +248,3 @@ timer_el.addEventListener("click", function(){ })() }) </script> - |
