move image encoding functions to image module
This commit is contained in:
parent
816993e1b9
commit
842d536dc8
4 changed files with 416 additions and 147 deletions
|
@ -5,23 +5,60 @@ Ox.load('Image', function() {
|
|||
Ox.Image('png/Lenna.png', function(image) {
|
||||
var body = Ox.element('body'),
|
||||
select = Ox.element('<select>').appendTo(body);
|
||||
['Filter...', 'blur', 'channel', 'contour', 'invert', 'edges', 'emboss', 'motionBlur', 'posterize', 'sharpen', 'solarize'].forEach(function(filter) {
|
||||
[
|
||||
'Method...', 'blur(1)', 'blur(2)', 'blur(3)',
|
||||
'channel("r")', 'channel("g")', 'channel("b")',
|
||||
'channel("h")', 'channel("s")', 'channel("l")',
|
||||
'contour()', 'edges()', 'emboss()',
|
||||
'encode("some secret stuff")', 'decode()',
|
||||
'encode("some secret stuff", true)', 'decode(true)',
|
||||
'encode("some secret stuff", 1)', 'decode(1)',
|
||||
'encode("some secret stuff", 127)', 'decode(127)',
|
||||
'hue(0)', 'hue(120)', 'hue(240)',
|
||||
'invert()',
|
||||
'lightness(-0.5)', 'lightness(0.5)',
|
||||
'motionBlur()', 'posterize()',
|
||||
'saturation(-0.5)', 'saturation(0.5)',
|
||||
'sharpen()', 'solarize()', 'src("png/Lenna.png")'
|
||||
].forEach(function(filter) {
|
||||
Ox.element('<option>').html(filter).appendTo(select);
|
||||
});
|
||||
select[0].onchange = function() {
|
||||
if (select[0].value[0] == select[0].value[0].toLowerCase()) {
|
||||
Ox.element('#filter').attr({
|
||||
src: image[select[0].value]().url()
|
||||
var split = select[0].value.split('('),
|
||||
fn = split[0],
|
||||
args = split[1].length == 1 ? []
|
||||
: split[1].split(')')[0].split(', ').map(function(v) {
|
||||
return v == 'true' ? true
|
||||
: v == 'false'? false
|
||||
: v[0] == '"' ? v.split('"')[1]
|
||||
: parseFloat(v);
|
||||
});
|
||||
if (fn == 'encode' || fn == 'src') {
|
||||
image[fn].apply(null, Ox.merge(args, function(image) {
|
||||
Ox.element('#filter').attr({
|
||||
src: image.src()
|
||||
});
|
||||
}));
|
||||
} else if (fn == 'decode') {
|
||||
image[fn].apply(null, Ox.merge(args, function(str) {
|
||||
alert(str);
|
||||
}));
|
||||
} else {
|
||||
Ox.element('#filter').attr({
|
||||
src: image[fn].apply(null, args).src()
|
||||
});
|
||||
}
|
||||
select[0].selectedIndex = 0;
|
||||
}
|
||||
}
|
||||
Ox.element('<br>').appendTo(body);
|
||||
Ox.element('<img>').attr({
|
||||
src: image.url()
|
||||
src: image.src()
|
||||
}).appendTo(body);
|
||||
Ox.element('<img>').attr({
|
||||
id: 'filter',
|
||||
src: image.url()
|
||||
src: image.src()
|
||||
}).appendTo(body);
|
||||
//Ox.element('<img>').attr({src: image.saturation(0.5).blur().url()}).appendTo(Ox.element('body'));
|
||||
});
|
||||
|
|
BIN
demos/image/png/Lenna.png
Normal file
BIN
demos/image/png/Lenna.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 464 KiB |
|
@ -5,17 +5,43 @@ Ox.load.Image = function(options, callback) {
|
|||
var self = {},
|
||||
that = {};
|
||||
|
||||
self.callback = arguments[arguments.length - 1];
|
||||
if (arguments.length == 2) {
|
||||
self.src = arguments[0];
|
||||
self.callback = arguments[1];
|
||||
self.image = new Image();
|
||||
self.image.onload = init;
|
||||
self.image.src = self.src;
|
||||
} else {
|
||||
self.width = arguments[0];
|
||||
self.height = arguments[1];
|
||||
self.callback = arguments[2];
|
||||
self.background = arguments.length == 4 ? arguments[2] : [0, 0, 0, 0];
|
||||
init();
|
||||
}
|
||||
|
||||
function getIndex(x, y) {
|
||||
return (Ox.mod(x, self.width) + Ox.mod(y * self.width, self.width * self.height)) * 4;
|
||||
function error(mode) {
|
||||
throw new RangeError('PNG codec can\'t ' + mode + ' ' + (
|
||||
mode == 'encode' ? 'data' : 'image'
|
||||
));
|
||||
}
|
||||
|
||||
function getCapacity(bpb) {
|
||||
var capacity = 0;
|
||||
that.forEach(function(rgba) {
|
||||
capacity += rgba[3] == 255 ? bpb / 8 : 0;
|
||||
});
|
||||
return capacity;
|
||||
}
|
||||
|
||||
function getIndex() {
|
||||
if (arguments.length == 1) {
|
||||
xy = arguments[0];
|
||||
} else {
|
||||
xy = [arguments[0], arguments[1]];
|
||||
}
|
||||
return (
|
||||
Ox.mod(xy[0], self.width)
|
||||
+ Ox.mod(xy[1] * self.width, self.width * self.height)
|
||||
) * 4;
|
||||
}
|
||||
|
||||
function getXY(index) {
|
||||
|
@ -23,67 +49,39 @@ Ox.load.Image = function(options, callback) {
|
|||
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;
|
||||
function init() {
|
||||
if (self.image) {
|
||||
self.width = self.image.width;
|
||||
self.height = self.image.height;
|
||||
}
|
||||
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];
|
||||
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);
|
||||
} else if (Ox.sum(self.background)) {
|
||||
that.fillStyle(self.background);
|
||||
that.fillRect(0, 0, self.width, self.height);
|
||||
}
|
||||
filterIndex++;
|
||||
self.imageData = self.context.getImageData(0, 0, self.width, self.height);
|
||||
self.data = self.imageData.data;
|
||||
self.callback(that);
|
||||
}
|
||||
}
|
||||
}
|
||||
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) {
|
||||
function setSL(sl, d) {
|
||||
var c = sl == 's' ? 1 : 2;
|
||||
return that.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]];
|
||||
return Ox.merge(rgb, rgba[3]);
|
||||
});
|
||||
}
|
||||
|
||||
that.blur = function(val) {
|
||||
self.filter(val == 1 ? [
|
||||
return that.filter(val == 1 ? [
|
||||
0.0, 0.2, 0.0,
|
||||
0.2, 0.2, 0.2,
|
||||
0.0, 0.2, 0.0
|
||||
|
@ -102,83 +100,320 @@ Ox.load.Image = function(options, callback) {
|
|||
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]];
|
||||
that.channel = function(c) {
|
||||
c = c.toLowerCase();
|
||||
return that.map(function(rgba) {
|
||||
var i = ['r', 'g', 'b'].indexOf(c), rgb, val;
|
||||
if (i > -1) {
|
||||
return Ox.map(rgba, function(v, c) {
|
||||
return c == i || c == 3 ? v : 0;
|
||||
});
|
||||
} else {
|
||||
i = ['h', 's', 'l'].indexOf(c);
|
||||
val = Ox.hsl([rgba[0], rgba[1], rgba[2]])[i];
|
||||
rgb = i == 0
|
||||
? Ox.rgb([val, 1, 0.5])
|
||||
: Ox.map(Ox.range(3), function(v) {
|
||||
return parseInt(val * 255);
|
||||
});
|
||||
return Ox.merge(rgb, rgba[3]);
|
||||
}
|
||||
});
|
||||
return that;
|
||||
}
|
||||
|
||||
that.contour = function(val) {
|
||||
self.filter([
|
||||
return that.filter([
|
||||
+1, +1, +1,
|
||||
+1, -7, +1,
|
||||
+1, +1, +1
|
||||
]);
|
||||
return that;
|
||||
};
|
||||
|
||||
that.edges = function(val) {
|
||||
self.filter([
|
||||
return that.filter([
|
||||
-1, -1, -1,
|
||||
-1, +8, -1,
|
||||
-1, -1, -1
|
||||
]);
|
||||
that.saturation(-1);
|
||||
return that;
|
||||
]).saturation(-1);
|
||||
};
|
||||
|
||||
that.emboss = function(val) {
|
||||
self.filter([
|
||||
return that.filter([
|
||||
-1, -1, +0,
|
||||
-1, +0, +1,
|
||||
+0, +1, +1
|
||||
], 128);
|
||||
that.saturation(-1);
|
||||
], 128).saturation(-1);
|
||||
};
|
||||
|
||||
that.decode = function() {
|
||||
var callback = arguments[arguments.length - 1],
|
||||
deflate = Ox.isBoolean(arguments[0]) ? arguments[0]
|
||||
: Ox.isBoolean(arguments[1]) ? arguments[1] : false,
|
||||
mode = Ox.isNumber(arguments[0]) ? arguments[0]
|
||||
: Ox.isNumber(arguments[1]) ? arguments[1] : 0,
|
||||
bin = '',
|
||||
bits = mode < 1 ? [-mode] : Ox.map(Ox.range(8), function(b) {
|
||||
return mode & 1 << b ? b : null;
|
||||
}),
|
||||
done = 0; len = 4, str = '';
|
||||
that.forEach(function(rgba, xy) {
|
||||
if (rgba[3] == 255) {
|
||||
var index = getIndex(xy);
|
||||
Ox.loop(3, function(c) {
|
||||
var i = index + c;
|
||||
Ox.forEach(bits, function(bit) {
|
||||
if (mode < 1) {
|
||||
bin += Ox.sum(Ox.range(8).map(function(b) {
|
||||
return self.data[i] & 1 << b;
|
||||
})) % 2;
|
||||
} else {
|
||||
bin += +!!(self.data[i] & i << bit);
|
||||
}
|
||||
/*mode > 0 &&*/ Ox.print(bin)
|
||||
if (bin.length == 8) {
|
||||
str += Ox.char(parseInt(bin, 2));
|
||||
bin = '';
|
||||
if (str.length == len) {
|
||||
if (++done == 1) {
|
||||
len = Ox.decodeBase256(str);
|
||||
Ox.print("LEN", len)
|
||||
if (len + 4 > getCapacity(1)) {
|
||||
error('decode');
|
||||
}
|
||||
str = '';
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
if (done == 2) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
});
|
||||
try {
|
||||
Ox.print("STR", str, str.length, str.charCodeAt(0));
|
||||
if (deflate) {
|
||||
Ox.decodeDeflate(str, callback);
|
||||
} else {
|
||||
callback(Ox.decodeUTF8(str));
|
||||
return str;
|
||||
}
|
||||
} catch (e) {
|
||||
error('decode');
|
||||
}
|
||||
}
|
||||
|
||||
that.encode = function(str) {
|
||||
var callback = arguments[arguments.length - 1],
|
||||
deflate = Ox.isBoolean(arguments[1]) ? arguments[1]
|
||||
: Ox.isBoolean(arguments[2]) ? arguments[2] : false,
|
||||
mode = Ox.isNumber(arguments[1]) ? arguments[1]
|
||||
: Ox.isNumber(arguments[2]) ? arguments[2] : 0,
|
||||
b = 0, bin,
|
||||
bits = mode < 1 ? [-mode] : Ox.map(Ox.range(8), function(bit) {
|
||||
return mode & 1 << bit ? bit : null;
|
||||
}),
|
||||
cap = getCapacity(bits.length), len;
|
||||
Ox.print("CAPACITY", cap);
|
||||
// Compress the string
|
||||
str = Ox[deflate ? 'encodeDeflate' : 'encodeUTF8'](str);
|
||||
Ox.print("STR", str, str.length, str.charCodeAt(0));
|
||||
len = str.length;
|
||||
// Prefix the string with its length, as a four-byte value
|
||||
str = Ox.pad(Ox.encodeBase256(len), 4, Ox.char(0)) + str;
|
||||
str.length > cap && error('encode');
|
||||
while (str.length < cap) {
|
||||
str += str.substr(4, len);
|
||||
}
|
||||
str = str.substr(0, Math.ceil(cap));
|
||||
// Create an array of bit values
|
||||
bin = Ox.flatten(Ox.map(str, function(chr) {
|
||||
return Ox.map(Ox.range(8), function(i) {
|
||||
return chr.charCodeAt(0) >> 7 - i & 1;
|
||||
});
|
||||
}));
|
||||
b = 0;
|
||||
that.forEach(function(rgba, xy) {
|
||||
if (rgba[3] == 255) {
|
||||
var index = getIndex(xy);
|
||||
Ox.loop(3, function(c) {
|
||||
var i = index + c;
|
||||
Ox.forEach(bits, function(bit) {
|
||||
if ((
|
||||
mode < 1
|
||||
? Ox.sum(Ox.range(8).map(function(bit) {
|
||||
return self.data[i] & 1 << bit;
|
||||
})) % 2
|
||||
: self.data[i] & 1 << bit
|
||||
) != bin[b++]) {
|
||||
self.data[i] ^= 1 << bit;
|
||||
}
|
||||
})
|
||||
/*
|
||||
if (mode < 1) {
|
||||
if (Ox.sum(Ox.range(8).map(function(bit) {
|
||||
return self.data[i] & 1 << bit;
|
||||
})) % 2 != bin[b++]) {
|
||||
// If the number of bits set to one, modulo 2,
|
||||
// is not equal to the data bit, flip one bit
|
||||
self.data[i] ^= 1 << bits[0];
|
||||
}
|
||||
} else {
|
||||
Ox.forEach(bits, function(bit) {
|
||||
if (self.data[i] & 1 << bit != bin[b++]) {
|
||||
// If the bit is not equal to the data bit,
|
||||
// flip it
|
||||
self.data[i] ^= 1 << bit;
|
||||
}
|
||||
});
|
||||
}
|
||||
*/
|
||||
});
|
||||
}
|
||||
});
|
||||
self.context.putImageData(self.imageData, 0, 0);
|
||||
callback(that);
|
||||
};
|
||||
|
||||
that.fillRect = function(x, y, w, h) {
|
||||
self.context.fillRect(x, y, w, h);
|
||||
return that;
|
||||
};
|
||||
|
||||
that.fillStyle = function() {
|
||||
if (arguments.length == 0) {
|
||||
return self.context.fillStyle;
|
||||
} else {
|
||||
self.context.fillStyle = arguments[0];
|
||||
return that;
|
||||
}
|
||||
};
|
||||
|
||||
that.filter = function(filter, bias) {
|
||||
bias = bias || 0;
|
||||
var filterSize = Math.sqrt(filter.length),
|
||||
d = (filterSize - 1) / 2,
|
||||
imageData = self.context.createImageData(self.width, self.height),
|
||||
data = [];
|
||||
self.imageData = self.context.getImageData(0, 0, self.width, self.height);
|
||||
self.data = self.imageData.data;
|
||||
Ox.loop(0, self.data.length, 4, function(i) {
|
||||
var filterIndex = 0,
|
||||
xy = getXY(i);
|
||||
Ox.loop(3, function(c) {
|
||||
data[i + c] = 0;
|
||||
});
|
||||
Ox.loop(-d, d + 1, function(x) {
|
||||
Ox.loop(-d, d + 1, function(y) {
|
||||
var pixelIndex = getIndex(xy[0] + x, xy[1] + y);
|
||||
Ox.loop(3, function(c) {
|
||||
data[i + c] += self.data[pixelIndex + c] * filter[filterIndex];
|
||||
});
|
||||
filterIndex++;
|
||||
});
|
||||
});
|
||||
});
|
||||
Ox.loop(0, self.data.length, 4, function(i) {
|
||||
Ox.loop(4, function(c) {
|
||||
imageData.data[i + c] = c < 3
|
||||
? Ox.limit(Math.round(data[i + c] + bias), 0, 255)
|
||||
: self.data[i + c];
|
||||
});
|
||||
});
|
||||
self.context.putImageData(imageData, 0, 0);
|
||||
self.imageData = imageData;
|
||||
self.data = data;
|
||||
return that;
|
||||
};
|
||||
|
||||
/*@
|
||||
forEach <f> Pixel-wise forEach function
|
||||
(fn) -> <o> The image object
|
||||
fn <f> Iterator function
|
||||
rgba <[n]> RGBA values
|
||||
xy <[n]> XY coordinates
|
||||
@*/
|
||||
that.forEach = function(fn) {
|
||||
Ox.loop(0, self.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;
|
||||
};
|
||||
|
||||
that.hue = function(val) {
|
||||
self.map(function(rgba) {
|
||||
return that.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 Ox.merge(rgb, rgba[3]);
|
||||
});
|
||||
return that;
|
||||
};
|
||||
|
||||
that.invert = function() {
|
||||
self.map(function(rgba) {
|
||||
return that.map(function(rgba) {
|
||||
return [255 - rgba[0], 255 - rgba[1], 255 - rgba[2], rgba[3]];
|
||||
});
|
||||
};
|
||||
|
||||
that.lightness = function(val) {
|
||||
return setSL('l', val);
|
||||
};
|
||||
|
||||
/*@
|
||||
map <f> Pixel-wise map function
|
||||
(fn) -> <o> The image object
|
||||
fn <f> Iterator function
|
||||
rgba <[n]> RGBA values
|
||||
xy <[n]> XY coordinates
|
||||
@*/
|
||||
that.map = function(fn) {
|
||||
self.imageData = self.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) {
|
||||
self.data[i + c] = val;
|
||||
});
|
||||
})
|
||||
self.context.putImageData(self.imageData, 0, 0);
|
||||
return that;
|
||||
};
|
||||
|
||||
that.motionBlur = function() {
|
||||
self.filter([
|
||||
return that.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.pixel = function(x, y, val) {
|
||||
var index = getIndex(x, y);
|
||||
if (!val) {
|
||||
return Ox.range(4).map(function(c) {
|
||||
return self.data[i + c];
|
||||
});
|
||||
} else {
|
||||
val.forEach(function(v, c) {
|
||||
self.data[i + c] = v;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
that.posterize = function() {
|
||||
that.blur(3);
|
||||
self.map(function(rgba) {
|
||||
return that.blur(3).map(function(rgba) {
|
||||
return [
|
||||
Math.floor(rgba[0] / 64) * 64,
|
||||
Math.floor(rgba[1] / 64) * 64,
|
||||
|
@ -186,35 +421,8 @@ Ox.load.Image = function(options, callback) {
|
|||
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,
|
||||
|
@ -223,34 +431,54 @@ Ox.load.Image = function(options, callback) {
|
|||
return that;
|
||||
}
|
||||
|
||||
that.url = function() {
|
||||
return self.canvas[0].toDataURL();
|
||||
return that;
|
||||
that.saturation = function(val) {
|
||||
return setSL('s', val);
|
||||
};
|
||||
|
||||
if (self.src) {
|
||||
self.image = new Image();
|
||||
self.image.onload = init;
|
||||
self.image.src = self.src;
|
||||
} else {
|
||||
init();
|
||||
that.sharpen = function(val) {
|
||||
return that.filter([
|
||||
-1, -1, -1,
|
||||
-1, +9, -1,
|
||||
-1, -1, -1
|
||||
]);
|
||||
};
|
||||
|
||||
that.solarize = function() {
|
||||
return that.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]
|
||||
];
|
||||
});
|
||||
}
|
||||
|
||||
function init() {
|
||||
if (self.image) {
|
||||
that.src = function() {
|
||||
if (arguments.length == 0) {
|
||||
return self.canvas[0].toDataURL();
|
||||
} else {
|
||||
var callback = arguments[1];
|
||||
self.src = arguments[0];
|
||||
self.image = new Image();
|
||||
self.image.onload = function() {
|
||||
self.width = self.image.width;
|
||||
self.height = self.image.height;
|
||||
}
|
||||
self.canvas = Ox.element('<canvas>').attr({
|
||||
self.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.imageData = self.context.getImageData(0, 0, self.width, self.height);
|
||||
self.data = self.imageData.data;
|
||||
callback && callback(that);
|
||||
}
|
||||
self.callback(that);
|
||||
self.image.src = self.src;
|
||||
return that;
|
||||
}
|
||||
};
|
||||
|
||||
that.toDataURL = that.src;
|
||||
|
||||
};
|
||||
|
||||
|
|
18
source/Ox.js
18
source/Ox.js
|
@ -309,12 +309,15 @@ Ox.flatten = function(arr) {
|
|||
Ox.merge <f> Merges an array with one or more other arrays
|
||||
> Ox.merge([1], [2, 3, 2], [1])
|
||||
[1, 2, 3, 2, 1]
|
||||
> Ox.merge(1, [2, 3, 2], 1)
|
||||
[1, 2, 3, 2, 1]
|
||||
@*/
|
||||
Ox.merge = function(arr) {
|
||||
arr = Ox.isArray(arr) ? arr : [arr];
|
||||
Ox.forEach(Array.prototype.slice.call(arguments, 1), function(arg) {
|
||||
Ox.forEach(arg, function(val) {
|
||||
Ox.isArray(arg) ? Ox.forEach(arg, function(val) {
|
||||
arr.push(val);
|
||||
});
|
||||
}) : arr.push(arg);
|
||||
});
|
||||
return arr;
|
||||
};
|
||||
|
@ -2082,14 +2085,15 @@ Ox.element = function(str) {
|
|||
head, tail and chunk names are removed.
|
||||
(str) -> <s> The encoded string
|
||||
str <s> The string to be encoded
|
||||
# Test with: Ox.decodeDeflate(Ox.encodeDeflate('foo'), alert)
|
||||
@*/
|
||||
|
||||
Ox.encodeDeflate = function(str) {
|
||||
Ox.encodeDeflate = function(str, callback) {
|
||||
// Make sure we can encode the full unicode range of characters.
|
||||
str = Ox.encodeUTF8(str);
|
||||
// We can only safely write to RGB, so we need 1 pixel for 3 bytes.
|
||||
var len = str.length, c = Ox.canvas(Math.ceil((4 + len) / 3), 1),
|
||||
data = '', idat, ihdr;
|
||||
data = '', idat;
|
||||
// Prefix the string with its length, left-padded with 0-bytes to
|
||||
// length of 4 bytes, and right-pad the result with non-0-bytes to a
|
||||
// length that is a multiple of 3.
|
||||
|
@ -2105,7 +2109,7 @@ Ox.element = function(str) {
|
|||
// The first 16 and the last 12 bytes of a PNG are always the same and
|
||||
// can be discarded, the first 17 remaining bytes are part of the IHDR
|
||||
// chunk, and the rest are IDAT chunks.
|
||||
ihdr = Ox.sub(str, 16, 33); idat = Ox.sub(str, 33, -12);
|
||||
data = Ox.sub(str, 16, 33); idat = Ox.sub(str, 33, -12);
|
||||
while (idat) {
|
||||
// Each IDAT chunk consists of 4 bytes length, 4 bytes "IDAT" and
|
||||
// length bytes data, so we can optimize by removing each "IDAT".
|
||||
|
@ -2113,7 +2117,8 @@ Ox.element = function(str) {
|
|||
data += len + idat.substr(8, 12 + (len = Ox.decodeBase256(len)));
|
||||
idat = idat.substr(12 + len);
|
||||
}
|
||||
return ihdr + data;
|
||||
callback && callback(data);
|
||||
return data;
|
||||
}
|
||||
|
||||
/*@
|
||||
|
@ -2127,7 +2132,6 @@ Ox.element = function(str) {
|
|||
str <s> The string to be decoded
|
||||
callback <f> Callback function
|
||||
str <s> The decoded string
|
||||
# Test with: Ox.decodeDeflate(Ox.encodeDeflate('foo'), alert)
|
||||
@*/
|
||||
|
||||
Ox.decodeDeflate = function(str, callback) {
|
||||
|
|
Loading…
Reference in a new issue