2013-06-27 16:31:27 +02:00

192 lines
4.4 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*global define*/
define(
[ 'aux/canvas' ],
function( canvas_helper )
{
var canvas = document.createElement( 'canvas' );
var ctx = canvas.getContext( '2d' );
var tmp_canvas = document.createElement( 'canvas' );
var tmp_ctx = tmp_canvas.getContext( '2d' );
var canvas_size = { width: 10, height: 10 };
var base64_chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
var base64_map = base64_chars.split( '' );
var reverse_base64_map = { };
var iterations;
var quality;
var seed;
var amount;
var base64;
var byte_array;
var jpg_header_length;
var img;
var new_image_data;
var i;
var len;
base64_map.forEach( function( val, key ) { reverse_base64_map[val] = key; } );
function getGlitchedImageSrc( image_data, input, callback )
{
seed = input.seed / 100;
quality = input.quality / 100;
amount = input.amount / 100;
iterations = input.iterations;
canvas_helper.resize( canvas, image_data );
canvas_helper.resize( tmp_canvas, image_data );
base64 = getBase64FromImageData( image_data, quality );
byte_array = base64ToByteArray( base64 );
jpg_header_length = getJpegHeaderSize( byte_array );
for ( i = 0; i < iterations; i++ )
{
glitchJpegBytes( byte_array, jpg_header_length, seed, amount, i, iterations );
}
img = new Image();
img.onload = function() {
ctx.drawImage( img, 0, 0 );
new_image_data = ctx.getImageData( 0, 0, image_data.width, image_data.height );
callback( new_image_data );
};
img.src = byteArrayToBase64( byte_array );
}
function glitchJpegBytes( byte_array, jpg_header_length, seed, amount, i, len )
{
var max_index = byte_array.length - jpg_header_length - 4;
var px_min = parseInt( max_index / len * i, 10 );
var px_max = parseInt( max_index / len * ( i + 1 ), 10 );
var delta = px_max - px_min;
var px_i = parseInt( px_min + delta * seed, 10 );
if ( px_i > max_index )
{
px_i = max_index;
}
var index = Math.floor( jpg_header_length + px_i );
byte_array[index] = Math.floor( amount * 256 );
}
function getBase64FromImageData( image_data, quality )
{
var q = typeof quality === 'number' && quality < 1 && quality > 0 ? quality : 0.1;
tmp_ctx.putImageData( image_data, 0, 0 );
return tmp_canvas.toDataURL( 'image/jpeg', q );
}
function getJpegHeaderSize( data )
{
var result = 417;
for ( var i = 0, l = data.length; i < l; i++ )
{
if ( data[i] === 0xFF && data[i + 1] === 0xDA )
{
result = i + 2;
break;
}
}
return result;
}
// https://github.com/mutaphysis/smackmyglitchupjs/blob/master/glitch.html
// base64 is 2^6, byte is 2^8, every 4 base64 values create three bytes
function base64ToByteArray( str )
{
var result = [ ];
var digit_num;
var cur;
var prev;
for ( var i = 23, l = str.length; i < l; i++ )
{
cur = reverse_base64_map[ str.charAt( i ) ];
digit_num = ( i - 23 ) % 4;
switch ( digit_num )
{
// case 0: first digit - do nothing, not enough info to work with
case 1: // second digit
result.push( prev << 2 | cur >> 4 );
break;
case 2: // third digit
result.push( ( prev & 0x0f ) << 4 | cur >> 2 );
break;
case 3: // fourth digit
result.push( ( prev & 3 ) << 6 | cur );
break;
}
prev = cur;
}
return result;
}
function byteArrayToBase64( arr )
{
var result = [ 'data:image/jpeg;base64,' ];
var byte_num;
var cur;
var prev;
var i;
for ( var i = 0, l = arr.length; i < l; i++ )
{
cur = arr[i];
byte_num = i % 3;
switch ( byte_num )
{
case 0: // first byte
result.push( base64_map[ cur >> 2 ] );
break;
case 1: // second byte
result.push( base64_map[( prev & 3 ) << 4 | ( cur >> 4 )] );
break;
case 2: // third byte
result.push( base64_map[( prev & 0x0f ) << 2 | ( cur >> 6 )] );
result.push( base64_map[cur & 0x3f] );
break;
}
prev = cur;
}
if ( byte_num === 0 )
{
result.push( base64_map[( prev & 3 ) << 4] );
result.push( '==' );
}
else if ( byte_num === 1 )
{
result.push( base64_map[( prev & 0x0f ) << 2] );
result.push( '=' );
}
return result.join( '' );
}
function getImageDataCopy( image_data )
{
var copy = tmp_ctx.createImageData( image_data.width, image_data.height );
copy.data.set( image_data.data );
return copy;
}
return getGlitchedImageSrc;
}
);