���ä����������ˡ�Ϥɤ�����

404 Blog Not Found:Ajax - �ǡ����� via PNG
�Ȥ��ɤ���������Ū�����롣

Demo 0

�����������˥��󥳡������Υ����������ɤ�������Ǥ��롣

$('#demo0 input').click(function(){
    $('#demo0dst').text(showTextInPNG($('#demo0img').get(0)));
});

Perl�ǥƥ����Ȥ���Ф������������ɤϰʲ��ΤȤ��ꡣ

#!/usr/bin/env perl
use strict;
use warnings;
use Imager;
use autodie;

my $img = Imager->new();
$img->read( file => shift ) or die $img->errstr;
$img->write( data => \my $pnm, type => 'pnm' ) or die $img->errstr;
my $hdr = do {
    $pnm =~ s/((?:[^\n]+\n){4})//;
    $1;
};
my @pnm = map { ord } split //, $pnm;
my $txt = '';
for my $i (0..+@pnm / 3){
    my $ord = (($pnm[3*$i]   & 0b00000111)<<5)
            + (($pnm[3*$i+1] & 0b00000011)<<3)
            +  ($pnm[3*$i+2] & 0b00000111);
    last if ! $ord;
    $txt .= chr $ord;
}
print $txt;

�ɤ���äƤ��?

�פ���ˡ�24bit���顼�θ�������16bit(RGB=565)�˸���������ǡ�������8bit�����1 byte�Υƥ����Ȥ�������Ǥ��롣�ԥ�������ʲ��ΥХ��ȿ���Ǥ�դΥƥ����Ȥ�������롣�ƥ����Ȥ����������ʬ�ϲ��˸��ο���#000000���Ȥ��Ƥ�⡹#070307�ˤ����ʤ餺�����Ƥ��̤�ͤ��ܤǤϤۤȤ�ɶ��̤��Ĥ��ʤ���

Demo 1

Get Image from URL:
Size:
0x0=0bytes
Text: 0
and
$('#demo0 input').click(function(){
    $('#demo0dst').text(showTextInPNG($('#demo0img').get(0)));
});

$('#demo1get').click(function(){
  $.get('http://api.dan.co.jp/datauri/' + $('#demo1url').val(), function(txt){
    $('#demo1img').attr('src', txt)
  })
});

$('#demo1img').load(function(){
  $('#demo1w').text(this.width);
  $('#demo1h').text(this.height);
  $('#demo1s').text(this.height*this.width);
});

$('#demo1txt').keyup(function(){
  var text = this.value,
      chars = text.length,
      bytes = Base64.utob(text).length;
  $('#demo1st').text([chars, 'chars,', bytes, 'bytes'].join(' '));
}).trigger('keyup');

$('#demo1embed').click(function(){
  $('#demo1timg').attr('src', 
    hideTextInPNG($('#demo1img').get(0), $('#demo1txt').val())
  );
});

$('#demo1extract').click(function(){
  $('#demo1dst').text(showTextInPNG($('#demo1timg').get(0)));
});

JavaScript�ˤ�����

/*
 * You need base64.js.
 * cf: http://blog.livedoor.jp/dankogai/archives/51067688.html
*/

showTextInPNG = function(node) {
    var el  = document.createElement("canvas"),
        ctx = el.getContext("2d"),
        w   = el.width  = el.style.width  = node.width,
        h   = el.height = el.style.height = node.height;
    ctx.drawImage(node, 0, 0);
    var d = ctx.getImageData(0, 0, w, h).data,
        a = [];
    for(var i = 0, l = d.length; i < l; i += 4) {
        var c = ((d[i]   & 0x7) << 5)
              + ((d[i+1] & 0x3) << 3)
              +  (d[i+2] & 0x7);
        if (!c) break;
        a.push(String.fromCharCode(c));
    }
    return Base64.btou(a.join(''));
};

hideTextInPNG = function(node, txt) {
    var el  = document.createElement("canvas"),
        ctx = el.getContext("2d"),
        w   = el.width  = el.style.width  = node.width,
        h   = el.height = el.style.height = node.height,
        bin = Base64.utob(txt);
    ctx.drawImage(node, 0, 0);
    var imd = ctx.getImageData(0, 0, w, h),
        d = imd.data,
        a = [];
    for(var i = 0, l = d.length; i < l; i += 4) {
        var ord = bin.charCodeAt(i >> 2);
        d[i]   = (d[i]   & 0xf8) + ((ord & 0xf8) >> 5);
        d[i+1] = (d[i+1] & 0xfc) + ((ord & 0x18) >> 3);
        d[i+2] = (d[i+2] & 0xf8) +  (ord & 0x07);
    }
    ctx.putImageData(imd, 0, 0);
    return el.toDataURL('image/png');
};

See Also:

Dan the Steganographer