add drawing methods to Ox.Image, allow for asynchronous image manipulation
This commit is contained in:
parent
b4dc9e15ba
commit
37f3bf8f51
1 changed files with 92 additions and 32 deletions
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue