From 3c403604bd8ee5a4d503ab032b10b238b6f9e99e Mon Sep 17 00:00:00 2001 From: Georg Fischer Date: Wed, 11 Sep 2013 21:37:17 +0200 Subject: [PATCH 1/2] rename the aux folder to util, because windows. fixes issue #3 --- scripts/src/glitch.js | 192 +++++++++++++++++++++++++++++++++++ scripts/src/main.js | 2 +- scripts/src/process.js | 2 +- scripts/util/canvas.js | 38 +++++++ scripts/util/feature-test.js | 48 +++++++++ 5 files changed, 280 insertions(+), 2 deletions(-) create mode 100644 scripts/src/glitch.js create mode 100644 scripts/util/canvas.js create mode 100644 scripts/util/feature-test.js diff --git a/scripts/src/glitch.js b/scripts/src/glitch.js new file mode 100644 index 0000000..ade55c0 --- /dev/null +++ b/scripts/src/glitch.js @@ -0,0 +1,192 @@ +/*global define*/ +define( + [ 'util/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; + } +); \ No newline at end of file diff --git a/scripts/src/main.js b/scripts/src/main.js index eea64c7..129f0af 100644 --- a/scripts/src/main.js +++ b/scripts/src/main.js @@ -20,7 +20,7 @@ require( 'src/controls', 'src/export-png', 'src/save-button', - 'aux/feature-test', + 'util/feature-test', 'lib/signals-1.0.0', 'lib/html5slider' ], diff --git a/scripts/src/process.js b/scripts/src/process.js index e2a96b2..26e26d2 100644 --- a/scripts/src/process.js +++ b/scripts/src/process.js @@ -1,6 +1,6 @@ /*global define, requestAnimationFrame*/ define( - [ 'aux/glitch', 'aux/canvas', 'lib/raf' ], + [ 'src/glitch', 'util/canvas', 'lib/raf' ], function( glitch, canvas_helper ) { var tmp_canvas = document.createElement( 'canvas' ); diff --git a/scripts/util/canvas.js b/scripts/util/canvas.js new file mode 100644 index 0000000..f7fe2dd --- /dev/null +++ b/scripts/util/canvas.js @@ -0,0 +1,38 @@ +/*global define*/ +define( + function() + { + var update = false; + + function resize( canvas, size ) + { + + if ( canvas.width !== size.width ) + { + canvas.width = size.width; + update = true; + } + + if ( canvas.height !== size.height ) + { + canvas.height = size.height; + update = true; + } + + if ( update ) + { + canvas.width = size.width; + canvas.height = size.height; + } + + update = false; + } + + function clear( canvas, ctx ) + { + ctx.clearRect( ctx, 0, 0, canvas.width, canvas.height ); + } + + return { resize: resize, clear: clear }; + } +); \ No newline at end of file diff --git a/scripts/util/feature-test.js b/scripts/util/feature-test.js new file mode 100644 index 0000000..f4beb28 --- /dev/null +++ b/scripts/util/feature-test.js @@ -0,0 +1,48 @@ +/*global define*/ +define( + function() + { + var tests = { + 'canvas': { required: true, test: function(){ return !! document.createElement('canvas').getContext; } }, + 'query-selector-all': { required: false, test: function(){ return !! document.querySelectorAll; } }, + 'drag-drop': { required: false, test: function(){ return 'draggable' in document.createElement('span'); } }, + 'file-api': { required: false, test: function(){ return typeof FileReader !== 'undefined'; } } + }; + + function test( success, error ) + { + var required_supported = true; + var results = { }; + var required_features_missing = [ ]; + + for ( var key in tests ) + { + var result = tests[key].test(); + + if ( ! result ) + { + if ( tests[key].required ) + { + required_supported = false; + + required_features_missing.push( key ); + } + } + + results[key] = result; + } + + if ( required_supported ) + { + success( results ); + } + + else + { + error( required_features_missing, results ); + } + } + + return test; + } +); \ No newline at end of file From 9d64a16c644dacb7c9c700240324529228cb39d3 Mon Sep 17 00:00:00 2001 From: Georg Fischer Date: Wed, 11 Sep 2013 21:45:13 +0200 Subject: [PATCH 2/2] remove obsolete files --- scripts/aux/canvas.js | 38 ------- scripts/aux/feature-test.js | 48 --------- scripts/aux/glitch.js | 192 ------------------------------------ 3 files changed, 278 deletions(-) delete mode 100644 scripts/aux/canvas.js delete mode 100644 scripts/aux/feature-test.js delete mode 100644 scripts/aux/glitch.js diff --git a/scripts/aux/canvas.js b/scripts/aux/canvas.js deleted file mode 100644 index f7fe2dd..0000000 --- a/scripts/aux/canvas.js +++ /dev/null @@ -1,38 +0,0 @@ -/*global define*/ -define( - function() - { - var update = false; - - function resize( canvas, size ) - { - - if ( canvas.width !== size.width ) - { - canvas.width = size.width; - update = true; - } - - if ( canvas.height !== size.height ) - { - canvas.height = size.height; - update = true; - } - - if ( update ) - { - canvas.width = size.width; - canvas.height = size.height; - } - - update = false; - } - - function clear( canvas, ctx ) - { - ctx.clearRect( ctx, 0, 0, canvas.width, canvas.height ); - } - - return { resize: resize, clear: clear }; - } -); \ No newline at end of file diff --git a/scripts/aux/feature-test.js b/scripts/aux/feature-test.js deleted file mode 100644 index f4beb28..0000000 --- a/scripts/aux/feature-test.js +++ /dev/null @@ -1,48 +0,0 @@ -/*global define*/ -define( - function() - { - var tests = { - 'canvas': { required: true, test: function(){ return !! document.createElement('canvas').getContext; } }, - 'query-selector-all': { required: false, test: function(){ return !! document.querySelectorAll; } }, - 'drag-drop': { required: false, test: function(){ return 'draggable' in document.createElement('span'); } }, - 'file-api': { required: false, test: function(){ return typeof FileReader !== 'undefined'; } } - }; - - function test( success, error ) - { - var required_supported = true; - var results = { }; - var required_features_missing = [ ]; - - for ( var key in tests ) - { - var result = tests[key].test(); - - if ( ! result ) - { - if ( tests[key].required ) - { - required_supported = false; - - required_features_missing.push( key ); - } - } - - results[key] = result; - } - - if ( required_supported ) - { - success( results ); - } - - else - { - error( required_features_missing, results ); - } - } - - return test; - } -); \ No newline at end of file diff --git a/scripts/aux/glitch.js b/scripts/aux/glitch.js deleted file mode 100644 index caa5499..0000000 --- a/scripts/aux/glitch.js +++ /dev/null @@ -1,192 +0,0 @@ -/*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; - } -); \ No newline at end of file