add drawing methods to Ox.Image, allow for asynchronous image manipulation

This commit is contained in:
rolux 2012-04-13 23:21:36 +02:00
parent b4dc9e15ba
commit 37f3bf8f51

View file

@ -180,6 +180,16 @@ Ox.load.Image = function(options, callback) {
});
};
/*@
drawCircle <f> Draws a circle
(point, radius, options) -> <o> The image object
point <[n]> Center (<code>[x, y]</code>)
radius <n> Radius in px
options <o> Options
color <s|'rgb(0, 0, 0)'> CSS color
fill <s|'rgba(0, 0, 0, 0)'> CSS color
width <n|1> 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 <f> Draws a line
(points, options) -> <o> The image object
points <[a]> End points (<code>[[x1, y1], [x2, y2]]</code>)
options <o> Options
color <s|'rgb(0, 0, 0)'> CSS color
width <n|1> 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 <f> Draws a path
(points, options) -> <o> The image object
points <[a]> Points (<code>[[x1, y2], [x2, y2], ...]</code>)
options <o> Options
color <s|'rgb(0, 0, 0)'> CSS color
fill <s|'rgba(0, 0, 0, 0)'> CSS color
width <n|1> 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 <f> Draws a rectangle
(point, size, options) -> <o> The image object
point <[n]> Top left corner (<code>[x, y]</code>)
size <[n]> Width and height in px (<code>[w, h]</code>)
options <o> Options
color <s|'rgb(0, 0, 0)'> CSS color
fill <s|'rgba(0, 0, 0, 0)'> CSS color
width <n|1> 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 <f> Draws text
(text, point, options) -> <o> The image object
text <s> Text
point <[n]> Top left corner (<code>[x, y]</code>)
options <o> Options
color <s|'rgb(0, 0, 0)'> CSS color
font <s|'10px sans-serif'> CSS font
outline <s|'0px rgba(0, 0, 0, 0)'> CSS border
textAlign <n|'start'> 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 <f> Pixel-wise forEach function
forEach <f> Pixel-wise forEach loop
(fn) -> <o> The image object
(fn, callback) -> <o> The image object
fn <f> Iterator function
rgba <[n]> RGBA values
xy <[n]> XY coordinates
i <n> Pixel index
callback <f> 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));
})
data[i], data[i + 1], data[i + 2], data[i + 3]
], getXY(i), i);
}, 10000, callback);
return that;
};
/*@
getSize <f> Returns width and height
() -> <o> Image size
width <n> Width in px
height <n> Height in px
@*/
that.getSize = function() {
return {width: self.width, height: self.height};
};
/*@
hue <f> Change the hue of the image
(val) -> <o> The image object
val <n> 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) -> <o> Image object with new image data
imageData <o> ImageData object
@*/
that.imageData = function() {
if (arguments.length == 0) {
return self.imageData;
@ -545,18 +607,16 @@ Ox.load.Image = function(options, callback) {
fn <f> Iterator function
rgba <[n]> RGBA values
xy <[n]> XY coordinates
i <n> 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