oxjs/source/Ox.Image/Ox.Image.js
2011-06-21 11:16:23 +02:00

260 lines
7.9 KiB
JavaScript

Ox.load.Image = function(options, callback) {
Ox.Image = function() {
var self = {},
that = {};
if (arguments.length == 2) {
self.src = arguments[0];
self.callback = arguments[1];
} else {
self.width = arguments[0];
self.height = arguments[1];
self.callback = arguments[2];
}
function getIndex(x, y) {
return (Ox.mod(x, self.width) + Ox.mod(y * self.width, self.width * self.height)) * 4;
}
function getXY(index) {
index /= 4;
return [index % self.width, Math.floor(index / self.width)];
}
self.filter = function(filter, bias) {
bias = bias || 0;
var filterSize = Math.sqrt(filter.length),
d = (filterSize - 1) / 2,
imageData = self.context.getImageData(0, 0, self.width, self.height),
imageDataNew = self.context.createImageData(self.width, self.height),
data = [],
n = imageData.data.length,
xy, filterIndex, pixelIndex;
for (var i = 0; i < n; i += 4) {
for (var c = 0; c < 3; c++) {
data[i + c] = 0;
}
filterIndex = 0;
xy = getXY(i);
for (var x = -d; x <= d; x++) {
for (var y = -d; y <= d; y++) {
pixelIndex = getIndex(xy[0] + x, xy[1] + y);
for (var c = 0; c < 3; c++) {
data[i + c] += imageData.data[pixelIndex + c] * filter[filterIndex];
}
filterIndex++;
}
}
}
for (var i = 0; i < n; i += 4) {
for (var c = 0; c < 3; c++) {
imageDataNew.data[i + c] = Ox.limit(Math.round(data[i + c] + bias), 0, 255)
}
imageDataNew.data[i + 3] = 255;
}
self.context.putImageData(imageDataNew, 0, 0);
};
self.map = function(fn) {
var imageData = self.context.getImageData(0, 0, self.width, self.height),
i, n = imageData.data.length, c;
for (i = 0; i < n; i += 4) {
var data = fn([
imageData.data[i], imageData.data[i + 1],
imageData.data[i + 2], imageData.data[i + 3]
], getXY(i));
for (c = 0; c < 4; c++) {
imageData.data[i + c] = data[c];
};
}
self.context.putImageData(imageData, 0, 0);
};
self.setSL = function(sl, d) {
var c = sl == 'saturation' ? 1 : 2;
self.map(function(rgba) {
var hsl = Ox.hsl([rgba[0], rgba[1], rgba[2]]), rgb;
hsl[c] = d < 0 ? hsl[c] * (d + 1) : hsl[c] + (1 - hsl[c]) * d;
rgb = Ox.rgb(hsl);
return [rgb[0], rgb[1], rgb[2], rgba[3]];
});
}
that.blur = function(val) {
self.filter(val == 1 ? [
0.0, 0.2, 0.0,
0.2, 0.2, 0.2,
0.0, 0.2, 0.0
] : val == 2 ? [
0.00, 1/21, 1/21, 1/21, 0.00,
1/21, 1/21, 1/21, 1/21, 1/21,
1/21, 1/21, 1/21, 1/21, 1/21,
1/21, 1/21, 1/21, 1/21, 1/21,
0.00, 1/21, 1/21, 1/21, 0.00
] : [
0.00, 0.00, 1/37, 1/37, 1/37, 0.00, 0.00,
0.00, 1/37, 1/37, 1/37, 1/37, 1/37, 0.00,
1/37, 1/37, 1/37, 1/37, 1/37, 1/37, 1/37,
1/37, 1/37, 1/37, 1/37, 1/37, 1/37, 1/37,
1/37, 1/37, 1/37, 1/37, 1/37, 1/37, 1/37,
0.00, 1/37, 1/37, 1/37, 1/37, 1/37, 0.00,
0.00, 0.00, 1/37, 1/37, 1/37, 0.00, 0.00
]);
return that;
};
that.brightness = function(val) {
self.setSL('brightness', val);
return that;
};
that.channel = function(channel) {
self.map(function(rgba) {
var hue = Ox.hsl([rgba[0], rgba[1], rgba[2]])[0],
rgb = Ox.rgb([hue, 1, 0.5]);
return [rgb[0], rgb[1], rgb[2], rgba[3]];
});
return that;
}
that.contour = function(val) {
self.filter([
+1, +1, +1,
+1, -7, +1,
+1, +1, +1
]);
return that;
};
that.edges = function(val) {
self.filter([
-1, -1, -1,
-1, +8, -1,
-1, -1, -1
]);
that.saturation(-1);
return that;
};
that.emboss = function(val) {
self.filter([
-1, -1, +0,
-1, +0, +1,
+0, +1, +1
], 128);
that.saturation(-1);
return that;
};
that.hue = function(val) {
self.map(function(rgba) {
var hsl = Ox.hsl([rgba[0], rgba[1], rgba[2]]), rgb;
hsl[0] = (hsl[0] + val) % 360;
rgb = Ox.rgb(hsl);
return [rgb[0], rgb[1], rgb[2], rgba[3]];
});
return that;
};
that.invert = function() {
self.map(function(rgba) {
return [255 - rgba[0], 255 - rgba[1], 255 - rgba[2], rgba[3]];
});
return that;
};
that.motionBlur = function() {
self.filter([
0.2, 0.0, 0.0, 0.0, 0.0,
0.0, 0.2, 0.0, 0.0, 0.0,
0.0, 0.0, 0.2, 0.0, 0.0,
0.0, 0.0, 0.0, 0.2, 0.0,
0.0, 0.0, 0.0, 0.0, 0.2
]);
return that;
};
that.posterize = function() {
that.blur(3);
self.map(function(rgba) {
return [
Math.floor(rgba[0] / 64) * 64,
Math.floor(rgba[1] / 64) * 64,
Math.floor(rgba[2] / 64) * 64,
rgba[3]
];
});
return that;
};
that.saturation = function(val) {
self.setSL('saturation', val);
return that;
};
that.sharpen = function(val) {
self.filter([
-1, -1, -1,
-1, +9, -1,
-1, -1, -1
]);
return that;
};
that.solarize = function() {
self.map(function(rgba) {
return [
rgba[0] < 128 ? rgba[0] : 255 - rgba[0],
rgba[1] < 128 ? rgba[1] : 255 - rgba[1],
rgba[2] < 128 ? rgba[2] : 255 - rgba[2],
rgba[3]
];
});
return that;
}
that.resize = function(width, height) {
self.canvas.attr({
width: width,
height: height
});
return that;
}
that.url = function() {
return self.canvas[0].toDataURL();
return that;
};
if (self.src) {
self.image = new Image();
self.image.onload = init;
self.image.src = self.src;
} else {
init();
}
function init() {
if (self.image) {
self.width = self.image.width;
self.height = self.image.height;
}
self.canvas = Ox.element('<canvas>').attr({
width: self.width,
height: self.height
});
self.context = self.canvas[0].getContext('2d');
if (self.image) {
self.context.drawImage(self.image, 0, 0);
}
self.callback(that);
}
};
callback(true);
}