diff options
Diffstat (limited to 'js/lib/canvas_loader.js')
| -rw-r--r-- | js/lib/canvas_loader.js | 150 |
1 files changed, 150 insertions, 0 deletions
diff --git a/js/lib/canvas_loader.js b/js/lib/canvas_loader.js new file mode 100644 index 0000000..c2ed31a --- /dev/null +++ b/js/lib/canvas_loader.js @@ -0,0 +1,150 @@ +var CanvasLoader = (function(){ + + var loader = new Loader (function(){}) + + function CanvasLoader (opt){ + this.opt = defaults(opt, { + rotate: true, + }) + this.canvas = document.createElement("canvas") + this.ctx = this.canvas.getContext('2d') + } + CanvasLoader.prototype.load_image = function(url, cb){ + loader.preloadImage(url, function(img){ + var w = this.w = img.naturalWidth + var h = this.h = img.naturalHeight + this.img = img + cb(img, w, h) + }.bind(this)) + } + CanvasLoader.prototype.scale_image_data = function(opt){ + var w, h + if (opt.scale) { + w = this.w * opt.scale + h = this.h * opt.scale + } + if (opt.w) { + w = opt.w + h = opt.w * this.h / this.w + } + else if (opt.h) { + w = opt.h * this.w / this.h + h = opt.h + } + this.canvas.width = w + this.canvas.height = h + this.ctx.save() + + if (this.opt.rotate) { + this.ctx.translate(w/2, h/2) + this.ctx.rotate( Math.PI ) + this.ctx.translate(-w/2, -h/2) + } + + this.ctx.drawImage(this.img, 0, 0, w, h) + this.ctx.restore() + return this.ctx.getImageData(0, 0, w, h) + } + CanvasLoader.prototype.gray_image_data = function(opt){ + var data = this.scale_image_data(opt) + var pixels = data.data + var len = data.width * data.height + var gray_data = new Uint8Array( len ) + var invert = this.opt.invert + + var gray, ii + for (var i = 0; i < len; i++) { + ii = i * 4 + gray = (255 - (pixels[ii] + pixels[ii+1] + pixels[ii+2]) / 3 ) * (pixels[ii+3]/255) + gray_data[i] = (invert) ? 255 - gray : gray + } + + return { + width: data.width, + height: data.height, + data: gray_data, + } + } + // in: imagedata [r,g,b,a] and a palette + // out: an array strided as [ palette offset, alpha ] + CanvasLoader.prototype.palette_image_data = function(opt){ + var data = this.scale_image_data(opt) + var pixels = data.data + var len = data.width * data.height + var palette_data = new Uint8Array( len*2 ) + var invert = this.opt.invert + + var palette = this.paletteToNumbers(opt.palette) + + var color, index, ii + for (var i = 0; i < len; i++) { + ii = i * 2 + jj = i * 4 + index = closest_to( palette, pixels.slice(jj, jj+3) ) + palette_data[ii] = index + palette_data[ii+1] = pixels[jj+3] + } + + return { + width: data.width, + height: data.height, + data: palette_data, + } + } + + CanvasLoader.prototype.paletteToStrings = function (palette){ + if (typeof palette[0] === "string") return palette + return palette.map(function(rgb){ + return "rgb(" + rgb.join(",") + ")" + }) + } + CanvasLoader.prototype.paletteToNumbers = function (palette){ + if (typeof palette[0] !== "string") return palette + var colors = palette.map(function(color){ + if (color[0] == "#") return hexToRgb(color) + return rgbStringToRgb(color) + }).filter(function(color){ return !! color }).map(function(rgb){ + return [rgb.r, rgb.g, rgb.b] + }) + return colors + } + + function hexToRgb(hex) { + // Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF") + var shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i; + hex = hex.replace(shorthandRegex, function(m, r, g, b) { + return r + r + g + g + b + b; + }); + + var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); + return result ? { + r: parseInt(result[1], 16), + g: parseInt(result[2], 16), + b: parseInt(result[3], 16) + } : null; + } + function rgbStringToRgb(rgb) { + var nums = rgb.replace(/rgba?\(/,"").replace(/\)/,"").split(",") + return { r: nums[0], g: nums[1], b: nums[2] } + } + function closest_to(palette, pixel){ + return palette.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) + } + + return CanvasLoader + +})()
\ No newline at end of file |
