-
-
Save leandrodaher/44cfe2b218eff26bb5e5ff7000a4094a to your computer and use it in GitHub Desktop.
Canvas fun
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <html> | |
| <head> | |
| <style> | |
| body { | |
| margin: 0; | |
| padding: 0; | |
| } | |
| canvas { | |
| width: 100%; | |
| height: 100%; | |
| image-rendering: -moz-crisp-edges; | |
| image-rendering: -webkit-optimize-contrast; | |
| } | |
| .newCan { | |
| width: 100%; | |
| height: 100%; | |
| image-rendering: -moz-crisp-edges; | |
| image-rendering: -webkit-optimize-contrast; | |
| } | |
| </style> | |
| <script> | |
| Object.size = function(obj) { | |
| var size = 0, key; | |
| for (key in obj) { | |
| if (obj.hasOwnProperty(key)) size++; | |
| } | |
| return size; | |
| }; | |
| var requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame; | |
| window.onload = function () { | |
| var canvas = document.getElementById('main'); | |
| var canvasWidth = canvas.width; | |
| var canvasHeight = canvas.height; | |
| var ctx = canvas.getContext('2d'); | |
| var imageData = ctx.getImageData(0, 0, canvasWidth, canvasHeight); | |
| var data = imageData.data; | |
| var buf = new ArrayBuffer(imageData.data.length); | |
| var buf8 = new Uint8ClampedArray(buf); | |
| var data32 = new Uint32Array(buf); | |
| var pixelSet = new Uint8ClampedArray(new ArrayBuffer(imageData.data.length)); | |
| var pixelAreaCheck = new Uint8ClampedArray(new ArrayBuffer(imageData.data.length)); | |
| var PIXELS_PER_ITERATION = 50; | |
| var NUM_COLORS = 16; | |
| var totalPixelsSet = 0; | |
| var palette = {}; | |
| var currentIndex = 0; | |
| var MAX_BALAGAN = 60*60*24*10000; | |
| function choosePalette() { | |
| for (var i = 0; i < NUM_COLORS; i++) { | |
| palette[i] = randomColor(); | |
| } | |
| } | |
| /** | |
| * Place random pixels on the canvas | |
| */ | |
| function step1() { | |
| for (var i = currentIndex; i < currentIndex + PIXELS_PER_ITERATION; i++) { | |
| var pixel = randomPixel(); | |
| var color = palette[parseInt(Math.random() * 16)]; | |
| setPixelIndex(pixel, color); | |
| } | |
| currentIndex += PIXELS_PER_ITERATION; | |
| if (totalPixelsSet < (canvas.width * canvas.height)) { | |
| requestAnimationFrame(step1); | |
| } else { | |
| pixelSet = new Uint8ClampedArray(new ArrayBuffer(imageData.data.length)); | |
| totalPixelsSet = 0; | |
| requestAnimationFrame(step2); | |
| } | |
| } | |
| // file://localhost/Users/ron/Dropbox/Ron/src/shirley/becoming.html | |
| function step2() { | |
| var pixel; | |
| for (var i = currentIndex; i < currentIndex + PIXELS_PER_ITERATION; i++) { | |
| pixel = randomPixel(); | |
| if (pixelIsFree(pixel)) { | |
| setPixelIndex(pixel, randomNeighborColor(pixel)); | |
| } | |
| // check if it's not free | |
| if (!pixelIsFree(pixel) && (pixelSet[pixel] == 0)) { | |
| pixelSet[pixel] = 1; | |
| totalPixelsSet++; | |
| } | |
| } | |
| if (totalPixelsSet < (canvas.width * canvas.height)) { | |
| requestAnimationFrame(step2); | |
| } else { | |
| pixelSet = new Uint8ClampedArray(new ArrayBuffer(imageData.data.length)); | |
| totalPixelsSet = 0; | |
| requestAnimationFrame(step3); | |
| } | |
| } | |
| function step3() { | |
| if (getNumColors() <= 2) { | |
| alert("done"); | |
| return; | |
| } | |
| var pixel = randomPixel(); | |
| var oldColor = getColor(pixel); | |
| // var newColor = palette[parseInt(Math.random() * 16)]; | |
| pixelAreaCheck = new Uint8ClampedArray(new ArrayBuffer(imageData.data.length)); | |
| var adjacentColors = getAdjacentBlockColors(pixel, oldColor); | |
| var newColor = pickRandomProperty(adjacentColors); | |
| if (newColor == null) { | |
| alert("Error, no adjacent color"); | |
| } | |
| newColor = newColor.split(","); | |
| for (i = 0; i < newColor.length; i++) { | |
| newColor[i] = parseInt(newColor[i]); | |
| } | |
| paintPixels(pixel, oldColor, newColor); | |
| requestAnimationFrame(step3); | |
| } | |
| function pickRandomProperty(obj) { | |
| var result = null; | |
| var count = 0; | |
| for (var prop in obj) | |
| if (Math.random() < 1/++count) | |
| result = prop; | |
| return result; | |
| } | |
| function getAdjacentBlockColors(pixel, oldColor) { | |
| var result = {}; | |
| if (pixelAreaCheck[pixel] == 1) { | |
| return result; | |
| } | |
| if (pixel >= canvas.width * canvas.height || pixel < 0) { | |
| return result; | |
| } | |
| pixelAreaCheck[pixel] = 1; | |
| var pixelColor = getColor(pixel) | |
| // Check if its a new color | |
| if (!sameColorArray(pixelColor, oldColor)) { | |
| result[pixelColor] = 1; | |
| return result; | |
| } | |
| var resultUp = getAdjacentBlockColors(pixel - canvas.width, oldColor); | |
| var resultDown = getAdjacentBlockColors(pixel + canvas.width, oldColor); | |
| var resultLeft = getAdjacentBlockColors(pixel - 1, oldColor); | |
| var resultRight = getAdjacentBlockColors(pixel + 1, oldColor); | |
| merge_options(result, resultUp); | |
| merge_options(result, resultDown); | |
| merge_options(result, resultLeft); | |
| merge_options(result, resultRight); | |
| return result; | |
| } | |
| function merge_options(obj1,obj2){ | |
| for (var attrname in obj2) { obj1[attrname] = obj2[attrname]; } | |
| return obj1; | |
| } | |
| function paintPixels(pixel, oldColor, newColor) { | |
| var pixelsToPaint = []; | |
| if (sameColorArray(oldColor, newColor)) { | |
| return; | |
| } | |
| pixelsToPaint.push(pixel); | |
| while (pixelsToPaint.length > 0) { | |
| var currentPixel = pixelsToPaint.pop(); | |
| if (!(sameColorArray(getColor(currentPixel), oldColor))) continue; | |
| if (currentPixel < 0 || currentPixel > canvas.width * canvas.height) { | |
| continue; | |
| } | |
| console.log(currentPixel); | |
| setPixelIndex(currentPixel, newColor); | |
| if (sameColorArray(getColor(currentPixel-1), oldColor)) pixelsToPaint.push(currentPixel-1); | |
| if (sameColorArray(getColor(currentPixel+1), oldColor)) pixelsToPaint.push(currentPixel+1); | |
| if (sameColorArray(getColor(currentPixel-canvas.width), oldColor)) pixelsToPaint.push(currentPixel-canvas.width); | |
| if (sameColorArray(getColor(currentPixel+canvas.width), oldColor)) pixelsToPaint.push(currentPixel+canvas.width); | |
| } | |
| } | |
| function sameColorArray(color1, color2) { | |
| var c20 = ~~ (color2[0]+0.5); | |
| var c21 = ~~ (color2[1]+0.5); | |
| var c22 = ~~ (color2[2]+0.5); | |
| return ( color1[0] == c20 && //Math.round(color2[0])) && | |
| color1[1] == c21 && // Math.round(color2[1])) && | |
| color1[2] == c22 ); | |
| } | |
| function paintPixelsRecursive(pixel, oldColor, newColor) { | |
| setPixelIndex(pixel, newColor); | |
| if (sameColor(getColor(pixel-1), oldColor)) paintPixels(pixel-1, oldColor, newColor); | |
| if (sameColor(getColor(pixel+1), oldColor)) paintPixels(pixel+1, oldColor, newColor); | |
| if (sameColor(getColor(pixel-canvas.width), oldColor)) paintPixels(pixel-canvas.width, oldColor, newColor); | |
| if (sameColor(getColor(pixel+canvas.width), oldColor)) paintPixels(pixel+canvas.width, oldColor, newColor); | |
| } | |
| function getNumColors() { | |
| var colors = {}; | |
| for (var i = 0; i < canvas.width * canvas.height; i++) { | |
| var color = getColor(i); | |
| colors[color[0] + color[1] << 8 + color[2] << 16] = true; | |
| } | |
| var size = 0; | |
| for (var key in colors) { | |
| if (colors.hasOwnProperty(key)) size++; | |
| } | |
| return size; | |
| } | |
| function pixelIsFree(pixel) { | |
| var colorAtPixel = getColor(pixel); | |
| var pixelsSameCount = 0; | |
| if (sameColor(colorAtPixel, pixel-1)) pixelsSameCount++; | |
| if (sameColor(colorAtPixel, pixel+1)) pixelsSameCount++; | |
| if (sameColor(colorAtPixel, pixel-canvas.width)) pixelsSameCount++; | |
| if (sameColor(colorAtPixel, pixel+canvas.width)) pixelsSameCount++; | |
| pixelFree = (pixelsSameCount < 1); | |
| return pixelFree; | |
| } | |
| function getPixelArrayToMatch() { | |
| var pixelArray = []; | |
| for (var i = currentIndex; i < currentIndex + PIXELS_PER_ITERATION; i++) { | |
| pixel = randomPixel(); | |
| pixelArray.push(pixel); | |
| } | |
| return pixelArray; | |
| } | |
| function randomNeighborColor(pixel) { | |
| var options = []; | |
| if (pixel > 0) { | |
| options.push(getColor(pixel-1)); | |
| } | |
| if (pixel < canvas.width * canvas.height) { | |
| options.push(getColor(pixel+1)); | |
| } | |
| if (pixel > canvas.width) { | |
| options.push(getColor(pixel-canvas.width)); | |
| } | |
| if (pixel < canvas.width * (canvas.height - 1)) { | |
| options.push(getColor(pixel+canvas.width)); | |
| } | |
| return options[parseInt(Math.random() * options.length)]; | |
| } | |
| function getColor(pixel) { | |
| var index = pixel * 4; | |
| if (pixel < 0 || pixel > canvas.width * canvas.height) { | |
| return [0,0,0]; | |
| } | |
| return [data[index], data[index+1], data[index+2]]; | |
| } | |
| function sameColor(color, pixel) { | |
| var index = pixel * 4; | |
| return (data[index] == color[0]) && (data[index+1] == color[1]) && (data[index+2] == color[2]); | |
| } | |
| function setPixelIndex(pixel, color) { | |
| pixelSet[pixel] = 1; | |
| totalPixelsSet++; | |
| var index = pixel * 4; | |
| var c0 = ~~ (color[0]+0.5); | |
| var c1 = ~~ (color[1]+0.5); | |
| var c2 = ~~ (color[2]+0.5); | |
| data[index] = c0; //(0.5 + (color[0])) | 0; // red | |
| data[++index] = c1; //(0.5 + (color[1])) | 0; // green | |
| data[++index] = c2; //(0.5 + (color[2])) | 0; // blue | |
| data[++index] = 255; // alpha | |
| ctx.putImageData(imageData, 0, 0); | |
| ctx.translate(1.5, 1.5); | |
| } | |
| function setPixel(x, y, color) { | |
| var index = (y * canvasWidth + x) * 4; | |
| var c0 = ~~ (color[0]+0.5); | |
| var c1 = ~~ (color[1]+0.5); | |
| var c2 = ~~ (color[2]+0.5); | |
| data[index] = c0; // red | |
| data[++index] = c1; // green | |
| data[++index] = c2; // blue | |
| data[++index] = 255; // alpha | |
| ctx.putImageData(imageData, 0, 0); | |
| ctx.translate(1.5, 1.5); | |
| } | |
| function resetAlpha() { | |
| for (var i = 0; i < canvas.width * canvas.height; imageData) { | |
| data[i * 4 + 3] = 0; | |
| } | |
| } | |
| function randomPixel(allowOverride) { | |
| var index; | |
| var attempts = 10; | |
| if (allowOverride == true) { | |
| return parseInt(Math.random() * canvas.width * canvas.height); | |
| } | |
| do { | |
| if (attempts > 0) { | |
| index = parseInt(Math.random() * canvas.width * canvas.height); | |
| attempts--; | |
| } else { | |
| index++; | |
| } | |
| if (index >= canvas.width * canvas.height) { | |
| index = 0; | |
| } | |
| } while (pixelSet[index] != 0); | |
| return index; | |
| } | |
| function randomColor() { | |
| var h = Math.random(); // all colors | |
| var s = Math.random() * 0.5; // add 0 to 50% gray | |
| var l = Math.random() * 0.4 + 0.4; // add 50% to 100% light | |
| return hslToRgb(h, s, l); | |
| } | |
| function hslToRgb(h, s, l){ | |
| var r, g, b; | |
| if(s == 0){ | |
| r = g = b = l; // achromatic | |
| }else{ | |
| function hue2rgb(p, q, t){ | |
| if(t < 0) t += 1; | |
| if(t > 1) t -= 1; | |
| if(t < 1/6) return p + (q - p) * 6 * t; | |
| if(t < 1/2) return q; | |
| if(t < 2/3) return p + (q - p) * (2/3 - t) * 6; | |
| return p; | |
| } | |
| var q = l < 0.5 ? l * (1 + s) : l + s - l * s; | |
| var p = 2 * l - q; | |
| r = hue2rgb(p, q, h + 1/3); | |
| g = hue2rgb(p, q, h); | |
| b = hue2rgb(p, q, h - 1/3); | |
| } | |
| return [r * 255, g * 255, b * 255]; | |
| } | |
| choosePalette(); | |
| step1(); | |
| // 32 bit works only on chrome 20 | |
| /* | |
| for (var y = 0; y < canvasHeight; ++y) { | |
| for (var x = 0; x < canvasWidth; ++x) { | |
| var value = x * y & 0xff; | |
| value = 128; | |
| data32[y * canvasWidth + x] = | |
| (255 << 24) | // alpha | |
| (value << 16) | // blue | |
| (value << 8) | // green | |
| value; // red | |
| } | |
| } | |
| imageData.data.set(buf8); | |
| */ | |
| ctx.putImageData(imageData, 0, 0); | |
| } | |
| </script> | |
| </head> | |
| <body> | |
| <canvas id="main" class="newCan" width="300px" height="400px"></canvas> | |
| </body> | |
| </html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment