image to pixel art converter
A Pen by Gregor Adams on CodePen.
image to pixel art converter
A Pen by Gregor Adams on CodePen.
| "use strict"; | |
| // requestAnimationFrame() shim by Paul Irish | |
| // http://paulirish.com/2011/requestanimationframe-for-smart-animating/ | |
| window.requestAnimFrame = function () { | |
| return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function ( /* function */callback, /* DOMElement */element) { | |
| window.setTimeout(callback, 1000 / 60); | |
| }; | |
| }(); | |
| /** | |
| * Behaves the same as setInterval except uses requestAnimationFrame() where possible for better performance | |
| * @param {function} fn The callback function | |
| * @param {int} delay The delay in milliseconds | |
| */ | |
| window.requestInterval = function (fn, delay) { | |
| if (!window.requestAnimationFrame && !window.webkitRequestAnimationFrame && !(window.mozRequestAnimationFrame && window.mozCancelRequestAnimationFrame) && // Firefox 5 ships without cancel support | |
| !window.oRequestAnimationFrame && !window.msRequestAnimationFrame) return window.setInterval(fn, delay); | |
| var start = new Date().getTime(), | |
| handle = new Object(); | |
| function loop() { | |
| var current = new Date().getTime(), | |
| delta = current - start; | |
| if (delta >= delay) { | |
| fn.call(); | |
| start = new Date().getTime(); | |
| } | |
| handle.value = requestAnimFrame(loop); | |
| }; | |
| handle.value = requestAnimFrame(loop); | |
| return handle; | |
| }; | |
| /** | |
| * Behaves the same as clearInterval except uses cancelRequestAnimationFrame() where possible for better performance | |
| * @param {int|object} fn The callback function | |
| */ | |
| window.clearRequestInterval = function (handle) { | |
| window.cancelAnimationFrame ? window.cancelAnimationFrame(handle.value) : window.webkitCancelAnimationFrame ? window.webkitCancelAnimationFrame(handle.value) : window.webkitCancelRequestAnimationFrame ? window.webkitCancelRequestAnimationFrame(handle.value) : /* Support for legacy API */ | |
| window.mozCancelRequestAnimationFrame ? window.mozCancelRequestAnimationFrame(handle.value) : window.oCancelRequestAnimationFrame ? window.oCancelRequestAnimationFrame(handle.value) : window.msCancelRequestAnimationFrame ? window.msCancelRequestAnimationFrame(handle.value) : clearInterval(handle); | |
| }; | |
| class Pixel { | |
| constructor(props,target){ | |
| this.props = props; | |
| this.target = target; | |
| this.createReader(); | |
| this.createInput(); | |
| this.generateType = props.type || 'canvas'; | |
| this.downScale = props.scale || 32; | |
| this.pixelSize = (props.pixel || 1); | |
| this.pixelShape = (props.shape || 'square'); | |
| this.src(props.src); | |
| } | |
| createReader(){ | |
| this.Reader = document.createElement('canvas'); | |
| this.reader = this.Reader.getContext('2d'); | |
| } | |
| updateReader(){ | |
| if (!this.loaded) return; | |
| this.Reader.height = this.height; | |
| this.Reader.width = this.width; | |
| this.reader.drawImage(this.Input,0,0,this.width,this.height); | |
| this.getColorArray(); | |
| this.draw(); | |
| } | |
| draw(){ | |
| let drawing = this.generateByType(this.generateType); | |
| this.target.innerHTML = ''; | |
| this.target.appendChild(drawing); | |
| } | |
| onLoad(e){ | |
| this.loaded = true; | |
| this.setSize(); | |
| this.updateReader(); | |
| } | |
| createInput(){ | |
| this.Input = document.createElement('img'); | |
| this.Input.crossOrigin = 'Anonymous'; | |
| this.Input.onload = this.onLoad.bind(this); | |
| } | |
| src(src){ | |
| this.loaded = false; | |
| this.Input.src = src; | |
| } | |
| pixel(size){ | |
| this.pixelSize = size; | |
| this.updateReader(); | |
| } | |
| type(type){ | |
| this.generateType = type; | |
| this.updateReader(); | |
| } | |
| scale(scale){ | |
| this.downScale = scale; | |
| this.setSize(); | |
| this.updateReader(); | |
| } | |
| shape(shape){ | |
| this.pixelShape = shape; | |
| this.updateReader(); | |
| } | |
| resize(scale, pixel) { | |
| this.downScale = scale; | |
| this.pixelSize = pixel; | |
| this.setSize(); | |
| this.updateReader(); | |
| } | |
| setSize(){ | |
| this.height = this.Input.height/this.Input.width*this.downScale; | |
| this.width = this.downScale; | |
| this.Input.height = this.height; | |
| this.Input.width = this.width; | |
| } | |
| getColorArray(){ | |
| let data = []; | |
| if (this.Reader.height > 0) { | |
| data = this.reader.getImageData(0,0,this.width,this.height).data; | |
| } | |
| let colorArray = []; | |
| for (let i = 0; i < data.length; i += 4) { | |
| let r = data[i]; | |
| let g = data[i + 1]; | |
| let b = data[i + 2]; | |
| let a = data[i + 3]/255; | |
| let rgba = [r,g,b,a].join(','); | |
| if (a === 0) { | |
| colorArray.push('transparent'); | |
| } else { | |
| colorArray.push(`rgba(${rgba})`); | |
| } | |
| } | |
| this.colorArray = colorArray; | |
| this.generateByType(this.generateType); | |
| } | |
| drawCanvas(){ | |
| let C = document.createElement('canvas'); | |
| let $ = C.getContext('2d'); | |
| C.height = this.height*this.pixelSize; | |
| C.width = this.width*this.pixelSize; | |
| let n = -1; | |
| for (let i = 0; i < this.colorArray.length; i++ ) { | |
| $.fillStyle = this.colorArray[i]; | |
| let x = i%this.width; | |
| if (x === 0) { | |
| ++n; | |
| } | |
| if (this.colorArray[i] !== 'transparent') { | |
| let y = n; | |
| if (this.pixelShape === 'circle') { | |
| $.beginPath(); | |
| $.arc((x + .5)*this.pixelSize, (y + .5)*this.pixelSize, this.pixelSize/2, 0, 2 * Math.PI); | |
| $.closePath(); | |
| $.fill(); | |
| } else { | |
| $.fillRect(x*this.pixelSize,y*this.pixelSize,this.pixelSize,this.pixelSize); | |
| } | |
| } | |
| } | |
| return C; | |
| } | |
| drawSVG(){ | |
| let xmlns = 'http://www.w3.org/2000/svg'; | |
| let SVG = document.createElementNS(xmlns,'svg'); | |
| SVG.setAttributeNS (null, 'viewBox', `0 0 ${[this.width, this.height].join(' ')}`); | |
| SVG.setAttributeNS (null, 'height', this.height*this.pixelSize); | |
| SVG.setAttributeNS (null, 'width', this.width*this.pixelSize); | |
| let n = -1; | |
| for (let i = 0; i < this.colorArray.length; i++ ) { | |
| let x = i%this.width; | |
| if (x === 0) { | |
| ++n; | |
| } | |
| if (this.colorArray[i] !== 'transparent') { | |
| let y = n; | |
| if (this.pixelShape === 'circle') { | |
| let circle = document.createElementNS(xmlns,'circle'); | |
| circle.setAttributeNS (null, 'fill', this.colorArray[i]); | |
| circle.setAttributeNS (null, 'cx', (x + .5)); | |
| circle.setAttributeNS (null, 'cy', (y + .5)); | |
| circle.setAttributeNS (null, 'r', .5); | |
| SVG.appendChild(circle); | |
| } else { | |
| let rect = document.createElementNS(xmlns,'rect'); | |
| rect.setAttributeNS (null, 'fill', this.colorArray[i]); | |
| rect.setAttributeNS (null, 'x', x); | |
| rect.setAttributeNS (null, 'y', y); | |
| rect.setAttributeNS (null, 'width', 1); | |
| rect.setAttributeNS (null, 'height', 1); | |
| SVG.appendChild(rect); | |
| } | |
| } | |
| } | |
| return SVG; | |
| } | |
| drawShadow(){ | |
| let shadow = []; | |
| let S = document.createElement('div'); | |
| S.style.margin = `${-1*this.pixelSize}px ${this.width*this.pixelSize}px ${this.height*this.pixelSize}px ${-1*this.pixelSize}px`; | |
| S.style.width = `${this.pixelSize}px`; | |
| S.style.height = `${this.pixelSize}px`; | |
| if (this.pixelShape === 'circle') { | |
| S.style.borderRadius = '100%'; | |
| } | |
| let n = 0; | |
| for (let i = 0; i < this.colorArray.length; i++ ) { | |
| let x = (i%this.width + 1)*this.pixelSize; | |
| if (i%this.width === 0) { | |
| ++n; | |
| } | |
| if (this.colorArray[i] !== 'transparent') { | |
| let y = n*this.pixelSize; | |
| shadow.push(`${x}px ${y}px 0 ${this.colorArray[i]}`) | |
| } | |
| } | |
| S.style.boxShadow = shadow.join(',').replace(/"/g,''); | |
| return S; | |
| } | |
| drawIMG(){ | |
| let C = this.drawCanvas(); | |
| let I = document.createElement('img'); | |
| let dataURL = C.toDataURL('image/png');; | |
| I.src = dataURL; | |
| return I; | |
| } | |
| generateByType(type){ | |
| if (type === 'canvas') { | |
| return this.drawCanvas(); | |
| } else if (type === 'svg') { | |
| return this.drawSVG(); | |
| } else if (type === 'img') { | |
| return this.drawIMG(); | |
| } else if (type === 'shadow') { | |
| return this.drawShadow(); | |
| } | |
| } | |
| } |