forked from 0x2620/oxjs
image module update
This commit is contained in:
parent
1b4591dcbe
commit
1e38ff6b9e
4 changed files with 188 additions and 152 deletions
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue