add image methods example
This commit is contained in:
parent
581b87baf9
commit
c8e25562db
8 changed files with 165 additions and 26 deletions
|
@ -3,7 +3,7 @@
|
||||||
<head>
|
<head>
|
||||||
<title>OxJS Image Demo</title
|
<title>OxJS Image Demo</title
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
|
||||||
<script type="text/javascript" src="../../build/Ox.js"></script>
|
<script type="text/javascript" src="../../dev/Ox.js"></script>
|
||||||
<script type="text/javascript" src="js/image.js"></script>
|
<script type="text/javascript" src="js/image.js"></script>
|
||||||
</head>
|
</head>
|
||||||
<body></body>
|
<body></body>
|
||||||
|
|
|
@ -2,15 +2,21 @@ Ox.load('Image', function() {
|
||||||
|
|
||||||
// see http://en.wikipedia.org/wiki/Lenna
|
// see http://en.wikipedia.org/wiki/Lenna
|
||||||
|
|
||||||
Ox.Image('png/Lenna.png', function(image) {
|
Ox.Image('png/lenna256.png', function(image) {
|
||||||
var body = Ox.element('body'),
|
var body = Ox.element('body'),
|
||||||
select = Ox.element('<select>').appendTo(body);
|
select = Ox.element('<select>').appendTo(body);
|
||||||
[
|
[
|
||||||
'Method...', 'blur(1)', 'blur(5)',
|
'Method...', 'src("png/lenna256.png")',
|
||||||
|
'blur(1)', 'blur(5)',
|
||||||
'channel("r")', 'channel("g")', 'channel("b")', 'channel("a")',
|
'channel("r")', 'channel("g")', 'channel("b")', 'channel("a")',
|
||||||
'channel("h")', 'channel("s")', 'channel("l")',
|
'channel("h")', 'channel("s")', 'channel("l")',
|
||||||
'contour()',
|
'contour()',
|
||||||
'depth(1)', 'depth(2)', 'depth(4)',
|
'depth(1)', 'depth(2)', 'depth(4)',
|
||||||
|
'drawCircle([128, 128], 64, {"fill": "rgba(0, 0, 0, 0.5)"})',
|
||||||
|
'drawLine([[64, 64], [192, 192]], {"color": "red", "width": 2})',
|
||||||
|
'drawPath([[64, 64], [192, 64], [64, 192]], {"close": true, "fill": "rgba(0, 0, 0, 0.5)", "width": 2})',
|
||||||
|
'drawRectangle([64, 64], [128, 128], {"fill": "rgba(0, 0, 0, 0.5)"})',
|
||||||
|
'drawText("?", [128, 160], {"font": "64px Arial", "outline": "2px white"})',
|
||||||
'edges()', 'emboss()',
|
'edges()', 'emboss()',
|
||||||
'encode("secret")', 'decode()',
|
'encode("secret")', 'decode()',
|
||||||
'encode("secret", false)', 'decode(false)',
|
'encode("secret", false)', 'decode(false)',
|
||||||
|
@ -24,46 +30,39 @@ Ox.load('Image', function() {
|
||||||
'resize(256, 256)', 'resize(512, 512)',
|
'resize(256, 256)', 'resize(512, 512)',
|
||||||
'saturation(-0.5)', 'saturation(0.5)',
|
'saturation(-0.5)', 'saturation(0.5)',
|
||||||
'scale(0.5, -1)',
|
'scale(0.5, -1)',
|
||||||
'sharpen()', 'solarize()',
|
'sharpen()', 'solarize()'
|
||||||
'src("png/Lenna.png")', 'src("png/OxJS.png")'
|
|
||||||
].forEach(function(filter) {
|
].forEach(function(filter) {
|
||||||
Ox.element('<option>').html(filter).appendTo(select);
|
Ox.element('<option>').html(filter).appendTo(select);
|
||||||
});
|
});
|
||||||
select[0].onchange = function() {
|
select[0].onchange = function() {
|
||||||
if (select[0].value[0] == select[0].value[0].toLowerCase()) {
|
if (select[0].value[0] == select[0].value[0].toLowerCase()) {
|
||||||
var split = select[0].value.split('('),
|
//Ox.print(select[0].value.match(/^(\w+)\((.+)\)$/))
|
||||||
fn = split[0],
|
var match = select[0].value.match(/^(\w+)\((.*?)\)$/),
|
||||||
args = split[1].length == 1 ? []
|
fn = match[1],
|
||||||
: split[1].split(')')[0].split(', ').map(function(v) {
|
args = JSON.parse('[' + match[2] + ']');
|
||||||
return v == 'true' ? true
|
//Ox.print('??', fn, args, image.drawLine)
|
||||||
: v == 'false'? false
|
|
||||||
: v[0] == '"' ? v.split('"')[1]
|
|
||||||
: parseFloat(v);
|
|
||||||
});
|
|
||||||
if (fn == 'encode' || fn == 'src') {
|
if (fn == 'encode' || fn == 'src') {
|
||||||
image[fn].apply(null, Ox.merge(args, function(image) {
|
image[fn].apply(null, Ox.merge(args, function(image) {
|
||||||
Ox.element('#filter').attr({
|
Ox.element('#image').attr({
|
||||||
src: image.src()
|
src: image.src()
|
||||||
}).css({width: '512px', height: '512px'});
|
});
|
||||||
}));
|
}));
|
||||||
} else if (fn == 'decode') {
|
} else if (fn == 'decode') {
|
||||||
image[fn].apply(null, Ox.merge(args, function(str) {
|
image[fn].apply(null, Ox.merge(args, function(str) {
|
||||||
alert(str);
|
alert(str);
|
||||||
}));
|
}));
|
||||||
} else {
|
} else {
|
||||||
Ox.element('#filter').attr({
|
Ox.element('#image').attr({
|
||||||
src: image[fn].apply(null, args).src()
|
src: image[fn].apply(null, args).src()
|
||||||
});
|
});
|
||||||
|
Ox.print('DONE')
|
||||||
}
|
}
|
||||||
select[0].selectedIndex = 0;
|
select[0].selectedIndex = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ox.element('<br>').appendTo(body);
|
Ox.element('<br>').appendTo(body);
|
||||||
Ox.element('<img>').attr({
|
Ox.element('<img>').attr({
|
||||||
src: image.src()
|
id: 'image',
|
||||||
}).appendTo(body);
|
|
||||||
Ox.element('<img>').attr({
|
|
||||||
id: 'filter',
|
|
||||||
src: image.src()
|
src: image.src()
|
||||||
}).appendTo(body);
|
}).appendTo(body);
|
||||||
//Ox.element('<img>').attr({src: image.saturation(0.5).blur().url()}).appendTo(Ox.element('body'));
|
//Ox.element('<img>').attr({src: image.saturation(0.5).blur().url()}).appendTo(Ox.element('body'));
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 464 KiB |
8
examples/lenna/css/example.css
Normal file
8
examples/lenna/css/example.css
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
body {
|
||||||
|
margin: 16px;
|
||||||
|
background-color: rgb(240, 240, 240);
|
||||||
|
}
|
||||||
|
img {
|
||||||
|
display: block;
|
||||||
|
margin: 8px 0 0 2px;
|
||||||
|
}
|
13
examples/lenna/index.html
Normal file
13
examples/lenna/index.html
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Lenna</title>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
|
||||||
|
<link rel="shortcut icon" type="image/png" href="../../source/Ox.UI/png/icon16.png"/>
|
||||||
|
<link rel="stylesheet" type="text/css" href="css/example.css"/>
|
||||||
|
<script type="text/javascript" src="../../dev/Ox.js"></script>
|
||||||
|
<script type="text/javascript" src="js/example.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
</body>
|
||||||
|
</html>
|
90
examples/lenna/js/example.js
Normal file
90
examples/lenna/js/example.js
Normal file
|
@ -0,0 +1,90 @@
|
||||||
|
/*
|
||||||
|
Load the image module.
|
||||||
|
*/
|
||||||
|
Ox.load('Image', function() {
|
||||||
|
|
||||||
|
/*
|
||||||
|
Load our image (about which you can read more on
|
||||||
|
<a href="see http://en.wikipedia.org/wiki/Lenna">Wikipedia</a>).
|
||||||
|
*/
|
||||||
|
Ox.Image('png/lenna256.png', function(image) {
|
||||||
|
|
||||||
|
/*
|
||||||
|
Create some DOM elements.
|
||||||
|
*/
|
||||||
|
var $body = Ox.$('body'),
|
||||||
|
$select = Ox.$('<select>').bind({change: change}).appendTo($body),
|
||||||
|
$image = Ox.$('<img>').attr({src: image.src()}).appendTo($body);
|
||||||
|
|
||||||
|
[
|
||||||
|
'Method...', 'src("png/lenna256.png")',
|
||||||
|
'blur(2)', 'blur(4)',
|
||||||
|
'channel("r")', 'channel("g")', 'channel("b")',
|
||||||
|
'channel("h")', 'channel("s")', 'channel("l")',
|
||||||
|
'contour()',
|
||||||
|
'depth(1)', 'depth(2)', 'depth(4)',
|
||||||
|
'drawCircle([128, 128], 64, {"fill": "rgba(0, 0, 0, 0.5)"})',
|
||||||
|
'drawLine([[64, 64], [192, 192]], {"color": "green", "width": 2})',
|
||||||
|
'drawPath([[64, 64], [192, 64], [64, 192]], {"close": true})',
|
||||||
|
'drawRectangle([64, 64], [128, 128], {"fill": "red", "width": 0})',
|
||||||
|
'drawText("?", [16, 240], {"color": "blue", "font": "64px Arial"})',
|
||||||
|
'edges()', 'emboss()',
|
||||||
|
'encode("secret")', 'decode()',
|
||||||
|
'encode("secret", false)', 'decode(false)',
|
||||||
|
'encode("secret", 1)', 'decode(1)',
|
||||||
|
'encode("secret", false, 15)', 'decode(false, 15)',
|
||||||
|
'encode("secret", 127)', 'decode(127)',
|
||||||
|
'filter([0, 1, 0, 1, -2, 1, 0, 1, 0])',
|
||||||
|
'hue(-60)', 'hue(60)',
|
||||||
|
'invert()',
|
||||||
|
'lightness(-0.5)', 'lightness(0.5)',
|
||||||
|
'map(function(v, xy) { return Ox.sum(xy) % 2 ? [0, 0, 0] : v; })',
|
||||||
|
'mosaic(4)', 'motionBlur()',
|
||||||
|
'photocopy()', 'pixel([16, 16], [255, 255, 255])', 'posterize()',
|
||||||
|
'saturation(-0.5)', 'saturation(0.5)',
|
||||||
|
'sharpen()', 'solarize()'
|
||||||
|
].forEach(function(method) {
|
||||||
|
Ox.$('<option>').html(method).appendTo($select);
|
||||||
|
});
|
||||||
|
|
||||||
|
function change() {
|
||||||
|
var value = $select.val(),
|
||||||
|
match = value.match(/^(\w+)\((.*?)\)$/),
|
||||||
|
fn = match[1], args;
|
||||||
|
/*
|
||||||
|
The <code>map</code> method takes a function as its argument, which
|
||||||
|
we can't <code>JSON.parse</code>, but have to <code>eval</code>.
|
||||||
|
*/
|
||||||
|
try {
|
||||||
|
args = JSON.parse('[' + match[2] + ']');
|
||||||
|
} catch(e) {
|
||||||
|
args = [eval('f = ' + match[2])];
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
The <code>src</code> and <code>encode</code> methods are
|
||||||
|
asynchronous and take a callback function.
|
||||||
|
*/
|
||||||
|
if (fn == 'src' || fn == 'encode') {
|
||||||
|
image[fn].apply(null, Ox.merge(args, function(image) {
|
||||||
|
$image.attr({src: image.src()});
|
||||||
|
}));
|
||||||
|
/*
|
||||||
|
The <code>decode</code> method is asynchronous too, and its callback
|
||||||
|
function gets passed a string.
|
||||||
|
*/
|
||||||
|
} else if (fn == 'decode') {
|
||||||
|
image[fn].apply(null, Ox.merge(args, function(str) {
|
||||||
|
alert(str);
|
||||||
|
}));
|
||||||
|
/*
|
||||||
|
All other methods simply return the image.
|
||||||
|
*/
|
||||||
|
} else {
|
||||||
|
$image.attr({src: image[fn].apply(null, args).src()});
|
||||||
|
}
|
||||||
|
$select.val('Method...');
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
BIN
examples/lenna/png/lenna256.png
Normal file
BIN
examples/lenna/png/lenna256.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 116 KiB |
|
@ -1,9 +1,25 @@
|
||||||
|
/*
|
||||||
|
Ox.Image provides a pair of methods, <code>encode</code> and
|
||||||
|
<code>decode</code>, which can be used for
|
||||||
|
<a href="http://en.wikipedia.org/wiki/Steganography">steganography</a>, i.e. to
|
||||||
|
add a hidden message to an image.<br><br>
|
||||||
|
The signature of the <code>encode</code> function is
|
||||||
|
<code>image.encode(message, deflate, mode, callback)</code>.
|
||||||
|
<code>deflate</code> turns deflate-compression on or off, and <code>mode</code>
|
||||||
|
determines which bits of the image the message will be written to — but
|
||||||
|
for most purposes, the default values (<code>true</code> and <code>0</code>)
|
||||||
|
are fine, so <code>deflate</code> and <code>mode</code> can be omitted.<br>
|
||||||
|
<br>
|
||||||
|
In this example, we demonstrate a valid use case for <code>deflate</code> and
|
||||||
|
<code>mode</code>: To encode an decoy message (a line of text), which will be
|
||||||
|
relatively easy to detect, and then the the actual message, (another image,
|
||||||
|
itself containing another line of text), which will be harder to detect.
|
||||||
|
*/
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
Ox.load('Image', function() {
|
Ox.load('Image', function() {
|
||||||
|
|
||||||
var $body = Ox.$('body'),
|
var $table = Ox.$('<table>').appendTo(Ox.$('body')),
|
||||||
$table = Ox.$('<table>').appendTo($body),
|
|
||||||
$tr,
|
$tr,
|
||||||
text = {
|
text = {
|
||||||
iceland: 'The first image he told me about '
|
iceland: 'The first image he told me about '
|
||||||
|
@ -11,11 +27,21 @@ Ox.load('Image', function() {
|
||||||
vietnam: 'He said for him it was the image of happiness, '
|
vietnam: 'He said for him it was the image of happiness, '
|
||||||
+ 'and that he had often tried to link it to other images, '
|
+ 'and that he had often tried to link it to other images, '
|
||||||
+ 'but it had never worked.'
|
+ 'but it had never worked.'
|
||||||
},
|
};
|
||||||
i = 0;
|
|
||||||
|
|
||||||
encode(decode);
|
encode(decode);
|
||||||
|
|
||||||
|
/*
|
||||||
|
So we first encode two lines text into two images, by writing them bit by
|
||||||
|
bit (without compression, <code>deflate = false</code>), into the least
|
||||||
|
significant bit of each 8-bit RGB value (<code>mode = 1</code>). Then we
|
||||||
|
encode one image into the other: We take the (deflate-compressed,
|
||||||
|
<code>deflate = true</code>) data URL of the source image and flip, if
|
||||||
|
needed, the second least significant bit of each RGB value of the target
|
||||||
|
image, so that the number of bits set to 1, modulo 2 (for example: 10101010
|
||||||
|
-> 0), is the bit we're encoding (<code>mode = -1</code>). As the least
|
||||||
|
significant bit remains untouched, this will preserve the encoded text.
|
||||||
|
*/
|
||||||
function encode(callback) {
|
function encode(callback) {
|
||||||
status('Load iceland.png');
|
status('Load iceland.png');
|
||||||
Ox.Image('png/iceland.png', function(iceland) {
|
Ox.Image('png/iceland.png', function(iceland) {
|
||||||
|
@ -49,6 +75,9 @@ Ox.load('Image', function() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Finally, we decode all the data again.
|
||||||
|
*/
|
||||||
function decode(iceland) {
|
function decode(iceland) {
|
||||||
status('Decode the least signigicant bits of iceland.png');
|
status('Decode the least signigicant bits of iceland.png');
|
||||||
iceland.decode(false, 1, function(str) {
|
iceland.decode(false, 1, function(str) {
|
||||||
|
@ -91,7 +120,7 @@ Ox.load('Image', function() {
|
||||||
} else {
|
} else {
|
||||||
$td.append(value);
|
$td.append(value);
|
||||||
}
|
}
|
||||||
$tr.append($td)
|
$tr.append($td);
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
Loading…
Reference in a new issue