summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--img/test/binary.gifbin0 -> 1970 bytes
-rw-r--r--img/test/black.gifbin0 -> 1355 bytes
-rw-r--r--img/test/circle.jpgbin0 -> 12002 bytes
-rw-r--r--img/test/frog.pngbin0 -> 688579 bytes
-rw-r--r--img/test/quad.gifbin0 -> 1722 bytes
-rw-r--r--img/test/rainbow.pngbin0 -> 21796 bytes
-rw-r--r--img/test/red-circle.pngbin0 -> 4355 bytes
-rw-r--r--img/test/spiral.jpgbin0 -> 829143 bytes
-rw-r--r--img/test/white.gifbin0 -> 1355 bytes
-rw-r--r--js/color.js1
-rw-r--r--js/ui/evolver.js199
-rw-r--r--js/ui/nopaint.js17
-rw-r--r--js/vendor/image-ssim.js129
-rw-r--r--simi.html146
14 files changed, 490 insertions, 2 deletions
diff --git a/img/test/binary.gif b/img/test/binary.gif
new file mode 100644
index 0000000..06f5840
--- /dev/null
+++ b/img/test/binary.gif
Binary files differ
diff --git a/img/test/black.gif b/img/test/black.gif
new file mode 100644
index 0000000..5f186b6
--- /dev/null
+++ b/img/test/black.gif
Binary files differ
diff --git a/img/test/circle.jpg b/img/test/circle.jpg
new file mode 100644
index 0000000..8de13b8
--- /dev/null
+++ b/img/test/circle.jpg
Binary files differ
diff --git a/img/test/frog.png b/img/test/frog.png
new file mode 100644
index 0000000..1f8fec9
--- /dev/null
+++ b/img/test/frog.png
Binary files differ
diff --git a/img/test/quad.gif b/img/test/quad.gif
new file mode 100644
index 0000000..95ed995
--- /dev/null
+++ b/img/test/quad.gif
Binary files differ
diff --git a/img/test/rainbow.png b/img/test/rainbow.png
new file mode 100644
index 0000000..88aaa9f
--- /dev/null
+++ b/img/test/rainbow.png
Binary files differ
diff --git a/img/test/red-circle.png b/img/test/red-circle.png
new file mode 100644
index 0000000..2dd9d81
--- /dev/null
+++ b/img/test/red-circle.png
Binary files differ
diff --git a/img/test/spiral.jpg b/img/test/spiral.jpg
new file mode 100644
index 0000000..cf67f4a
--- /dev/null
+++ b/img/test/spiral.jpg
Binary files differ
diff --git a/img/test/white.gif b/img/test/white.gif
new file mode 100644
index 0000000..cf3e695
--- /dev/null
+++ b/img/test/white.gif
Binary files differ
diff --git a/js/color.js b/js/color.js
index 23fb13f..0ba29e7 100644
--- a/js/color.js
+++ b/js/color.js
@@ -33,6 +33,7 @@ function all_hue (n) { return colors[all_color_hue_order[mod(n, 16)|0]] }
function all_inv_hue (n) { return colors[all_color_inv_order[mod(n, 16)|0]] }
function hue (n) { return colors[color_hue_order[mod(n, 11)|0]] }
function rand_hue () { return colors[color_hue_order[randint(11)]] }
+function rand_gray () { return colors[gray_names[randint(4)]] }
function inv_hue (n) { return colors[color_inv_order[mod(n, 11)|0]] }
function gray (n) { return colors[gray_names[mod(n, 4)|0]] }
function fire (n) { return colors[fire_names[mod(n, 7)|0]] }
diff --git a/js/ui/evolver.js b/js/ui/evolver.js
new file mode 100644
index 0000000..e65df20
--- /dev/null
+++ b/js/ui/evolver.js
@@ -0,0 +1,199 @@
+var evolver = (function(){
+
+ setTimeout(init)
+
+ var hash = window.location.hash
+ var opt = {
+ src: "img/sistene-chapel.jpg",
+ w: 40,
+ h: 16,
+ }
+ if (hash.length) {
+ hash.split("#").forEach(function(s){
+ var kv = s.split("=")
+ if (opt.hasOwnProperty(kv[0])) {
+ opt[kv[0]] = kv[1]
+ }
+ })
+ }
+
+ var target, last_score = 0
+ var clones = [], clone_count = 10, strokes_per_iteration = 1
+ var clone_index = 0
+ var main_canvas
+
+ var compare_w = 64, compare_h = 64
+
+ var target = document.createElement('canvas')
+ target.width = compare_w
+ target.height = compare_h
+ var t_ctx = target.getContext('2d')
+
+ var compare = document.createElement('canvas')
+ compare.width = compare_w
+ compare.height = compare_h
+ var c_ctx = compare.getContext('2d')
+
+
+ brush.rebuild = function(){
+ this.initialize()
+ }
+
+ function init () {
+ nopaint.debug = false
+
+ main_canvas = canvas
+ canvas.resize(opt.w, opt.h)
+// canvas.forEach(function(lex,x,y){
+// lex.bg = randint(16)
+// })
+ for (var i = 0; i < clone_count; i++) {
+ clones[i] = {
+ el: document.createElement("div"),
+ canvas: canvas.clone(),
+ score: 0,
+ hash: -1,
+ }
+// clones[i].canvas.append(clones[i].el)
+// clones[i].el.className = "rapper"
+// document.getElementById("clones").appendChild( clones[i].el )
+ clones[i].canvas.forEach(function(lex){
+ lex.build = noop
+ })
+ }
+ load(opt.src, go)
+ }
+ function load(src, fn){
+ var img = new Image ()
+ img.onload = function(){
+ target = drawImage(t_ctx, img)
+ last_score = 0
+ go()
+ }
+ if (opt.src.match(/^http/)) {
+ opt.src = "http://asdf.us/cgi-bin/proxy?" + opt.src
+ }
+ img.src = src
+ }
+ function drawImage (ctx, img) {
+ ctx.drawImage(img, 0, 0, compare_w, compare_h)
+ return { width: compare_w, height: compare_h, data: ctx.getImageData(0,0,compare_w,compare_h).data, channels: 4 }
+ }
+ function go () {
+ if (evolver.paused) return
+ clone_index = 0
+ paint_next()
+ }
+
+ function paint_next () {
+ canvas = clones[clone_index].canvas
+ for (var i = 0; i < strokes_per_iteration; i++) {
+ nopaint.paint()
+ }
+ render(canvas, function(c){
+ compare = drawImage(c_ctx, c)
+
+ clones[clone_index].score = ImageSSIM.compare(target, compare).ssim
+ if (++clone_index == clone_count) {
+ fitness()
+ changed = false
+ requestAnimationFrame(go)
+ }
+ else {
+ paint_next()
+ }
+ })
+ }
+ function fitness () {
+ clones.sort(function(a,b){ return b.score - a.score })
+
+ var best_clone, next_best_clone, third_best_clone
+ var clones_to_keep
+
+ var max_score = clones[0].score
+
+// console.log(clones.filter(function(c,i){ return i < 10 }).map(function(c){ return c.score.toFixed(2) }).join(" "))
+
+ if (max_score < last_score) {
+ console.log("no improvement [%s] [%s]", max_score.toFixed(3), last_score.toFixed(3))
+ clones_to_keep = 2
+ best_clone = main_canvas
+ next_best_clone = clones[0].canvas
+ third_best_clone = clones[1].canvas
+ }
+ else {
+ last_score = max_score
+
+ clones_to_keep = 3
+ best_clone = clones[0].canvas
+ next_best_clone = clones[1].canvas
+ third_best_clone = clones[2].canvas
+
+ console.log("top clone [%s]", max_score.toFixed(5))
+ main_canvas.forEach(function(lex,x,y){
+ lex.assign( best_clone.getCell(x,y) )
+ })
+ }
+
+ var best_clone = clones[0].canvas
+ clones.forEach(function(clone, i){
+ if (i < clones_to_keep) return
+ var clone_to_copy
+ if (i < clones.length / 4) {
+ clone_to_copy = third_best_clone
+ }
+ else if (i < clones.length / 2) {
+ clone_to_copy = next_best_clone
+ }
+ else {
+ clone_to_copy = best_clone
+ }
+ clone.canvas.forEach(function(lex,x,y) {
+ lex.assign( clone_to_copy.getCell(x,y) )
+ })
+ })
+
+ }
+
+/*
+ function check () {
+ clipboard.export_canvas(function(canvas){
+ var hash = simi.hash(canvas)
+ var score = simi.compare(hash, target)
+ if (score > last_score) {
+ last_score = score
+ console.log(score.toFixed(3), "PAINT")
+ nopaint.paint()
+ }
+ else {
+ console.log(score.toFixed(3), "NO")
+ nopaint.no()
+ }
+ requestAnimationFrame(check)
+ })
+ }
+*/
+
+ var buffer_canvas = document.createElement('canvas')
+
+ function render (canvas, done_fn) {
+ var opts = {
+ palette: 'mirc',
+ font: 'fixedsys_8x15',
+ fg: 0,
+ bg: 1,
+ canvas: buffer_canvas
+ }
+ opts.done = function(c){
+ done_fn(c)
+ }
+ colorcode.to_canvas(canvas.mirc(), opts)
+ }
+
+ return {
+ paused: false,
+ pause: function(){
+ evolver.paused = ! evolver.paused
+ }
+ }
+})() \ No newline at end of file
diff --git a/js/ui/nopaint.js b/js/ui/nopaint.js
index bf94bdc..d3741a9 100644
--- a/js/ui/nopaint.js
+++ b/js/ui/nopaint.js
@@ -33,6 +33,7 @@ var nopaint = (function(){
oktween.raf = function(){}
var nopaint = {}
+ nopaint.debug = true
nopaint.delay = nopaint.normal_delay = 100
nopaint.turbo_delay = 0
nopaint.tool = null
@@ -83,7 +84,7 @@ var nopaint = (function(){
last_tool && last_tool.finish()
nopaint.tool = nopaint.get_random_tool( last_tool )
nopaint.tool.start( last_tool )
- console.log("> %s", nopaint.tool.type)
+ nopaint.debug && console.log("> %s", nopaint.tool.type)
}
nopaint.add_tool = function(fn){
nopaint.tools[fn.type] = fn
@@ -143,6 +144,9 @@ var nopaint = (function(){
upload_interval: 100,
step: 0,
timeout: null,
+ delay: function(){
+ return nopaint.is_turbo ? randrange(150, 300) : randrange(400, 800)
+ },
reset: function(){
this.no_count = 0
this.paint_count = 0
@@ -153,7 +157,7 @@ var nopaint = (function(){
},
play: function(){
clearTimeout(this.timeout)
- var delay = nopaint.is_turbo ? randrange(150, 300) : randrange(400, 800)
+ var delay = this.delay()
this.timeout = setTimeout(this.play.bind(this), delay)
this.check_fitness()
this.step += 1
@@ -451,6 +455,14 @@ var nopaint = (function(){
},
})
+ var GrayBrush = SolidBrush.extend({
+ type: "hue",
+ recolor: function(){
+ this.fg = this.bg = rand_gray()
+ this.char = " "
+ },
+ })
+
var LetterBrush = SolidBrush.extend({
type: "letter",
recolor: function(){
@@ -742,6 +754,7 @@ var nopaint = (function(){
nopaint.add_tool( new EraseBrush({ weight: 5 }) )
nopaint.add_tool( new RandomBrush({ weight: 4 }) )
nopaint.add_tool( new HueBrush({ weight: 5 }) )
+ nopaint.add_tool( new GrayBrush({ weight: 5 }) )
nopaint.add_tool( new LetterBrush({ weight: 2 }) )
nopaint.add_tool( new RandomLetterBrush({ weight: 12 }) )
nopaint.add_tool( new CloneBrush({ weight: 8 }) )
diff --git a/js/vendor/image-ssim.js b/js/vendor/image-ssim.js
new file mode 100644
index 0000000..e1f07b4
--- /dev/null
+++ b/js/vendor/image-ssim.js
@@ -0,0 +1,129 @@
+var ImageSSIM;
+(function (ImageSSIM) {
+ 'use strict';
+ /**
+ * Grey = 1, GreyAlpha = 2, RGB = 3, RGBAlpha = 4
+ */
+ (function (Channels) {
+ Channels[Channels["Grey"] = 1] = "Grey";
+ Channels[Channels["GreyAlpha"] = 2] = "GreyAlpha";
+ Channels[Channels["RGB"] = 3] = "RGB";
+ Channels[Channels["RGBAlpha"] = 4] = "RGBAlpha";
+ })(ImageSSIM.Channels || (ImageSSIM.Channels = {}));
+ var Channels = ImageSSIM.Channels;
+ /**
+ * Entry point.
+ * @throws new Error('Images have different sizes!')
+ */
+ function compare(image1, image2, windowSize, K1, K2, luminance, bitsPerComponent) {
+ if (windowSize === void 0) { windowSize = 8; }
+ if (K1 === void 0) { K1 = 0.01; }
+ if (K2 === void 0) { K2 = 0.03; }
+ if (luminance === void 0) { luminance = true; }
+ if (bitsPerComponent === void 0) { bitsPerComponent = 8; }
+ if (image1.width !== image2.width || image1.height !== image2.height) {
+ throw new Error('Images have different sizes!');
+ }
+ /* tslint:disable:no-bitwise */
+ var L = (1 << bitsPerComponent) - 1;
+ /* tslint:enable:no-bitwise */
+ var c1 = Math.pow((K1 * L), 2), c2 = Math.pow((K2 * L), 2), numWindows = 0, mssim = 0.0;
+ var mcs = 0.0;
+ function iteration(lumaValues1, lumaValues2, averageLumaValue1, averageLumaValue2) {
+ // calculate variance and covariance
+ var sigxy, sigsqx, sigsqy;
+ sigxy = sigsqx = sigsqy = 0.0;
+ for (var i = 0; i < lumaValues1.length; i++) {
+ sigsqx += Math.pow((lumaValues1[i] - averageLumaValue1), 2);
+ sigsqy += Math.pow((lumaValues2[i] - averageLumaValue2), 2);
+ sigxy += (lumaValues1[i] - averageLumaValue1) * (lumaValues2[i] - averageLumaValue2);
+ }
+ var numPixelsInWin = lumaValues1.length - 1;
+ sigsqx /= numPixelsInWin;
+ sigsqy /= numPixelsInWin;
+ sigxy /= numPixelsInWin;
+ // perform ssim calculation on window
+ var numerator = (2 * averageLumaValue1 * averageLumaValue2 + c1) * (2 * sigxy + c2);
+ var denominator = (Math.pow(averageLumaValue1, 2) + Math.pow(averageLumaValue2, 2) + c1) * (sigsqx + sigsqy + c2);
+ mssim += numerator / denominator;
+ mcs += (2 * sigxy + c2) / (sigsqx + sigsqy + c2);
+ numWindows++;
+ }
+ // calculate SSIM for each window
+ Internals._iterate(image1, image2, windowSize, luminance, iteration);
+ return { ssim: mssim / numWindows, mcs: mcs / numWindows };
+ }
+ ImageSSIM.compare = compare;
+ /**
+ * Internal functions.
+ */
+ var Internals;
+ (function (Internals) {
+ function _iterate(image1, image2, windowSize, luminance, callback) {
+ var width = image1.width, height = image1.height;
+ for (var y = 0; y < height; y += windowSize) {
+ for (var x = 0; x < width; x += windowSize) {
+ // avoid out-of-width/height
+ var windowWidth = Math.min(windowSize, width - x), windowHeight = Math.min(windowSize, height - y);
+ var lumaValues1 = _lumaValuesForWindow(image1, x, y, windowWidth, windowHeight, luminance), lumaValues2 = _lumaValuesForWindow(image2, x, y, windowWidth, windowHeight, luminance), averageLuma1 = _averageLuma(lumaValues1), averageLuma2 = _averageLuma(lumaValues2);
+ callback(lumaValues1, lumaValues2, averageLuma1, averageLuma2);
+ }
+ }
+ }
+ Internals._iterate = _iterate;
+ function _lumaValuesForWindow(image, x, y, width, height, luminance) {
+ var array = image.data, lumaValues = new Float32Array(new ArrayBuffer(width * height * 4)), counter = 0;
+ var maxj = y + height;
+ for (var j = y; j < maxj; j++) {
+ var offset = j * image.width;
+ var i = (offset + x) * image.channels;
+ var maxi = (offset + x + width) * image.channels;
+ switch (image.channels) {
+ case 1 /* Grey */:
+ while (i < maxi) {
+ // (0.212655 + 0.715158 + 0.072187) === 1
+ lumaValues[counter++] = array[i++];
+ }
+ break;
+ case 2 /* GreyAlpha */:
+ while (i < maxi) {
+ lumaValues[counter++] = array[i++] * (array[i++] / 255);
+ }
+ break;
+ case 3 /* RGB */:
+ if (luminance) {
+ while (i < maxi) {
+ lumaValues[counter++] = (array[i++] * 0.212655 + array[i++] * 0.715158 + array[i++] * 0.072187);
+ }
+ }
+ else {
+ while (i < maxi) {
+ lumaValues[counter++] = (array[i++] + array[i++] + array[i++]);
+ }
+ }
+ break;
+ case 4 /* RGBAlpha */:
+ if (luminance) {
+ while (i < maxi) {
+ lumaValues[counter++] = (array[i++] * 0.212655 + array[i++] * 0.715158 + array[i++] * 0.072187) * (array[i++] / 255);
+ }
+ }
+ else {
+ while (i < maxi) {
+ lumaValues[counter++] = (array[i++] + array[i++] + array[i++]) * (array[i++] / 255);
+ }
+ }
+ break;
+ }
+ }
+ return lumaValues;
+ }
+ function _averageLuma(lumaValues) {
+ var sumLuma = 0.0;
+ for (var i = 0; i < lumaValues.length; i++) {
+ sumLuma += lumaValues[i];
+ }
+ return sumLuma / lumaValues.length;
+ }
+ })(Internals || (Internals = {}));
+})(ImageSSIM || (ImageSSIM = {})); \ No newline at end of file
diff --git a/simi.html b/simi.html
new file mode 100644
index 0000000..4d8f47a
--- /dev/null
+++ b/simi.html
@@ -0,0 +1,146 @@
+<!-- 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" />
+
+<body class="loading">
+
+ <div id="workspace_rapper">
+ <div id="canvas_rapper" class="rapper"></div>
+ </div>
+
+ <div id="ui_rapper">
+ <div class="block" id="tools_block">
+ <div id="palette_rapper"></div>
+ <div id="secret_rapper">
+ <span id="experimental_palette_toggle">.</span>
+ <!-- <span id="nopaint_toggle">N</span> -->
+ </div>
+ <div id="letters_rapper"></div>
+ <div id="custom_rapper"></div>
+ </div>
+ <div id="brush_container" class="block">
+ <div id="brush_rapper">
+ </div>
+ <br>
+ <span id="fg_checkbox" class="tool">x fg</span><br>
+ <span id="bg_checkbox" class="tool">x bg</span><br>
+ <span id="char_checkbox" class="tool">x char</span><br>
+ <br>
+ <span id="add_custom_el" class="tool">+ add</span>
+ <div id="nopaint_rapper">
+ <br>
+ <span id="nopaint_no_el" class="tool">no</span><br>
+ <span id="nopaint_paint_el" class="tool">paint</span><br>
+ <span id="nopaint_pause_el" class="tool hidden">pause</span><br>
+ </div>
+ </div>
+ <div id="tools_rapper" class="block">
+ <span id="square_el" class="tool">square</span><br>
+ <span id="circle_el" class="tool">circle</span><br>
+ <span id="cross_el" class="tool">cross</span><br>
+ <span id="text_el" class="tool">text</span><br>
+ <span id="fill_el" class="tool">fill</span><br>
+ <span id="select_el" class="tool">select</span><br>
+ <br>
+ <span id="undo_el" class="tool hidden">undo</span><br>
+ <span id="redo_el" class="tool hidden">redo</span><br>
+ <br>
+ <span id="grid_el" class="tool">_ grid</span><br>
+ <span id="rotate_checkbox" class="tool">_ rotate</span><br>
+ <span id="vertical_checkbox" class="tool">_ vertical</span><br>
+ <br>
+ brush size: <span id="brush_w_el" class="ed">5</span> x <span id="brush_h_el" class="ed">5</span><br>
+ canvas size: <span id="canvas_w_el" class="ed">100</span> x <span id="canvas_h_el" class="ed">30</span><br>
+ </div>
+
+ <div id="textarea_mode" style="float: left">
+ <div>
+ <span id="shader_el" class="tool">shader</span>
+ <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">new</span>
+ <a href="http://asdf.us/ascii/doc/" target="_blank">doc</a>
+ <a href="http://asdf.us/im/gallery/?tag=ascii" target="_blank">gallery</a>
+ <br>
+ </div>
+
+ <div id="import_rapper">
+ <span id="format_el">ascii *irssi mirc</span>
+ <span id="import_buttons">
+ <button id="import_button">import</button>
+ </span>
+ <div id="gallery_rapper">
+ <input id="username_input" type="text" placeholder="username">
+ <input id="upload_input" type="text" placeholder="uploaded url">
+ <button id="export_button">export</button>
+ <button id="save_button">save</button>
+ <button id="upload_button">upload</button>
+ </div><br>
+ <div id="cutoff_warning_el">colorcode is too wide for irc and is cutoff</div>
+ <textarea id="import_textarea"></textarea>
+ </div>
+
+ <div id="shader_rapper">
+ <span id="animate_checkbox" class="tool">_ animate</span>
+ to <span id="shader_target_el">*canvas brush selection</span>
+ <span id="shader_fps_el" class="hidden faded"></span><br>
+ <textarea id="shader_textarea"></textarea>
+ </div>
+ </div>
+
+ </div>
+ <div id="webcam_rapper" class="transparent">
+ <span class="close" id="webcam_close">x</span>
+ <iframe id="webcam_iframe"></iframe>
+ </div>
+
+ <input type="text" id="cursor_input">
+
+<div id="clones"></div>
+
+</body>
+<script type="text/javascript-shader" id="demo_shader">
+// lex.bg = hue((x+y*y+t/10)/20)
+// lex.fg = colors.white
+// lex.char = " "
+// 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>
+<script src="js/vendor/oktween.js"></script>
+<script src="js/vendor/image-ssim.js"></script>
+
+<script src="js/util.js"></script>
+<script src="js/png.js"></script>
+<script src="js/unicode.js"></script>
+<script src="js/color.js"></script>
+<script src="js/undo.js"></script>
+<script src="js/clipboard.js"></script>
+<script src="js/upload.js"></script>
+<script src="js/user.js"></script>
+
+<script src="js/lex.js"></script>
+<script src="js/matrix.js"></script>
+<script src="js/blit.js"></script>
+<script src="js/tool.js"></script>
+<script src="js/shader.js"></script>
+<script src="js/draw.js"></script>
+
+<script src="js/ui/brush.js"></script>
+<script src="js/ui/canvas.js"></script>
+<script src="js/ui/custom.js"></script>
+<script src="js/ui/keys.js"></script>
+<script src="js/ui/controls.js"></script>
+<script src="js/ui/palette.js"></script>
+<script src="js/ui/letters.js"></script>
+<script src="js/ui/selection.js"></script>
+<script src="js/ui/nopaint.js"></script>
+<script src="js/ui/evolver.js"></script>
+
+<script src="js/app.js"></script>
+