From 37f3bf8f514366971c94839d03b1335c4a0ac611 Mon Sep 17 00:00:00 2001 From: rolux Date: Fri, 13 Apr 2012 23:21:36 +0200 Subject: [PATCH] add drawing methods to Ox.Image, allow for asynchronous image manipulation --- source/Ox.Image/Ox.Image.js | 124 ++++++++++++++++++++++++++---------- 1 file changed, 92 insertions(+), 32 deletions(-) diff --git a/source/Ox.Image/Ox.Image.js b/source/Ox.Image/Ox.Image.js index f7442a72..69e78360 100644 --- a/source/Ox.Image/Ox.Image.js +++ b/source/Ox.Image/Ox.Image.js @@ -180,6 +180,16 @@ Ox.load.Image = function(options, callback) { }); }; + /*@ + drawCircle Draws a circle + (point, radius, options) -> The image object + point <[n]> Center ([x, y]) + radius Radius in px + options Options + color CSS color + fill CSS color + width Line width in px + @*/ that.drawCircle = function(point, radius, options) { options = options || {}; that.context.strokeStyle = options.color || 'rgb(0, 0, 0)'; @@ -192,6 +202,14 @@ Ox.load.Image = function(options, callback) { return that; }; + /*@ + drawLine Draws a line + (points, options) -> The image object + points <[a]> End points ([[x1, y1], [x2, y2]]) + options Options + color CSS color + width Line width in px + @*/ that.drawLine = function(points, options, isPath) { options = options || {}; that.context.strokeStyle = options.color || 'rgb(0, 0, 0)'; @@ -203,6 +221,15 @@ Ox.load.Image = function(options, callback) { return that; }; + /*@ + drawPath Draws a path + (points, options) -> The image object + points <[a]> Points ([[x1, y2], [x2, y2], ...]) + options Options + color CSS color + fill CSS color + width Line width in px + @*/ that.drawPath = function(points, options) { var n = points.length; options = options || {}; @@ -217,6 +244,16 @@ Ox.load.Image = function(options, callback) { return that; }; + /*@ + drawRectangle Draws a rectangle + (point, size, options) -> The image object + point <[n]> Top left corner ([x, y]) + size <[n]> Width and height in px ([w, h]) + options Options + color CSS color + fill CSS color + width Line width in px + @*/ that.drawRectangle = function(point, size, options) { options = options || {}; that.context.strokeStyle = options.color || 'rgb(0, 0, 0)'; @@ -227,6 +264,17 @@ Ox.load.Image = function(options, callback) { return that; }; + /*@ + drawText Draws text + (text, point, options) -> The image object + text Text + point <[n]> Top left corner ([x, y]) + options Options + color CSS color + font CSS font + outline CSS border + textAlign CSS text-align + @*/ that.drawText = function(text, point, options) { options = options || {}; var match = ( @@ -322,10 +370,9 @@ Ox.load.Image = function(options, callback) { }); })); b = 0; - that.forEach(function(rgba, xy) { + that.forEach(function(rgba, xy, index) { // If alpha is not 255, the RGB values may not be preserved if (rgba[3] == 255) { - var index = getIndex(xy); Ox.loop(3, function(c) { // fixme: use: var data = that.context.imageData.data[i + c] var i = index + c; @@ -346,9 +393,10 @@ Ox.load.Image = function(options, callback) { }); }); } + }, function() { + that.context.putImageData(self.imageData, 0, 0); + callback(that); }); - that.context.putImageData(self.imageData, 0, 0); - callback(that); return that; }; @@ -376,9 +424,8 @@ Ox.load.Image = function(options, callback) { return mode & 1 << b ? b : null; }), done = 0, len = 4, str = ''; - that.forEach(function(rgba, xy) { + that.forEach(function(rgba, xy, index) { if (rgba[3] == 255) { - var index = getIndex(xy); Ox.loop(3, function(c) { var i = index + c; Ox.forEach(bits, function(bit) { @@ -415,16 +462,18 @@ Ox.load.Image = function(options, callback) { }); return done != 2; } - }); - try { - if (deflate) { - Ox.decodeDeflate(str, callback); - } else { - callback(Ox.decodeUTF8(str)); + }, function() { + try { + if (deflate) { + Ox.decodeDeflate(str, callback); + } else { + callback(Ox.decodeUTF8(str)); + } + } catch (e) { + error('decode'); } - } catch (e) { - error('decode'); - } + }); + return that; } /*@ @@ -473,26 +522,40 @@ Ox.load.Image = function(options, callback) { }; /*@ - forEach Pixel-wise forEach function + forEach Pixel-wise forEach loop (fn) -> The image object + (fn, callback) -> The image object fn Iterator function rgba <[n]> RGBA values xy <[n]> XY coordinates + i Pixel index + callback Callback function (if present, forEach is async) @*/ - that.forEach = function(fn) { - Ox.loop(0, self.data.length, 4, function(i) { + that.forEach = function(fn, callback) { + var data = self.data; + Ox._loop(0, data.length, 4, function(i) { return fn([ - self.data[i], self.data[i + 1], - self.data[i + 2], self.data[i + 3] - ], getXY(i)); - }) - return that; + data[i], data[i + 1], data[i + 2], data[i + 3] + ], getXY(i), i); + }, 10000, callback); + return that; }; + /*@ + getSize Returns width and height + () -> Image size + width Width in px + height Height in px + @*/ that.getSize = function() { return {width: self.width, height: self.height}; }; + /*@ + hue Change the hue of the image + (val) -> The image object + val Hue, in degrees + @*/ that.hue = function(val) { return that.map(function(rgba) { var hsl = Ox.hsl([rgba[0], rgba[1], rgba[2]]), rgb; @@ -511,7 +574,6 @@ Ox.load.Image = function(options, callback) { (imageData) -> Image object with new image data imageData ImageData object @*/ - that.imageData = function() { if (arguments.length == 0) { return self.imageData; @@ -545,18 +607,16 @@ Ox.load.Image = function(options, callback) { fn Iterator function rgba <[n]> RGBA values xy <[n]> XY coordinates + i Pixel index @*/ - that.map = function(fn) { + that.map = function(fn, callback) { self.imageData = that.context.getImageData(0, 0, self.width, self.height); self.data = self.imageData.data; - Ox.loop(0, self.data.length, 4, function(i) { - fn([ - self.data[i], self.data[i + 1], - self.data[i + 2], self.data[i + 3] - ], getXY(i)).forEach(function(val, c) { + that.forEach(function(rgba, xy, i) { + fn(rgba, xy, i).forEach(function(val, c) { self.data[i + c] = val; }); - }) + }); that.context.putImageData(self.imageData, 0, 0); return that; }; @@ -650,7 +710,7 @@ Ox.load.Image = function(options, callback) { }; that.resize = function(width, height) { - // fixme: may not work this way + // fixme: doesn't work this way that.canvas.attr({ width: width, height: height