//////////////////////////////////////////////////////////////////////////////// // // File: LZW.as // Path: com.enso.LZW // // Modified by: Grant Cox // Copyright: © 2005 Grant Cox, enso . // // // Original code from: // http://www.razorberry.com/blog/archives/2004/08/22/lzw-compression-methods-in-as2/ // // A class for LZW compression modified from code posted at the following URL's // http://www.shoe-box.org/blog/index.php/2004/05/05/13-CompressionLzw // http://www.lalex.com/blog/comments/200405/164-compression-lzw-actionscript-2.html // //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// // // Class: LZW // // Utility functions for compressing arbitrary 8bit into an LZW stream // //////////////////////////////////////////////////////////////////////////////// class LZW { //////////////////////////////////////////////////////////////////////////// // // Function: compress // // Creates and returns an array of integer Numbers (often multibyte) which // is the LZW compressed version of the passed data. The return type can // optionally be a String of multibyte chars, depending on the second parameter. // // Parameters: // input_array - the data to compress, can be a string of 8bit chars, or an // array of 8bit char/integers. // as_array - Boolean, whether the return value should be an array of Numbers, // or a String of multibyte chars. // // Returns: // Array of integer Numbers / String of multibyte chars. // //////////////////////////////////////////////////////////////////////////// public static function compress( input_array, return_array ) { if ( return_array == undefined ) return_array == true; // create indices for all single byte values var dico:Array = new Array(); for (var i = 0; i < 256; i++) { dico[String(i)] = i; } var returnArray:Array = new Array(); var splitStr:Array; if ( input_array instanceof Array ){ splitStr = input_array; } else { splitStr = input_array.split(""); } var input_length:Number = splitStr.length; var next_index:Number = 256; var buffer:Array = new Array(); // for each character in the string to compress for (var i = 0; i <= input_length; i++) { // create a string from this character, and any in the buffer // this string is in the format 123-432-54 where the numbers // are the charCodes of the respective characters var current_charcode = splitStr[i]; if ( typeof(current_charcode) == "string" ){ current_charcode = current_charcode.charCodeAt(0); } //trace(" current: " + current + " current_charcode: " + current_charcode ); var buffer_joined:String = ""; if (buffer.length == 0) { var xstr = "" + current_charcode; } else { buffer_joined = buffer.join("-"); var xstr = buffer_joined + "-" + current_charcode; } // if we already have a key in the dictionary for this string sequence // then keep on looking at more characters if (dico[xstr] !== undefined) { buffer.push( current_charcode ); } else { // if we don't yet have a key for the new sequence, then add the index // of the previous sequence (ie minus the last character) to our // returnString. But also add a key for this full sequence, so any further // matches will be found var match_index:Number = dico[ buffer_joined ]; returnArray.push( match_index ); dico[xstr] = next_index; next_index++; delete buffer; buffer = [ current_charcode ]; } } if ( return_array ){ return returnArray; } else { var returnString:String = ""; for ( var i:Number = 0; i< returnArray.length; i++ ){ returnString += String.fromCharCode( returnArray[i] ); } return returnString; } } //////////////////////////////////////////////////////////////////////////// // // Function: decompress // // Creates and returns an array of 8bit integers which is the decompressed // version of the passed LZW compressed data. The data can be returned as // a string of 8bit chars rather than array of integers, depending on the // second parameter. // // Parameters: // input_array - the data to decompress, can either be a string of multibyte // chars, or an array of integer Numbers (multibyte allowed). // as_array - Boolean, whether the return value should be an array of 8bit // integers, or a string of 8bit chars. // // Returns: // Array of integer Numbers / String of 8bit chars. // //////////////////////////////////////////////////////////////////////////// public static function decompress( input_array, as_array) { if ( as_array == undefined ) as_array = true; var dico:Array = new Array(); for (var i = 0; i < 256; i++) { var c:String = String.fromCharCode(i); dico[i] = c; } var splitStr:Array; if ( input_array instanceof Array ){ splitStr = input_array; } else { splitStr = input_array.split(""); } var len:Number = splitStr.length; var nbChar:Number = 256; var buffer:String = ""; var chaine:String = ""; var returnString:String = ""; var returnArray:Array = new Array(); for (var i = 0; i < len; i++) { var code = splitStr[i]; if ( typeof(code) == "string" ) code = splitStr[i].charCodeAt(0); var current:String = dico[code]; if (buffer == "") { buffer = current; returnString += current; returnArray.push( current.charCodeAt(0) ); } else { if (code <= 255) { returnString += current; returnArray.push( current.charCodeAt(0) ); chaine = buffer + current; dico[nbChar] = chaine; nbChar++; buffer = current; } else { chaine = dico[code]; if (chaine == undefined) chaine = buffer + buffer.slice(0,1); returnString += chaine; for ( var j:Number =0; j < chaine.length; j++ ){ returnArray.push( chaine.charCodeAt(j) ); } dico[nbChar] = buffer + chaine.slice(0, 1); nbChar++; buffer = chaine; } } } if ( as_array ){ return returnArray; } else { return returnString; } } }