glitch-images/scripts/workers/glitchworker.js
2015-12-23 23:09:12 +01:00

139 lines
3.0 KiB
JavaScript

self.addEventListener( 'message', receivedMessageEvent, false );
function receivedMessageEvent ( event ) {
if (
event &&
event.data &&
event.data.glitch &&
event.data.glitch.base64 &&
event.data.glitch.parameters
) {
self.postMessage( { glitched: getGlitchedImageData( event.data.glitch.base64, event.data.glitch.parameters ) } );
} else {
self.postMessage( event.data );
}
}
var base64Chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
var base64Map = base64Chars.split( '' );
var reversedBase64Map = { };
var base64ImageData;
var byteArrayImageData;
var jpgHeaderLength = 0;
var params;
var i = 0;
var len = 0;
base64Map.forEach( function ( val, key ) {
reversedBase64Map[val] = key;
} );
function getGlitchedImageData ( base64ImageData, parameters ) {
params = parameters;
byteArrayImageData = base64ToByteArray( base64ImageData );
jpgHeaderLength = getJpegHeaderSize( byteArrayImageData );
for ( i = 0, len = params.iterations; i < len; i++ ) {
glitchJpegBytes( byteArrayImageData, jpgHeaderLength, params.seed, params.amount, i, params.iterations );
}
return byteArrayToBase64( byteArrayImageData );
}
function glitchJpegBytes ( byteArray, jpgHeaderLength, seed, amount, i, len ) {
var maxIndex = byteArray.length - jpgHeaderLength - 4;
var pxMin = parseInt( maxIndex / len * i, 10 );
var pxMax = parseInt( maxIndex / len * ( i + 1 ), 10 );
var delta = pxMax - pxMin;
var pxIndex = parseInt( pxMin + delta * seed, 10 );
if ( pxIndex > maxIndex ) {
pxIndex = maxIndex;
}
var index = Math.floor( jpgHeaderLength + pxIndex );
byteArray[index] = Math.floor( amount * 256 );
}
function base64ToByteArray ( str ) {
var result = [ ];
var digitNum;
var cur;
var prev;
for ( i = 23, len = str.length; i < len; i++ ) {
cur = reversedBase64Map[str.charAt( i )];
digitNum = ( i - 23 ) % 4;
switch ( digitNum ) {
case 1:
result.push( prev << 2 | cur >> 4 );
break;
case 2:
result.push( ( prev & 15 ) << 4 | cur >> 2 );
break;
case 3:
result.push( ( prev & 3 ) << 6 | cur );
break;
}
prev = cur;
}
return result;
}
function byteArrayToBase64 ( arr ) {
var result = [ 'data:image/jpeg;base64,' ];
var byteNum;
var cur;
var prev;
for ( i = 0, len = arr.length; i < len; i++ ) {
cur = arr[i];
byteNum = i % 3;
switch (byteNum) {
case 0:
result.push( base64Map[cur >> 2] );
break;
case 1:
result.push( base64Map[( prev & 3 ) << 4 | cur >> 4] );
break;
case 2:
result.push( base64Map[( prev & 15 ) << 2 | cur >> 6] );
result.push( base64Map[cur & 63] );
break;
}
prev = cur;
}
if ( byteNum === 0 ) {
result.push( base64Map[( prev & 3 ) << 4] );
result.push( '==' );
} else if ( byteNum === 1 ) {
result.push( base64Map[( prev & 15 ) << 2] );
result.push( '=' );
}
return result.join( '' );
}
function getJpegHeaderSize ( data ) {
var result = 417;
for ( i = 0, len = data.length; i < len; i++ ) {
if ( data[i] === 255 && data[i + 1] === 218 ) {
result = i + 2;
break;
}
}
return result;
}