1
0
Fork 0
forked from 0x2620/oxjs

image module update

This commit is contained in:
rlx 2011-09-08 21:39:07 +00:00
commit 1e38ff6b9e
4 changed files with 188 additions and 152 deletions

View file

@ -1,5 +1,17 @@
Ox.load.Image = function(options, callback) {
//@ Image ------------------------------------------------------------------
/*@
Ox.Image <f> Generic image object
(src, callback) -> <u> undefined
(width, height, callback) -> <u> undefined
(width, height, background, callback) -> <u> undefined
src <s> Image source (local, remote or data URL)
width <n> Width in px
image <n> Height in px
background <[n]> Background color (RGB or RGBA)
@*/
Ox.Image = function() {
var self = {},
@ -81,25 +93,22 @@ Ox.load.Image = function(options, callback) {
}
that.blur = function(val) {
return that.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
]);
var filter = [],
size = val * 2 + 1;
sum = 0
Ox.loop(size, function(x) {
Ox.loop(size, function(y) {
var isInCircle = +(Math.sqrt(
Math.pow(x - val, 2) + Math.pow(y - val, 2)
) <= val);
sum += isInCircle;
filter.push(isInCircle)
});
});
filter = filter.map(function(val) {
return val / sum;
})
return that.filter(filter);
};
that.channel = function(str) {
@ -133,6 +142,15 @@ Ox.load.Image = function(options, callback) {
]);
};
that.depth = function(val) {
var pow = Math.pow(2, 8 - val);
return that.map(function(rgba) {
return rgba.map(function(v, i) {
return i < 3 ? Math.floor(v / pow) * pow : v
});
});
}
that.edges = function(val) {
return that.filter([
-1, -1, -1,
@ -149,79 +167,35 @@ Ox.load.Image = function(options, callback) {
], 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(bit) {
return +!!(self.data[i] & 1 << bit);
})) % 2;
} else {
bin += +!!(self.data[i] & 1 << 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(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)) {
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');
}
}
/*@
encode <f> Encodes a string into the image
For most purposes, deflate and mode should be omitted, since the
defaults make the existence of the message harder to detect. A valid
use case for deflate and mode would be to encode, additionally to
the secret string, a more easily detected decoy string: <code>
image.encode(decoy, false, 1, function(image) { image.encode(secret,
-1, callback); })</code>.
(str, callback) -> <o> The image object (unmodified)
(str, deflate, callback) -> <o> The image object (unmodified)
(str, mode, callback) -> <o> The image object (unmodified)
(str, deflate, mode, callback) -> <o> The image object (unmodified)
(str, mode, deflate, callback) -> <o> The image object (unmodified)
str <s> The string to be encoded
callback <f> Callback function
image <o> The image object (modified)
deflate <b|true> If true, compress string with deflate
mode <n|0> Encoding mode
If mode is between -7 and 0, the string will be encoded one bit
per byte, as the number of bits within that byte set to 1,
modulo 2, by flipping, if necessary, the most (mode -7) to least
(mode 0) significant bit. If mode is between 1 and 255, the
string will be encoded bitwise into all bits per byte that, in
mode, are set to 1.
@*/
that.encode = function(str) {
var callback = arguments[arguments.length - 1],
deflate = Ox.isBoolean(arguments[1]) ? arguments[1]
: Ox.isBoolean(arguments[2]) ? arguments[2] : false,
: Ox.isBoolean(arguments[2]) ? arguments[2] : true,
mode = Ox.isNumber(arguments[1]) ? arguments[1]
: Ox.isNumber(arguments[2]) ? arguments[2] : 0,
b = 0, bin,
@ -229,13 +203,12 @@ Ox.load.Image = function(options, callback) {
return mode & 1 << bit ? bit : null;
}),
cap = getCapacity(bits.length), len;
Ox.print("CAPACITY", cap);
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 = Ox.pad(Ox.encodeBase256(len), 4, '\u0000') + str;
str.length > cap && error('encode');
while (str.length < cap) {
str += str.substr(4, len);
@ -249,6 +222,7 @@ Ox.load.Image = function(options, callback) {
}));
b = 0;
that.forEach(function(rgba, xy) {
// 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) {
@ -268,32 +242,70 @@ Ox.load.Image = function(options, callback) {
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);
return that;
};
that.decode = function() {
var callback = arguments[arguments.length - 1],
deflate = Ox.isBoolean(arguments[0]) ? arguments[0]
: Ox.isBoolean(arguments[1]) ? arguments[1] : true,
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) {
bin += mode < 1
? Ox.sum(Ox.range(8).map(function(bit) {
return +!!(self.data[i] & 1 << bit);
})) % 2
: +!!(self.data[i] & 1 << bit);
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)
len + 4 > getCapacity(bits.length)
&& error('decode');
str = '';
} else {
return false;
}
}
}
});
});
if (done == 2) {
return false;
}
}
});
try {
if (deflate) {
Ox.print('DEFLATE')
Ox.decodeDeflate(str, callback);
} else {
callback(Ox.decodeUTF8(str));
}
} catch (e) {
error('decode');
}
}
that.fillRect = function(x, y, w, h) {
self.context.fillRect(x, y, w, h);
return that;