add image methods example

This commit is contained in:
rolux 2012-04-14 11:46:46 +02:00
parent 581b87baf9
commit c8e25562db
8 changed files with 165 additions and 26 deletions

View file

@ -3,7 +3,7 @@
<head>
<title>OxJS Image Demo</title
<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>
</head>
<body></body>

View file

@ -2,15 +2,21 @@ Ox.load('Image', function() {
// 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'),
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("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": "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()',
'encode("secret")', 'decode()',
'encode("secret", false)', 'decode(false)',
@ -24,46 +30,39 @@ Ox.load('Image', function() {
'resize(256, 256)', 'resize(512, 512)',
'saturation(-0.5)', 'saturation(0.5)',
'scale(0.5, -1)',
'sharpen()', 'solarize()',
'src("png/Lenna.png")', 'src("png/OxJS.png")'
'sharpen()', 'solarize()'
].forEach(function(filter) {
Ox.element('<option>').html(filter).appendTo(select);
});
select[0].onchange = function() {
if (select[0].value[0] == select[0].value[0].toLowerCase()) {
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);
});
//Ox.print(select[0].value.match(/^(\w+)\((.+)\)$/))
var match = select[0].value.match(/^(\w+)\((.*?)\)$/),
fn = match[1],
args = JSON.parse('[' + match[2] + ']');
//Ox.print('??', fn, args, image.drawLine)
if (fn == 'encode' || fn == 'src') {
image[fn].apply(null, Ox.merge(args, function(image) {
Ox.element('#filter').attr({
Ox.element('#image').attr({
src: image.src()
}).css({width: '512px', height: '512px'});
});
}));
} else if (fn == 'decode') {
image[fn].apply(null, Ox.merge(args, function(str) {
alert(str);
}));
} else {
Ox.element('#filter').attr({
Ox.element('#image').attr({
src: image[fn].apply(null, args).src()
});
Ox.print('DONE')
}
select[0].selectedIndex = 0;
}
}
Ox.element('<br>').appendTo(body);
Ox.element('<img>').attr({
src: image.src()
}).appendTo(body);
Ox.element('<img>').attr({
id: 'filter',
id: 'image',
src: image.src()
}).appendTo(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

View 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
View 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>

View 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...');
}
});
});

Binary file not shown.

After

Width:  |  Height:  |  Size: 116 KiB

View file

@ -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 &mdash; 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';
Ox.load('Image', function() {
var $body = Ox.$('body'),
$table = Ox.$('<table>').appendTo($body),
var $table = Ox.$('<table>').appendTo(Ox.$('body')),
$tr,
text = {
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, '
+ 'and that he had often tried to link it to other images, '
+ 'but it had never worked.'
},
i = 0;
};
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
-&gt; 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) {
status('Load iceland.png');
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) {
status('Decode the least signigicant bits of iceland.png');
iceland.decode(false, 1, function(str) {
@ -91,7 +120,7 @@ Ox.load('Image', function() {
} else {
$td.append(value);
}
$tr.append($td)
$tr.append($td);
}
});