2011-06-19 15:40:53 +00:00
|
|
|
Ox.load.Image = function(options, callback) {
|
|
|
|
|
|
|
|
Ox.Image = function() {
|
|
|
|
|
|
|
|
var self = {},
|
|
|
|
that = {};
|
|
|
|
|
2011-09-08 01:53:19 +00:00
|
|
|
self.callback = arguments[arguments.length - 1];
|
2011-06-19 15:40:53 +00:00
|
|
|
if (arguments.length == 2) {
|
|
|
|
self.src = arguments[0];
|
2011-09-08 01:53:19 +00:00
|
|
|
self.image = new Image();
|
|
|
|
self.image.onload = init;
|
|
|
|
self.image.src = self.src;
|
2011-06-19 15:40:53 +00:00
|
|
|
} else {
|
|
|
|
self.width = arguments[0];
|
|
|
|
self.height = arguments[1];
|
2011-09-08 01:53:19 +00:00
|
|
|
self.background = arguments.length == 4 ? arguments[2] : [0, 0, 0, 0];
|
|
|
|
init();
|
2011-06-19 15:40:53 +00:00
|
|
|
}
|
|
|
|
|
2011-09-08 01:53:19 +00:00
|
|
|
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) {
|
2011-09-08 12:27:40 +00:00
|
|
|
capacity += rgba[3] == 255 ? bpb * 3/8 : 0;
|
2011-09-08 01:53:19 +00:00
|
|
|
});
|
|
|
|
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;
|
2011-06-21 09:16:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
function getXY(index) {
|
|
|
|
index /= 4;
|
|
|
|
return [index % self.width, Math.floor(index / self.width)];
|
|
|
|
}
|
|
|
|
|
2011-09-08 01:53:19 +00:00
|
|
|
function init() {
|
|
|
|
if (self.image) {
|
|
|
|
self.width = self.image.width;
|
|
|
|
self.height = self.image.height;
|
2011-06-21 09:16:23 +00:00
|
|
|
}
|
2011-09-08 01:53:19 +00:00
|
|
|
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);
|
2011-06-19 15:40:53 +00:00
|
|
|
}
|
2011-09-08 01:53:19 +00:00
|
|
|
self.imageData = self.context.getImageData(0, 0, self.width, self.height);
|
|
|
|
self.data = self.imageData.data;
|
|
|
|
self.callback(that);
|
|
|
|
}
|
2011-06-19 15:40:53 +00:00
|
|
|
|
2011-09-08 01:53:19 +00:00
|
|
|
function setSL(sl, d) {
|
|
|
|
var c = sl == 's' ? 1 : 2;
|
|
|
|
return that.map(function(rgba) {
|
2011-06-19 15:40:53 +00:00
|
|
|
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);
|
2011-09-08 01:53:19 +00:00
|
|
|
return Ox.merge(rgb, rgba[3]);
|
2011-06-19 15:40:53 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2011-06-21 09:16:23 +00:00
|
|
|
that.blur = function(val) {
|
2011-09-08 01:53:19 +00:00
|
|
|
return that.filter(val == 1 ? [
|
2011-06-21 09:16:23 +00:00
|
|
|
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
|
|
|
|
]);
|
2011-06-19 15:40:53 +00:00
|
|
|
};
|
|
|
|
|
2011-09-08 08:16:31 +00:00
|
|
|
that.channel = function(str) {
|
|
|
|
str = str[0].toLowerCase();
|
2011-09-08 01:53:19 +00:00
|
|
|
return that.map(function(rgba) {
|
2011-09-08 08:16:31 +00:00
|
|
|
var i = ['r', 'g', 'b', 'a'].indexOf(str), rgb, val;
|
2011-09-08 01:53:19 +00:00
|
|
|
if (i > -1) {
|
|
|
|
return Ox.map(rgba, function(v, c) {
|
2011-09-08 08:16:31 +00:00
|
|
|
return str == 'a'
|
|
|
|
? (c < 3 ? rgba[3] : 255)
|
|
|
|
: (c == i || c == 3 ? v : 0);
|
2011-09-08 01:53:19 +00:00
|
|
|
});
|
|
|
|
} else {
|
2011-09-08 08:16:31 +00:00
|
|
|
i = ['h', 's', 'l'].indexOf(str);
|
2011-09-08 01:53:19 +00:00
|
|
|
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]);
|
|
|
|
}
|
2011-06-19 15:40:53 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2011-06-21 09:16:23 +00:00
|
|
|
that.contour = function(val) {
|
2011-09-08 01:53:19 +00:00
|
|
|
return that.filter([
|
2011-06-21 09:16:23 +00:00
|
|
|
+1, +1, +1,
|
|
|
|
+1, -7, +1,
|
|
|
|
+1, +1, +1
|
|
|
|
]);
|
|
|
|
};
|
|
|
|
|
|
|
|
that.edges = function(val) {
|
2011-09-08 01:53:19 +00:00
|
|
|
return that.filter([
|
2011-06-21 09:16:23 +00:00
|
|
|
-1, -1, -1,
|
|
|
|
-1, +8, -1,
|
|
|
|
-1, -1, -1
|
2011-09-08 01:53:19 +00:00
|
|
|
]).saturation(-1);
|
2011-06-21 09:16:23 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
that.emboss = function(val) {
|
2011-09-08 01:53:19 +00:00
|
|
|
return that.filter([
|
2011-06-21 09:16:23 +00:00
|
|
|
-1, -1, +0,
|
|
|
|
-1, +0, +1,
|
|
|
|
+0, +1, +1
|
2011-09-08 01:53:19 +00:00
|
|
|
], 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) {
|
2011-09-08 12:27:40 +00:00
|
|
|
bin += Ox.sum(Ox.range(8).map(function(bit) {
|
|
|
|
return +!!(self.data[i] & 1 << bit);
|
2011-09-08 01:53:19 +00:00
|
|
|
})) % 2;
|
|
|
|
} else {
|
2011-09-08 12:27:40 +00:00
|
|
|
bin += +!!(self.data[i] & 1 << bit);
|
2011-09-08 01:53:19 +00:00
|
|
|
}
|
2011-09-08 12:27:40 +00:00
|
|
|
// /*mode > 0 &&*/ Ox.print(bin)
|
2011-09-08 01:53:19 +00:00
|
|
|
if (bin.length == 8) {
|
|
|
|
str += Ox.char(parseInt(bin, 2));
|
|
|
|
bin = '';
|
|
|
|
if (str.length == len) {
|
|
|
|
if (++done == 1) {
|
|
|
|
len = Ox.decodeBase256(str);
|
2011-09-08 12:27:40 +00:00
|
|
|
Ox.print(Ox.map(str, function(chr) {
|
|
|
|
return Ox.pad(chr.charCodeAt(0).toString(2), 8);
|
|
|
|
}).join(' '))
|
|
|
|
Ox.print("LEN", len, getCapacity(bits.length), bits, xy, c)
|
|
|
|
Ox.print(Ox.range(index).map(function(i) {
|
|
|
|
return that.pixel(i, 0).map(function(px, j) {
|
|
|
|
return j < 4 ? Ox.pad(px.toString(2), 8) : null;
|
|
|
|
}).join(',')
|
|
|
|
}).join('\n'))
|
|
|
|
if (len + 4 > getCapacity(bits.length)) {
|
2011-09-08 01:53:19 +00:00
|
|
|
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
|
2011-09-08 08:16:31 +00:00
|
|
|
// If the number of bits set to 1, mod 2
|
2011-09-08 01:53:19 +00:00
|
|
|
? Ox.sum(Ox.range(8).map(function(bit) {
|
2011-09-08 12:27:40 +00:00
|
|
|
return +!!(self.data[i] & 1 << bit);
|
2011-09-08 01:53:19 +00:00
|
|
|
})) % 2
|
2011-09-08 08:16:31 +00:00
|
|
|
// or the one bit in question
|
2011-09-08 12:27:40 +00:00
|
|
|
: +!!(self.data[i] & 1 << bit)
|
2011-09-08 08:16:31 +00:00
|
|
|
// is not equal to the data bit
|
2011-09-08 01:53:19 +00:00
|
|
|
) != bin[b++]) {
|
2011-09-08 08:16:31 +00:00
|
|
|
// then flip the bit
|
2011-09-08 01:53:19 +00:00
|
|
|
self.data[i] ^= 1 << bit;
|
|
|
|
}
|
2011-09-08 12:27:40 +00:00
|
|
|
});
|
2011-09-08 01:53:19 +00:00
|
|
|
/*
|
|
|
|
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;
|
2011-06-21 09:16:23 +00:00
|
|
|
return that;
|
|
|
|
};
|
|
|
|
|
2011-09-08 01:53:19 +00:00
|
|
|
/*@
|
|
|
|
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;
|
|
|
|
};
|
|
|
|
|
2011-06-19 15:40:53 +00:00
|
|
|
that.hue = function(val) {
|
2011-09-08 01:53:19 +00:00
|
|
|
return that.map(function(rgba) {
|
2011-06-19 15:40:53 +00:00
|
|
|
var hsl = Ox.hsl([rgba[0], rgba[1], rgba[2]]), rgb;
|
|
|
|
hsl[0] = (hsl[0] + val) % 360;
|
|
|
|
rgb = Ox.rgb(hsl);
|
2011-09-08 01:53:19 +00:00
|
|
|
return Ox.merge(rgb, rgba[3]);
|
2011-06-19 15:40:53 +00:00
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
that.invert = function() {
|
2011-09-08 01:53:19 +00:00
|
|
|
return that.map(function(rgba) {
|
2011-06-19 15:40:53 +00:00
|
|
|
return [255 - rgba[0], 255 - rgba[1], 255 - rgba[2], rgba[3]];
|
|
|
|
});
|
2011-09-08 01:53:19 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
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);
|
2011-06-21 09:16:23 +00:00
|
|
|
return that;
|
|
|
|
};
|
|
|
|
|
|
|
|
that.motionBlur = function() {
|
2011-09-08 01:53:19 +00:00
|
|
|
return that.filter([
|
2011-06-21 09:16:23 +00:00
|
|
|
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
|
|
|
|
]);
|
|
|
|
};
|
|
|
|
|
2011-09-08 01:53:19 +00:00
|
|
|
that.pixel = function(x, y, val) {
|
2011-09-08 12:27:40 +00:00
|
|
|
var i = getIndex(x, y);
|
2011-09-08 01:53:19 +00:00
|
|
|
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;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-06-21 09:16:23 +00:00
|
|
|
that.posterize = function() {
|
2011-09-08 01:53:19 +00:00
|
|
|
return that.blur(3).map(function(rgba) {
|
2011-06-21 09:16:23 +00:00
|
|
|
return [
|
|
|
|
Math.floor(rgba[0] / 64) * 64,
|
|
|
|
Math.floor(rgba[1] / 64) * 64,
|
|
|
|
Math.floor(rgba[2] / 64) * 64,
|
|
|
|
rgba[3]
|
|
|
|
];
|
|
|
|
});
|
2011-06-19 15:40:53 +00:00
|
|
|
};
|
|
|
|
|
2011-09-08 01:53:19 +00:00
|
|
|
that.resize = function(width, height) {
|
|
|
|
self.canvas.attr({
|
|
|
|
width: width,
|
|
|
|
height: height
|
|
|
|
});
|
2011-06-21 09:16:23 +00:00
|
|
|
return that;
|
2011-09-08 01:53:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
that.saturation = function(val) {
|
|
|
|
return setSL('s', val);
|
2011-06-21 09:16:23 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
that.sharpen = function(val) {
|
2011-09-08 01:53:19 +00:00
|
|
|
return that.filter([
|
2011-06-21 09:16:23 +00:00
|
|
|
-1, -1, -1,
|
|
|
|
-1, +9, -1,
|
|
|
|
-1, -1, -1
|
|
|
|
]);
|
2011-06-19 15:40:53 +00:00
|
|
|
};
|
|
|
|
|
2011-06-21 09:16:23 +00:00
|
|
|
that.solarize = function() {
|
2011-09-08 01:53:19 +00:00
|
|
|
return that.map(function(rgba) {
|
2011-06-21 09:16:23 +00:00
|
|
|
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]
|
|
|
|
];
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2011-09-08 01:53:19 +00:00
|
|
|
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.attr({
|
|
|
|
width: self.width,
|
|
|
|
height: self.height
|
|
|
|
});
|
|
|
|
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.image.src = self.src;
|
|
|
|
return that;
|
|
|
|
}
|
2011-06-19 15:40:53 +00:00
|
|
|
};
|
|
|
|
|
2011-09-08 01:53:19 +00:00
|
|
|
that.toDataURL = that.src;
|
2011-06-19 15:40:53 +00:00
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
callback(true);
|
|
|
|
|
|
|
|
}
|
|
|
|
|