mirror of
https://github.com/konvajs/konva.git
synced 2025-09-19 10:47:59 +08:00

I added the experimental folder to show some work on filters that can be applied to an entire layer. Multiple filters can be applied to a layer (in any order, multiple times). To hook into the layer I use: layer.on('draw', filterFunc); Eventually, I would like to move that to `layer.filterFunc` and automatically apply it after the draw. `filterFunc` looks like: function filterFunc(){ // Get pixel data and create a temporary pixel buffer for working var imageData = this.getContext().getImageData(0,0,this.getCanvas().width,this.getCanvas().height); var scratchData = this.getContext().createImageData(imageData); // Apply all filters here ColorStretch(imageData,scratchData,{}); // Copy the pixel data back this.getContext().putImageData(scratchData,0,0); } `ColorStretch` is an example of a filter. It takes 3 arguments: the original image data, image data to write the result to, and an options object.
94 lines
2.7 KiB
JavaScript
94 lines
2.7 KiB
JavaScript
Pixelate = (function () {
|
|
var Pixelate = function (src, dst, opt) {
|
|
|
|
var xBinSize = opt.width || 8,
|
|
yBinSize = opt.height || 8;
|
|
|
|
var xSize = src.width,
|
|
ySize = src.height,
|
|
srcPixels = src.data,
|
|
dstPixels = dst.data,
|
|
x, y, i;
|
|
var pixelsPerBin = xBinSize * yBinSize,
|
|
reds = [],
|
|
greens = [],
|
|
blues = [],
|
|
alphas = [],
|
|
red, green, blue, alpha,
|
|
nBinsX = Math.floor(xSize / opt.width),
|
|
nBinsY = Math.floor(ySize / opt.height),
|
|
xBinStart, xBinEnd, yBinStart, yBinEnd,
|
|
xBin, yBin;
|
|
|
|
for (xBin = 0; xBin < nBinsX; xBin += 1) {
|
|
|
|
// Add a new 'row'
|
|
reds.push([]);
|
|
greens.push([]);
|
|
blues.push([]);
|
|
alphas.push([]);
|
|
|
|
for (yBin = 0; yBin < nBinsY; yBin += 1) {
|
|
|
|
// Initialize all bins to 0
|
|
red = 0;
|
|
green = 0;
|
|
blue = 0;
|
|
alpha = 0;
|
|
|
|
// Determine which pixels are included in this bin
|
|
xBinStart = xBin * xBinSize;
|
|
xBinEnd = xBinStart + xBinSize;
|
|
yBinStart = yBin * yBinSize;
|
|
yBinEnd = yBinStart + yBinSize;
|
|
|
|
// Add all of the pixels to this bin!
|
|
for (x = xBinStart; x < xBinEnd; x += 1) {
|
|
for (y = yBinStart; y < yBinEnd; y += 1) {
|
|
i = (xSize * y + x) * 4;
|
|
red += srcPixels[i + 0];
|
|
green += srcPixels[i + 1];
|
|
blue += srcPixels[i + 2];
|
|
alpha += srcPixels[i + 3];
|
|
}
|
|
}
|
|
|
|
// Make sure the pixels are between 0-255
|
|
reds[xBin].push(red / pixelsPerBin);
|
|
greens[xBin].push(green / pixelsPerBin);
|
|
blues[xBin].push(blue / pixelsPerBin);
|
|
alphas[xBin].push(alpha / pixelsPerBin);
|
|
}
|
|
}
|
|
|
|
// For each bin
|
|
for (xBin = 0; xBin < nBinsX; xBin += 1) {
|
|
for (yBin = 0; yBin < nBinsY; yBin += 1) {
|
|
xBinStart = xBin * xBinSize;
|
|
xBinEnd = xBinStart + xBinSize;
|
|
yBinStart = yBin * yBinSize;
|
|
yBinEnd = yBinStart + yBinSize;
|
|
|
|
// Draw all of the pixels at the bin's average value
|
|
for (x = xBinStart; x < xBinEnd; x += 1) {
|
|
for (y = yBinStart; y < yBinEnd; y += 1) {
|
|
i = (xSize * y + x) * 4;
|
|
dstPixels[i + 0] = reds[xBin][yBin];
|
|
dstPixels[i + 1] = greens[xBin][yBin];
|
|
dstPixels[i + 2] = blues[xBin][yBin];
|
|
dstPixels[i + 3] = alphas[xBin][yBin];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// I probably don't need to set these to null, but I want to make sure
|
|
// the garabage collector removes them
|
|
reds = null;
|
|
greens = null;
|
|
blues = null;
|
|
alphas = null;
|
|
};
|
|
|
|
return Pixelate;
|
|
})(); |