/// /// class SimZip /// Compression/Decompression code to be used with SimFile format. /// /// 18 Mar 2009 - D.Bozarth - Sonoma State Engineering Science /// #region Using directives using System; using System.Collections.Generic; using System.IO; using System.Diagnostics; using Utility; #endregion namespace SimFile { public class SimZip : SimFile { #region Constants // #region Version1.0 // public const int HDR_FLG_SIZE = 1; public const int HDR_SEG_SIZE = HDR_FLG_SIZE + 1; // Applies only to current version! (use for write only) // #endregion #region VersionAll // public const byte HDR_FLG_SEMA = 0xff; public const byte HDR_FLG_DFLT = 0x00; public const byte HFLG_HDRJ_F = 0xfe; // Header Flag AND-bit mask: (Sweep Headers not jagged) public const byte HFLG_HDRJ_T = 0x01; // Header Flag OR-bit mask: (Sweep Headers jagged) public const byte HFLG_DATJ_F = 0xfd; // Header Flag AND-bit mask: (Signal Data not jagged) public const byte HFLG_DATJ_T = 0x02; // Header Flag OR-bit mask: (Signal Data jagged) public const string COMPRESS_EXE = @"c:\lzma\lzma.exe"; public const string DECOMPRESS_EXE = @"c:\lzma\lzma.exe"; public const string VERSION_HDR_FILE = @"..\..\version.hdr.txt"; public const string DATA_SZ_HDR_FILE = @"..\..\data.sz.hdr.lzma"; public const string DATA_SZ_TMP_FILE = @"..\..\data.sz.hdr.txt"; public const string cmFile0 = @"..\..\fileHdr.lzma"; public const string cmFile1 = @"..\..\fileHdr.raw"; public const string cmFile2 = @"..\..\swphdr.final.lzma"; public const string cmFile3 = @"..\..\swphdr.final.raw"; public const string cmFile4 = @"..\..\short.final.lzma"; public const string cmFile5 = @"..\..\short.final.raw"; public const string cmFile6 = @"..\..\abcde3.nis.lzma"; public const string cmFile7 = @"..\..\abcde3.nis.raw"; public const string cmFile8 = @"..\..\abcde012.raw"; public enum VerSupport { v1_0, None = -1 }; public enum ZipContent { FileHdr, SwpHdr, IntegerData, Signal012, Signal3 }; // #endregion // #endregion #region Contained classes of class SimZip // public class SimZipTest { static int Main( string[] args ) { Io.Result rtn = Io.Result.OK; SimZip zp = new SimZip(); try { if ( args[0] == "e" ) { rtn = zp.Compress( args[1], args[2], false); } else { if ( args[0] == "d" ) { rtn = zp.Decompress( args[1], args[2] ); } else { Console.WriteLine( "Syntax: SimZip [e|d] inFilePath outFilePath" ); } } } catch ( Exception ex ) { Console.WriteLine( ex.Message ); Console.WriteLine( ex.StackTrace ); } return (int) rtn; } // method Main } // class SimZipTest public class SimZipException : ApplicationException { public SimZipException( String message ) : base( message ) {} public SimZipException( String message, Exception inner ) : base( message, inner ) {} } // #endregion #region Methods of class SimZip /* * Limitation: inFile should have (size < Int32.MaxValue). * szChkFlg: false => Normal operation. true => (inFile < outFile => delete outFile, return NoAction). * Assumption: All samples are well-formed, including complete Integer and Signal components. * .. (Thus FileContent.IntegerData can be used to determine jagged arrays for Integer, Bt3, and Bt012.) * Returns OK, or NoAction. Throws SimZipException. */ public Io.Result Compress( string inFile, string outFile, bool szChkFlg ) { string[] cmFiles = { VERSION_HDR_FILE, DATA_SZ_HDR_FILE, cmFile0, cmFile2, cmFile4, cmFile6, cmFile8 }; Io.Result rtn = FileRead( inFile ); // rtn == OK unless exception thrown. FileStream fs = File.OpenRead( inFile ); long szIn; try { szIn = fs.Length; } catch ( Exception ex ) { throw new SimZipException( "Caught in SimZip.Compress(string,string,bool)" , ex ); } finally { fs.Close(); } bool hdrJg, datJg; int[] szAry; int[] bufSize = { BUF_SIZE_DFLT }; int[] empty = new int[0]; rtn = FindJaggedContent( FileContent.SwpHdr, out hdrJg, out szAry ); rtn = FindJaggedContent( FileContent.IntegerData,out datJg, out szAry ); // rtn == OK unless exception thrown // Build the 'Header Flags' byte array that will be stored (uncompressed) // .. following the Version Id string. byte[] hdrFlgs = new byte[1]; hdrFlgs[0] = 0x00; if ( hdrJg ) hdrFlgs[0] |= HFLG_HDRJ_T; if ( datJg ) hdrFlgs[0] |= HFLG_DATJ_T; WriteVersionHeader( VERSION_HDR_FILE, hdrFlgs ); WriteDataSizeHeader( DATA_SZ_HDR_FILE, DATA_SZ_TMP_FILE, szAry, nBytesInt16PerSample ); // Encode the file header. rtn = UnpackFileComponent( cmFile0, cmFile1, FileContent.FileHdr, StreamProcessor.TransformCopyStream, bufSize ); // rtn == OK unless exception was thrown StreamProcessor.Transform delegateTransform; int[] intAry; // Encode the sweep headers. if ( hdrJg ) { delegateTransform = StreamProcessor.TransformCopyStream; intAry = bufSize; } else { delegateTransform = StreamProcessor.TransformTranspose; intAry = empty; } rtn = UnpackFileComponent( cmFile2, cmFile3, FileContent.SwpHdr, delegateTransform, intAry ); // Encode the integer data. if ( datJg ) { delegateTransform = SimZip.TransformIntegerDataJg; } else { delegateTransform = SimZip.TransformIntegerData; } rtn = UnpackFileComponent( cmFile4, cmFile5, FileContent.IntegerData, delegateTransform, empty ); // Encode byte 3 of the signal data. if ( datJg ) { delegateTransform = SimZip.TransformSignalBt3Jg; } else { delegateTransform = SimZip.TransformSignalBt3; } rtn = UnpackFileComponent( cmFile6, cmFile7, FileContent.SignalData, delegateTransform, empty ); // Encode bytes 0-2 of the signal data. if ( datJg ) { delegateTransform = SimZip.TransformSignalBt012Jg; } else { delegateTransform = SimZip.TransformSignalBt012; } rtn = UnpackFileComponent( cmFile8, "", FileContent.SignalData, delegateTransform, empty ); Utility.FileProcessor.Catenate( outFile, cmFiles, true ); foreach ( string file in cmFiles ) File.Delete( file ); long szOut; fs = File.OpenRead( outFile ); try { szOut = fs.Length; } catch ( Exception ex ) { throw new SimZipException("Caught in SimZip.Compress(string,string,bool)", ex); } finally { fs.Close(); } if ( szChkFlg && (szIn < szOut) ) { File.Delete( outFile ); rtn = Io.Result.NoAction; } return rtn; } // method Compress /* * Limitation: All files must have size < Int32.MaxValue .. May not work with Int64-sized files. * Attempts to detect file format errors and returns BadFormat. Otherwise returns OK. * Method throws no exception and ignores any callee exception. */ public Io.Result Decompress( string inFile, string outFile ) { string[] cmFiles = { DATA_SZ_HDR_FILE, cmFile0, cmFile2, cmFile4, cmFile6, cmFile8 }; string verId; byte[] flags; Io.Result rtn = ReadVersionHeader( inFile, out verId, out flags ); if ( rtn == Io.Result.BadFormat ) return rtn; VerSupport ver = ValidateVersion( verId ); bool hdrJg = false; bool datJg = false; switch ( ver ) { // Address version-specific concerns here. case VerSupport.v1_0 : hdrJg = (flags[0] & HFLG_HDRJ_T) != 0x00; // bit true => expect uneven Sweep Headers datJg = (flags[0] & HFLG_DATJ_T) != 0x00; // bit true => expect uneven Sweep Data break; case VerSupport.None : default : return Io.Result.BadFormat; } // Total header length includes semaphore byte + header length int. int preSize = verId.Length + flags.Length + 1 + sizeof( Int32 ); rtn = FileProcessor.CopyFileMinusPrefix(inFile, cmFile1, preSize, BUF_SIZE_DFLT); if ( rtn == Io.Result.BadIndex ) return Io.Result.BadFormat; FileProcessor.Decatenate( cmFile1, cmFiles ); int[] szAry; rtn = ReadDataSizeHeader( DATA_SZ_HDR_FILE, DATA_SZ_TMP_FILE, out szAry ); if ( rtn == Io.Result.BadFormat ) return rtn; int[] bufSize = { BUF_SIZE_DFLT }; int[] empty = new int[0]; // Decode the file header. rtn = PackFileComponent( cmFile0, cmFile1, ZipContent.FileHdr, empty, StreamProcessor.TransformCopyStream, bufSize ); // OK unless exception was thrown StreamProcessor.Transform delegateTransform; int[] pass; int[] mySzAry = new int[ szAry.Length ]; Array.Copy( szAry, mySzAry, szAry.Length ); int[] hwPre = new int[2]; hwPre[0] = -1; hwPre[1] = szAry[0]; // Decode the sweep headers. if ( hdrJg ) { delegateTransform = StreamProcessor.TransformCopyStream; pass = bufSize; } else { delegateTransform = StreamProcessor.TransformTranspose; pass = empty; } rtn = PackFileComponent( cmFile2, cmFile3, ZipContent.SwpHdr, hwPre, delegateTransform, pass ); Array.Copy( szAry, mySzAry, szAry.Length ); mySzAry[0] = szAry[1] * nBytesInt16PerSample; mySzAry[1] = szAry[0]; // Decode the integer data. if ( datJg ) { delegateTransform = SimZip.InvTransformIntegerDataJg; } else { delegateTransform = SimZip.InvTransformIntegerData; } rtn = PackFileComponent( cmFile4, cmFile5, ZipContent.IntegerData, mySzAry, delegateTransform, empty ); Array.Copy( szAry, mySzAry, szAry.Length ); mySzAry[0] *= nComponentsPerSample; // Decode byte 3 of the signal data. if ( datJg ) { delegateTransform = SimZip.InvTransformSignalBt3Jg; } else { delegateTransform = SimZip.InvTransformSignalBt3; } rtn = PackFileComponent( cmFile6, cmFile7, ZipContent.Signal3, mySzAry, delegateTransform, empty ); // Note: cmFile7 has been re-written as a temporary file, will be interleaved with bytes 0-2. Array.Copy( szAry, mySzAry, szAry.Length ); mySzAry[1] *= 3 * nComponentsPerSample; // 3 of the 4 bytes of each Single precision numeric value. // Decode bytes 0-2 of the signal data. if ( datJg ) { delegateTransform = SimZip.InvTransformSignalBt012Jg; pass = empty; } else { delegateTransform = StreamProcessor.TransformCopyStream; pass = bufSize; } rtn = PackFileComponent( // Note: cmFile7 will be read from disk, but is not the decoding target. cmFile8, cmFile7, ZipContent.Signal012, mySzAry, delegateTransform, pass ); foreach (string file in cmFiles) File.Delete(file); return FileWrite( outFile ); } // method Decompress /* * Accept SizeArray data. * Build the "Data Size" byte array and store in a separate, compressed header file. * Throws SimZipException. */ private void WriteDataSizeHeader( string outFile, string tmpFile, int[] szAry, int scale ) { byte[] szBytes = new byte[szAry.Length * nBytesPerInt32]; for ( int i = 0; i < szAry.Length; ++i ) { int next = szAry[i]; if ( 0 < i ) { // Normalize the width values to represent #samples, not #bytes. if ( 0 < next ) { if ( 0 < next % scale ) { throw new SimZipException( "Arithmetic error in WriteDataSizeHeader" ); } next /= scale; } } byte[] oneInt32 = BitConverter.GetBytes( next ); Array.Copy( oneInt32, 0, szBytes, i * nBytesPerInt32, nBytesPerInt32 ); } FileStream tmpStream = File.OpenWrite( tmpFile ); try { tmpStream.Write( szBytes, 0, szBytes.Length ); } catch ( Exception ex ) { string msg = "Caught in SimZip.WriteDataSizeHeader(string,string,int[],int) call Stream.Write"; throw new SimZipException( msg, ex ); } finally { tmpStream.Close(); } RunCompress( tmpFile, outFile, false ); File.Delete( tmpFile ); } // method WriteDataSizeHeader /* * Read the "Data Size" byte array from a separate, compressed header file. * Build and return SizeArray data. * Returns OK or BadFormat. Throws SimZipException. */ private Io.Result ReadDataSizeHeader( string inFile, string tmpFile, out int[] szAry ) { RunCompress( inFile, tmpFile, true ); // tmpFile now contains decompressed size data. int bufSz; int outSz; byte[] buf; FileStream tmpStream = File.OpenRead( tmpFile ); if ( 0 < tmpStream.Length % nBytesPerInt32 ) { tmpStream.Close(); szAry = new int[0]; return Io.Result.BadFormat; } Io.Result rtn = Io.Result.OK; try { bufSz = (int) tmpStream.Length; outSz = bufSz / nBytesPerInt32; buf = new byte[ bufSz ]; szAry = new int[ outSz ]; rtn = StreamProcessor.ReadByteStream( buf, 0, bufSz, tmpStream ); } catch ( Exception ex ) { string msg = "Caught in SimZip.ReadDataSizeHeader(string,string,int[],int)"; throw new SimZipException( msg, ex ); } finally { tmpStream.Close(); File.Delete( tmpFile ); } switch ( rtn ) { case Io.Result.BadIndex : string tag = Io.GetResultTag( rtn ); string msg = "SimZip.ReadDataSizeHeader(string,string,int[]): '" +tag+ "' signal from StreamProcessor.ReadByteStream"; throw new SimZipException( msg ); case Io.Result.OK : break; } for ( int i = 0; i < outSz; ++i ) { szAry[i] = BitConverter.ToInt32( buf, i * nBytesPerInt32 ); } return Io.Result.OK; } /* * flgBytes[ 0 ] : Flags byte * flgBytes[ 1 .. 4]: Int32 #rows * flgBytes[ 5 .. 8]: Int32 min row width in #samples * flgBytes[ 9 .. n]: One integer per row, indicates #samples "over" min row width */ private void WriteVersionHeader( string outFile, byte[] flgBytes ) { int idLen = VERSION_ID.Length; byte[] toFile = new byte[ idLen + 1 + flgBytes.Length ]; for ( int i = 0; i < idLen; ++i ) { toFile[i] = (byte) VERSION_ID[i]; } toFile[ idLen ] = HDR_FLG_SEMA; // Mark end of Version Id. for ( int i = 0; i < flgBytes.Length; ++i ) { // Add flag byte plus array size configuration. toFile[idLen + 1 + i] = flgBytes[ i ]; } File.Delete( outFile ); FileStream fs = File.OpenWrite( outFile ); try { fs.Write( toFile, 0, toFile.Length ); } catch ( Exception ex ) { throw new SimZipException("Caught in SimZip.WriteVersionHeader(string,byte) call Stream.Write(byte[],int,int)", ex); } finally { fs.Close(); } } // method WriteVersionHeader /* * Will recognize in a variable number of flag bytes. * Version 1.0, however, uses a single flag byte, so the size of flags should be 1 upon return. * Returns OK, or BadFormat. Throws SimZipException. */ private Io.Result ReadVersionHeader( string inFile, out string verId, out byte[] flags ) { verId = ""; flags = new byte[0]; char[] verChars = new char[0]; byte[] flgBytes = new byte[0]; Io.Result rtn = Io.Result.OK; int nSz = sizeof( Int32 ); FileStream fs = File.OpenRead( inFile ); try { byte[] szBytes = new byte[ nSz ]; fs.Read( szBytes, 0, nSz ); int toRead = BitConverter.ToInt32( szBytes, 0 ); // Protect against excessive read length from incorrectly formatted file. toRead = GetNbrBytesToReadAsVersion( toRead ); byte[] hdrBytes = new byte[ toRead ]; int verSz = 0; int flgSz = -1; rtn = StreamProcessor.ReadByteStream( hdrBytes, 0, toRead, fs ); if ( rtn != Io.Result.BadIndex ) { for ( int i = 0; i < toRead; ++i ) { if ( flgSz < 0 ) { if ( hdrBytes[i] != HDR_FLG_SEMA ) { verSz += 1; } else { flgSz += 1; } } else { flgSz += 1; } } } else { // Parameters don't work; 'BadIndex' detected; verSz == 0. flgSz += 1; } if ( verSz == 0 || flgSz < 0 ) { rtn = Io.Result.BadFormat; } if ( rtn != Io.Result.BadFormat ) { verChars = new char[ verSz ]; flgBytes = new byte[ flgSz ]; for ( int i = 0; i < verSz; ++i ) { verChars[i] = (char) hdrBytes[i]; } for ( int i = 0; i < flgSz; ++i ) { flgBytes[i] = hdrBytes[verSz + 1 + i]; } } } catch ( Exception ex ) { throw new SimZipException("Caught in SimZip.ReadVersionHeader(string,string,byte[])", ex); } finally { fs.Close(); } if ( rtn != Io.Result.BadFormat ) { verId = new string( verChars ); flags = flgBytes; // Check integrity among total header bytes, bytes read, version id, and flags length. if ( rtn == Io.Result.OK ) { rtn = Io.Result.BadFormat; for ( int i = 0; i < verSupported.Length; ++i ) { if ( verId == verSupported[i] ) { if ( flags.Length + 1 == flgSupported[i] ) { rtn = Io.Result.OK; break; } } } } } return rtn; } // method ReadVersionHeader /* * Determine whether the string contains a valid Version Id. */ private VerSupport ValidateVersion( string verId ) { for ( int i = 0; i < verSupported.Length; ++i ) { if ( verSupported[i] == verId ) return (VerSupport) i; } return VerSupport.None; } /* * Return the lesser of: * (a) the input value, or * (b) the maximum string length from the collection of supported Version Id strings. * (Purpose is to limit the number of bytes the caller will later read from a bad-format file.) */ private int GetNbrBytesToReadAsVersion( int tryMe ) { int max = 0; if ( tryMe < 0 ) tryMe = Int32.MaxValue; for ( int i = 0; i < verSupported.Length; ++i ) { string s = verSupported[i]; int flgSz = flgSupported[i]; int test = s.Length + flgSz; if ( max < test ) max = test; } return max < tryMe ? max : tryMe; } // method GetNbrBytesToReadAsVersion /* * Inspects the tmp array formed (in the expected way) from a SimFile object queried with fc. * Post: If the tmp array is rectangular, then isJag == false. Otherwise, isJag == true. * .. szAry has the following structure by position k, describing the tmp array: * .. .. 0 : #rows * .. .. 1 : min #cols over all rows * .. .. 2->(n-1) : (#cols in row# (k-2)) - szAry[1] .. note this represents "excess #cols" * .. Note that (isJag == true) <=> (szAry.Length == 2 + szAry[0]) * .. Note that (isJag == false) <=> (szAry.Length == 2) * Note that the content of szAry controls just about everything else in this package! * Returns OK. Throws SimZipException. */ private Io.Result FindJaggedContent( FileContent fc, out bool isJag, out int[] szAry ) { isJag = false; Io.Result rtn = Io.Result.OK; Stream memStream = new MemoryStream(); try { rtn = UnpackFileComponent( memStream, fc, out szAry ); // rtn == OK unless exception thrown } catch ( Exception ex ) { throw new SimZipException("Caught in SimZip.FindJaggedContent(FileContent,bool) call UnpackFileComponent(Stream,FileContent,Pair)", ex); } finally { memStream.Close(); } isJag = (2 < szAry.Length); // Detect jagged array. return rtn; } // method FindJaggedContent /* * Purpose is to adapt a standard configuration to various transform parameters. * Throws SimZipException. */ private static void ScaleSzAryWidths( int[] szAry, double scale ) { for ( int i = 1; i < szAry.Length; ++i ) { double test = (double) szAry[i] * scale; if ( Math.Floor( test ) != test ) { string msg = "Arithmetic error in SimZip.ScaleSzAryWidths(int[],double)"; throw new SimZipException( msg ); } szAry[i] = (int) test; } } // method ScaleSzAryWidths /* * Populate outFile with the transformed SimFile content specified by fc. * If parameters is an empty array, * .. then (internally built) szAry will be passed in to transform. * .. Otherwise, parameters will be passed in to transform. * If rawFile is an empty string, then outFile will not be compressed. * .. Otherwise, outFile will be compressed, and rawFile will be deleted. * Returns OK. Throws SimZipException. */ public Io.Result UnpackFileComponent ( string outFile, string rawFile, FileContent fc, StreamProcessor.Transform transform, int[] parameters ){ int[] pass; int[] szAry; Stream rawStream; Io.Result rtn = Io.Result.OK; bool cmpFlg = (0 < rawFile.Length) ? true : false; if ( cmpFlg ) { File.Delete( rawFile ); rawStream = File.OpenWrite( rawFile ); } else { rawStream = new MemoryStream(); } try { Stream memStream = new MemoryStream(); try { rtn = UnpackFileComponent( memStream, fc, out szAry ); // rtn == OK unless exception thrown pass = (parameters.Length == 0) ? szAry : parameters; memStream.Position = 0; rtn = transform( memStream, rawStream, pass ); } catch ( Exception ex ) { string msg = "Caught in SimZip.UnpackFileComponent(string,string,FileContent,StreamProcessor.Transform,int[])"; throw new SimZipException( msg, ex ); } finally { memStream.Close(); } } catch ( Exception ex ) { rawStream.Close(); string msg = "Caught in SimZip.UnpackFileComponent(string,string,FileContent,StreamProcessor.Transform,int[])"; throw new SimZipException( msg, ex ); } switch ( rtn ) { case Io.Result.Mismatch : case Io.Result.Underflow : case Io.Result.Overflow : string tag = Io.GetResultTag( rtn ); string msg = "SimZip.UnpackFileComponent(string,string,FileContent,StreamProcessor.Transform,int[]): '"+tag+"' signal from StreamProcessor.Transform"; throw new SimZipException( msg ); case Io.Result.OK : break; } if ( cmpFlg ) { rawStream.Close(); File.Delete( outFile ); RunCompress( rawFile, outFile, false ); // Compress File.Delete( rawFile ); } else { rawStream.Position = 0; FileStream outStream = File.OpenWrite( outFile ); try { StreamProcessor.CopyStream( rawStream, outStream, BUF_SIZE_DFLT ); outStream.SetLength( rawStream.Length ); } catch ( Exception ex ) { string msg = "Caught in SimZip.UnpackFileComponent(string,string,FileContent,StreamProcessor.Transform,int[]) call StreamProcessor.CopyStream(Stream,Stream,int)"; throw new SimZipException( msg, ex ); } finally { outStream.Close(); rawStream.Close(); } } return rtn; } // method UnpackFileComponent /* * Populate outStream with the native SimFile content specified by fc. * Populate szAry with standard scale. * Returns OK. Throws no exception, ignores any exception thrown by callee. */ public Io.Result UnpackFileComponent( Stream outStream, FileContent fc, out int[] szAry ) { Io.Result rtn = LoadByteBlock( fc ); // rtn == OK unless exception thrown. int wmin; int[] extra; Pair scale = GetByteBlockScale( out wmin, out extra ); szAry = new int[2 + extra.Length]; szAry[0] = scale.First; // height szAry[1] = wmin; // min width for ( int i = 0; i < extra.Length; ++i ) { szAry[2 + i] = extra[i]; } return StreamWrite( outStream, fc ); // OK unless exception thrown. } // method UnpackFileComponent /* * Decompresses and interprets content of inFile according to zc and szAry. * Transforms the content according to zc, and transParm (if nonempty) or szAry. * Returns OK. Throws SimZipException. */ public Io.Result PackFileComponent ( string inFile, string rawFile, ZipContent zc, int[] szAry, StreamProcessor.Transform transform, int[] transParm ){ FileContent fc; switch ( zc ) { case ZipContent.FileHdr : fc = FileContent.FileHdr; break; case ZipContent.SwpHdr : fc = FileContent.SwpHdr; break; case ZipContent.IntegerData : fc = FileContent.IntegerData; break; case ZipContent.Signal3 : fc = FileContent.SignalData; break; case ZipContent.Signal012 : fc = FileContent.SignalData; break; default : return Io.Result.NoAction; } FileStream inStream; FileStream s3Stream; Io.Result rtn = Io.Result.OK; MemoryStream rawStream = new MemoryStream(); try { MemoryStream memStream = new MemoryStream(); try { if ( 0 < rawFile.Length && zc != ZipContent.Signal012 ) { // Hokey patch using zc. RunCompress( inFile, rawFile, true ); // Decompress inStream = File.OpenRead( rawFile ); } else { inStream = File.OpenRead( inFile ); } try { StreamProcessor.CopyStream( inStream, memStream, BUF_SIZE_DFLT ); if ( zc == ZipContent.SwpHdr ) { szAry[0] = (int) ( memStream.Length / NbrSweeps ); } } catch ( Exception ex ) { string msg = "Caught in SimZip.PackFileComponent(string,string,ZipContent,int[],StreamProcessor.Transform,int[])"; throw new SimZipException( msg, ex ); } finally { inStream.Close(); } // szAry now enables transform based on zc. memStream.Position = 0; int[] pass; pass = (0 < transParm.Length) ? transParm : szAry; rtn = transform( memStream, rawStream, pass ); } catch ( Exception ex ) { string msg = "Caught in SimZip.PackFileComponent(string,string,ZipContent,int[],StreamProcessor.Transform,int[])"; throw new SimZipException(msg, ex); } finally { memStream.Close(); } switch ( rtn ) { case Io.Result.BadFormat : case Io.Result.Mismatch : case Io.Result.Underflow : case Io.Result.Overflow : string tag = Io.GetResultTag( rtn ); string msg = "SimZip.PackFileComponent(string,string,ZipContent,int[],StreamProcessor.Transform,int[]): '" + tag + "' signal from StreamProcessor.Transform"; throw new SimZipException( msg ); case Io.Result.OK : break; } rawStream.Position = 0; switch ( zc ) { case ZipContent.Signal3 : File.Delete( rawFile ); s3Stream = File.OpenWrite( rawFile ); try { StreamProcessor.CopyStream( rawStream, s3Stream, BUF_SIZE_DFLT ); } catch ( Exception ex ) { string msg = "Caught in SimZip.PackFileComponent(string,string,ZipContent,int[],StreamProcessor.Transform,int[]) call StreamProcessor.CopyStream(Stream,Stream,int)"; throw new SimZipException(msg, ex); } finally { s3Stream.Close(); } break; case ZipContent.Signal012 : MemoryStream s012Stream = new MemoryStream(); try { s3Stream = File.OpenRead( rawFile ); try { StreamProcessor.CopyStream( rawStream, s012Stream, BUF_SIZE_DFLT ); rawStream.SetLength(0); s012Stream.Position = 0; Stream[] mergeThese = { s012Stream, s3Stream }; int[] counts = { 3, 1 }; StreamProcessor.MergeStreams( rawStream, mergeThese, counts ); } catch ( Exception ex ) { string msg = "Caught in SimZip.PackFileComponent(string,string,ZipContent,Pair,StreamProcessor.Transform,int[])"; throw new SimZipException( msg, ex ); } finally { s3Stream.Close(); } } catch ( Exception ex ) { string msg = "Caught in SimZip.PackFileComponent(string,string,ZipContent,Pair,StreamProcessor.Transform,int[])"; throw new SimZipException(msg, ex); } finally { s012Stream.Close(); } rawStream.Position = 0; rtn = StreamRead( rawStream, fc ); break; default : // Not processing a signal component. rtn = StreamRead( rawStream, fc, 0, NbrSweeps ); break; } } catch ( Exception ex ) { string msg = "Caught in SimZip.PackFileComponent(string,string,ZipContent,Pair,StreamProcessor.Transform,int[])"; throw new SimZipException(msg, ex); } finally { rawStream.Close(); } if ( rtn != Io.Result.OK ) { string tag = Io.GetResultTag( rtn ); string msg = "SimZip.PackFileComponent(string,string,ZipContent,int[],StreamProcessor.Transform,int[]): '" + tag + "' signal from SimFile.StreamRead"; throw new SimZipException( msg ); } if ( 0 < rawFile.Length && zc != ZipContent.Signal3 ) File.Delete( rawFile ); return rtn; } // method PackFileComponent /* * decoFlg: false => compress, true = decompress */ public void RunCompress( string inFile, string outFile, bool decoFlg ) { File.Delete( outFile ); Process p = new Process(); p.StartInfo.FileName = COMPRESS_EXE; p.StartInfo.Arguments = BuildCompressArgs( inFile, outFile, decoFlg ); p.Start(); while ( ! p.HasExited ) {} } /* * Used by RunCompress. */ private string BuildCompressArgs( string file1, string file2, bool decoFlg ) { string code = decoFlg ? "d " : "e "; string rtn; /**/ rtn = code + file1 + " " + file2; /**/ /* // apply command-line switch(es) string sw = "-pb4 -lp2"; rtn = code + file1 + " " + file2 + " " + sw; */ return rtn; } /* * Pre: hw contains the height, width of the superarray. * inStream.Length == h * w * h equals NbrSweeps. * (nBytesIntegerPerSample * nComponentsPerSample) divides w. * Post: outStream is transformed from inStream, for optimal dictionary compression. * Implements the Matlab function sig = transpose([s1 s2 s3 s4 s5 s6 s7 s8]) * .. where s1 is the segregation of all "1 of 8" bytes of inStream, * .. s2 is the segregation of all "2 of 8" bytes of inStream, etc. * (This is a performance bottleneck because of several calls to PickPeriodicValues.) * Returns OK, or Mismatch. Throws SimZipException. */ public static Io.Result TransformIntegerData( Stream inStream, Stream outStream, int[] hw ) { int h = hw[0]; int w = hw[1]; int cMod = nBytesIntegerPerSample; int pRem = w % cMod; if ( pRem != 0 ) return Io.Result.Mismatch; byte[,] buf = new byte[h, w]; Io.Result rtn = StreamProcessor.StreamToArray2D( inStream, buf ); switch ( rtn ) { case Io.Result.Underflow : case Io.Result.Overflow : string tag = Io.GetResultTag( rtn ); string msg = "SimZip.TransformIntegerData(Stream,Stream,int[]): '"+tag+"' signal from StreamProcessor.StreamToArray2D"; throw new SimZipException( msg ); case Io.Result.OK : break; } int pSz = w / cMod; int[] rNdx = {0}; int rMod = 0; byte[,] mat = new byte[h, w]; int[] cNdx = new int[1]; for ( int i = 0; i < cMod; ++i ) { cNdx[0] = i; byte[,] pick = ByteArrayManipulator.PickPeriodicValues( buf, rNdx, rMod, cNdx, cMod ); ByteArrayManipulator.CopyArrayByColumn( mat, 0, i * pSz, pick ); } buf = ByteArrayManipulator.Transpose( mat ); StreamProcessor.Array2DToStream( outStream, buf ); return rtn; } // method TransformIntegerData /* * Version of TransformIntegerData, for jagged arrays. * Returns OK. Throws SimZipException. */ public static Io.Result TransformIntegerDataJg( Stream inStream, Stream outStream, int[] szAry ) { StreamProcessor.Transform delegateTransform = SimZip.TransformIntegerData; int[] pick = new int[0]; int from = 0; Io.Result rtn = TransformJaggedFileComponent(inStream, outStream, delegateTransform, szAry, pick, from); if ( rtn != Io.Result.OK ) { string tag = Io.GetResultTag( rtn ); string msg = "SimZip.TransformIntegerDataJg(Stream,Stream,int[]): '"+tag+"' signal from SimZip.TransformJaggedFileComponent"; throw new SimZipException( msg ); } return rtn; } // method TransformIntegerDataJg /* * Pre: inStream.Length == h * w * h equals NbrSweeps. * nComponentsPerSample divides w. * Post: outStream is transformed from inStream, for optimal compression. * Implements the Matlab function sig = [ar3; ai3; br3; bi3; cr3; ci3; dr3; di3; er3; ei3] * .. where ar3 is the segregation of all "4 of 4" bytes of the A Real component of inStream, * .. bi3 is the segregation of all "4 of 4" bytes of the B Imaginary component of inStream, etc. * Returns OK, or Mismatch. Throws SimZipException.* */ public static Io.Result TransformSignalBt3( Stream inStream, Stream outStream, int[] hw ) { int h = hw[0]; int w = hw[1]; int cMod = nBytesPerComponent; int pRem = w % cMod; if ( pRem != 0 ) return Io.Result.Mismatch; byte[,] buf = new byte[h, w]; Io.Result rtn = StreamProcessor.StreamToArray2D( inStream, buf ); switch ( rtn ) { case Io.Result.Underflow : case Io.Result.Overflow : string tag = Io.GetResultTag( rtn ); string msg = "SimZip.TransformSignalBt3(Stream,Stream,int[]): '"+tag+"' signal from StreamProcessor.StreamToArray2D"; throw new SimZipException( msg ); case Io.Result.OK : break; } // Isolate byte# 3 --> bt3. int[] rNdx = {0}; int rMod = 0; int[] cNdx = new int[1]; cNdx[0] = 3; byte[,] bt3 = ByteArrayManipulator.PickPeriodicValues( buf, rNdx, rMod, cNdx, cMod ); // Transform bt3. cMod = nComponentsPerSample; int b = bt3.GetLength(1); pRem = b % cMod; if ( pRem != 0 ) return Io.Result.Mismatch; int pSz = b / cMod; int a = bt3.GetLength(0); byte[,] mat = new byte[a * cMod, pSz]; for ( int i = 0; i < cMod; ++i ) { cNdx[0] = i; byte[,] pick = ByteArrayManipulator.PickPeriodicValues( bt3, rNdx, rMod, cNdx, cMod ); ByteArrayManipulator.CopyArrayByColumn( mat, i * a, 0, pick ); } StreamProcessor.Array2DToStream( outStream, mat ); return rtn; } // method TransformSignalBt3 /* * Version of TransformSignalBt3, for jagged arrays. * Returns OK. Throws SimZipException. */ public static Io.Result TransformSignalBt3Jg( Stream inStream, Stream outStream, int[] szAry ) { StreamProcessor.Transform delegateTransform = SimZip.TransformSignalBt3; int[] pick = { 3 }; int from = 4; Io.Result rtn = TransformJaggedFileComponent(inStream, outStream, delegateTransform, szAry, pick, from); if ( rtn != Io.Result.OK ) { string tag = Io.GetResultTag( rtn ); string msg = "SimZip.TransformSignalBt3Jg(Stream,Stream,int[]): '"+tag+"' signal from SimZip.TransformJaggedFileComponent"; throw new SimZipException( msg ); } return rtn; } // method TransformSignalBt3Jg /* * All this does is to isolate the first 3 bytes of each Int32 in the signal component. * No transformation is done on the isolated bytes. * Returns OK, or Mismatch. Throws SimZipException. */ public static Io.Result TransformSignalBt012( Stream inStream, Stream outStream, int[] hw ) { int h = hw[0]; int w = hw[1]; int cMod = nBytesPerComponent; int pRem = w % cMod; if ( pRem != 0 ) return Io.Result.Mismatch; byte[,] buf = new byte[h, w]; Io.Result rtn = StreamProcessor.StreamToArray2D( inStream, buf ); switch ( rtn ) { case Io.Result.Underflow : case Io.Result.Overflow : string tag = Io.GetResultTag( rtn ); string msg = "SimZip.TransformSignalBt012(Stream,Stream,int[]): '"+tag+"' signal from StreamProcessor.StreamToArray2D"; throw new SimZipException( msg ); case Io.Result.OK : break; } // Isolate byte#s 0,1,2 --> bt012. int[] rNdx = {0}; int rMod = 0; int[] cNdx = {0, 1, 2}; byte[,] bt012 = ByteArrayManipulator.PickPeriodicValues( buf, rNdx, rMod, cNdx, cMod ); StreamProcessor.Array2DToStream( outStream, bt012 ); return rtn; } // method TransformSignalBt012 /* * Version of TransformSignalBt012, for jagged arrays. * Returns OK. Throws SimZipException. */ public static Io.Result TransformSignalBt012Jg( Stream inStream, Stream outStream, int[] szAry ) { StreamProcessor.Transform delegateTransform = SimZip.TransformSignalBt012; int[] pick = { 0, 1, 2 }; int from = 4; Io.Result rtn = TransformJaggedFileComponent(inStream, outStream, delegateTransform, szAry, pick, from); if ( rtn != Io.Result.OK ) { string tag = Io.GetResultTag( rtn ); string msg = "SimZip.TransformSignalBt012Jg(Stream,Stream,int[]): '"+tag+"' signal from SimZip.TransformJaggedFileComponent"; throw new SimZipException( msg ); } return rtn; } // method TransformSignalBt012Jg /* * Adapt a jagged file component to a rectangular transform in the following manner: * .. Form a new rectangular array using the minimum row width from szAry[1]. * .. Collect the excess bytes in a temporary stream. * .. Transform the rectangular array in the standard manner, and stream the transformed bytes. * .. Append the excess bytes to the stream. * pick and from are set by the caller, and may assist with further separation * .. of components from a composite input stream; e.g., SignalData -> SignalBt012 + SignalBt3 * Returns Mismatch, Underflow, NoAction, or OK. Throws SimZipException. */ public static Io.Result TransformJaggedFileComponent ( Stream inStream, Stream outStream, StreamProcessor.Transform transformRectangular, int[] szAry, int[] pick, int from ){ if ( szAry.Length < 3 ) return Io.Result.NoAction; int height = szAry[0]; int wmin = szAry[1]; int lim = szAry.Length - 2; int[] extra = new int[ lim ]; int i; for ( i = 0; i < lim; ++i ) { extra[i] = szAry[2 + i]; } i = 0; int j = 0; inStream.Position = 0; Io.Result rtn = Io.Result.OK; byte[,] reduced = new byte[height, wmin]; MemoryStream spilled = new MemoryStream(); try { // Separate the rectangular portion from the spillover portion of the data. while ( inStream.Position < inStream.Length ) { int next; if ( j == wmin ) { lim = extra[i]; if ( 0 < lim ) { byte[,] spill = new byte[1, lim]; int[] zero = { 0 }; for ( int k = 0; k < lim; ++k ) { next = inStream.ReadByte(); if ( next == -1 ) { spilled.Close(); return Io.Result.Underflow; } spill[0, k] = (byte) next; } byte[,] mySpill; if ( from != 0 ) { mySpill = ByteArrayManipulator.PickPeriodicValues( spill, zero, 0, pick, from ); } else { mySpill = spill; } for ( int k = 0; k < mySpill.GetLength( 1 ); ++k ) { spilled.WriteByte( mySpill[0, k] ); } } i += 1; j = 0; } else { next = inStream.ReadByte(); if ( next == -1 ) { spilled.Close(); return Io.Result.Underflow; } reduced[i, j] = (byte) next; j += 1; } } if ( !(i == height && j == 0) && !(i + 1 == height && j == wmin)) { spilled.Close(); return Io.Result.Mismatch; } spilled.Position = 0; // The key (szAry) and the spillover portion are ready for outStream. MemoryStream rectOut = new MemoryStream(); MemoryStream rectIn = new MemoryStream(); try { try { for ( i = 0; i < height; ++i ) { for ( j = 0; j < wmin; ++j ) { rectIn.WriteByte( reduced[i, j] ); } } rectIn.Position = 0; int[] hw = { height, wmin }; rtn = transformRectangular( rectIn, rectOut, hw ); } catch ( Exception ex ) { string msg = "Caught in SimZip.TransformJaggedFileComponent(Stream,Stream,StreamProcessor.Transform(Stream,Stream,int[]),int[])"; throw new SimZipException( msg, ex ); } finally { rectIn.Close(); } if ( rtn == Io.Result.OK ) { rectOut.Position = 0; // The transformed rectangular portion (rectOut) is ready for outStream. outStream.Position = 0; byte[] oneInt32 = new byte[ nBytesPerInt32 ]; // Write everything to outStream. while ( rectOut.Position < rectOut.Length ) { byte next = (byte) rectOut.ReadByte(); outStream.WriteByte( next ); } } } catch ( Exception ex ) { string msg = "Caught in SimZip.TransformJaggedFileComponent(Stream,Stream,StreamProcessor.Transform(Stream,Stream,int[]),int[])"; throw new SimZipException( msg, ex ); } finally { rectOut.Close(); } if ( rtn == Io.Result.OK ) { while ( spilled.Position < spilled.Length ) { byte next = (byte) spilled.ReadByte(); outStream.WriteByte( next ); } } } catch ( Exception ex ) { string msg = "Caught in SimZip.TransformJaggedFileComponent(Stream,Stream,StreamProcessor.Transform(Stream,Stream,int[]),int[])"; throw new SimZipException( msg, ex ); } finally { spilled.Close(); } if ( rtn != Io.Result.OK ) { string tag = Io.GetResultTag( rtn ); string msg = "SimZip.TransformJaggedFileComponent(Stream,Stream,StreamProcessor.Transform,int[],int[],int): '" + tag + "' signal from StreamProcessor.Transform"; throw new SimZipException( msg ); } return rtn; } // method TransformJaggedFileComponent /* * Pre: inStream.Length matches h * w. * (nBytesIntegerPerSample * nComponentsPerSample) divides h. * w equals NbrSweeps * Post: outStream is suitable for ReadStreamData( FileComponent.IntegerData ) * This is the inverse transform of TransformIntegerData. * Returns Mismatch, or OK. Throws SimZipException. */ public static Io.Result InvTransformIntegerData( Stream inStream, Stream outStream, int[] hw ) { int h = hw[0]; int w = hw[1]; byte[,] mat = new byte[h, w]; Io.Result rtn = StreamProcessor.StreamToArray2D( inStream, mat ); switch ( rtn ) { case Io.Result.Underflow : case Io.Result.Overflow : string tag = Io.GetResultTag( rtn ); string msg = "SimZip.InvTransformIntegerData(Stream,Stream,int[]): '"+tag+"' signal from StreamProcessor.StreamToArray2D"; throw new SimZipException( msg ); case Io.Result.OK : break; } byte[,] tam = ByteArrayManipulator.Transpose( mat ); int cMod = h; int pRem = h % nBytesIntegerPerSample; if ( pRem != 0 ) return Io.Result.Mismatch; int pSz = h / nBytesIntegerPerSample; int[] rNdx = {0}; int rMod = 0; int[] cNdx = new int[pSz]; Stream[] sAry = new Stream[ nBytesIntegerPerSample ]; int[] counts = new int[ nBytesIntegerPerSample ]; try { for ( int i = 0; i < nBytesIntegerPerSample; ++i ) { for ( int j = 0; j < pSz; ++j ) cNdx[j] = i * pSz + j; counts[i] = 1; MemoryStream memStream = new MemoryStream(); byte[,] pick = ByteArrayManipulator.PickPeriodicValues( tam, rNdx, rMod, cNdx, cMod ); StreamProcessor.Array2DToStream( memStream, pick ); memStream.Position = 0; sAry[i] = memStream; } StreamProcessor.MergeStreams( outStream, sAry, counts ); } catch ( Exception ex ) { string msg = "Caught in SimZip.InvTransformIntegerData(Stream,Stream,int[])"; throw new SimZipException( msg, ex ); } finally { foreach ( Stream s in sAry ) s.Close(); } return rtn; } // method InvTransformIntegerData /* * Version of InvTransformIntegerData, for jagged arrays. * Returns OK, or BadFormat. Throws SimZipException. */ public static Io.Result InvTransformIntegerDataJg( Stream inStream, Stream outStream, int[] szAry ) { if ( szAry[0] % nBytesInt16PerSample != 0 ) return Io.Result.BadFormat; int[] hw = new int[2]; hw[0] = szAry[0]; hw[1] = szAry[1]; szAry[0] = szAry[1]; szAry[1] = hw[0] / nBytesInt16PerSample; ScaleSzAryWidths( szAry, (double) nBytesInt16PerSample ); Io.Result rtn = InvTransformJaggedFileComponent(inStream, outStream, InvTransformIntegerData, szAry, hw); if ( rtn != Io.Result.OK ) { string tag = Io.GetResultTag( rtn ); string msg = "SimZip.InvTransformIntegerDataJg(Stream,Stream,int[]): '"+tag+"' signal from SimZip.InvTransformJaggedFileComponent"; throw new SimZipException( msg ); } return rtn; } // method InvTransformIntegerDataJg /* * Pre: inStream.Length matches h * w. * (NbrSweeps * nComponentsPerSample) divides h. * Post: outStream is suitable for further multiplexing with SignalBt012. * This is "not exactly" the inverse transform of TransformSignalBt3. * (The forward transform takes a composite stream as input. * The inverse transform supplies a pure stream as output.) * Returns Mismatch, or OK. Throws SimZipException. */ public static Io.Result InvTransformSignalBt3( Stream inStream, Stream outStream, int[] hw ) { int h = hw[0]; int w = hw[1]; byte[,] mat = new byte[h, w]; Io.Result rtn = StreamProcessor.StreamToArray2D( inStream, mat ); switch ( rtn ) { case Io.Result.Underflow : case Io.Result.Overflow : string tag = Io.GetResultTag( rtn ); string msg = "SimZip.InvTransformSignalBt3(Stream,Stream,int[]): '"+tag+"' signal from StreamProcessor.StreamToArray2D"; throw new SimZipException( msg ); case Io.Result.OK : break; } int rMod = h; int pRem = h % nComponentsPerSample; if ( pRem != 0 ) return Io.Result.Mismatch; int pSz = h / nComponentsPerSample; int[] cNdx = {0}; int cMod = 0; int[] rNdx = new int[ pSz ]; Stream[] sAry = new Stream[ nComponentsPerSample ]; int[] counts = new int[ nComponentsPerSample ]; try { for ( int i = 0; i < nComponentsPerSample; ++i ) { for ( int j = 0; j < pSz; ++j ) rNdx[j] = i * pSz + j; counts[i] = 1; byte[,] pick = ByteArrayManipulator.PickPeriodicValues( mat, rNdx, rMod, cNdx, cMod ); MemoryStream memStream = new MemoryStream(); StreamProcessor.Array2DToStream( memStream, pick ); memStream.Position = 0; sAry[i] = memStream; } StreamProcessor.MergeStreams( outStream, sAry, counts ); } catch ( Exception ex ) { string msg = "Caught in SimZip.InvTransformSignalBt3(Stream,Stream,int[])"; throw new SimZipException( msg, ex ); } finally { foreach ( Stream s in sAry ) s.Close(); } return rtn; } // method InvTransformSignalBt3 /* * Version of InvTransformSignalBt3, for jagged arrays. * Returns OK, or BadFormat. Throws SimZipException. */ public static Io.Result InvTransformSignalBt3Jg( Stream inStream, Stream outStream, int[] szAry ) { if ( szAry[0] % nComponentsPerSample != 0 ) return Io.Result.BadFormat; int[] hw = new int[2]; hw[0] = szAry[0]; hw[1] = szAry[1]; szAry[0] /= nComponentsPerSample; ScaleSzAryWidths( szAry, (double) nComponentsPerSample ); Io.Result rtn = InvTransformJaggedFileComponent(inStream, outStream, InvTransformSignalBt3, szAry, hw); if ( rtn != Io.Result.OK ) { string tag = Io.GetResultTag( rtn ); string msg = "SimZip.InvTransformSignalBt3Jg(Stream,Stream,int[]): '"+tag+"' signal from SimZip.InvTransformJaggedFileComponent"; throw new SimZipException( msg ); } return rtn; } // method InvTransformSignalBt3Jg /* * "Not quite" the inverse of TransformSignalBt012, for jagged arrays. * Returns OK, or BadFormat. Throws SimZipException. */ public static Io.Result InvTransformSignalBt012Jg( Stream inStream, Stream outStream, int[] szAry ) { if ( szAry[1] % (3 * nComponentsPerSample) != 0 ) return Io.Result.BadFormat; szAry[1] /= (3 * nComponentsPerSample); int[] empty = new int[0]; ScaleSzAryWidths( szAry, (double) 3 * nComponentsPerSample ); StreamProcessor.Transform delegateTransform = StreamProcessor.TransformCopyStream; Io.Result rtn = InvTransformJaggedFileComponent(inStream, outStream, delegateTransform, szAry, empty); if ( rtn != Io.Result.OK ) { string tag = Io.GetResultTag( rtn ); string msg = "SimZip.InvTransformSignalBt012Jg(Stream,Stream,int[]): '"+tag+"' signal from SimZip.InvTransformJaggedFileComponent"; throw new SimZipException( msg ); } return rtn; } // method InvTransformSignalBt012Jg /* * Adapt a rectangular transform to a jagged-array file component in the following manner: * .. Use szAry, hwPre to separate the rectangular component from the excess bytes. * .. Transform the rectangular array in the standard manner.. * .. Multiplex the rectangular rows with any corresponding excess bytes. * Returns Underflow, Overflow, or OK. Throws SimZipException. */ public static Io.Result InvTransformJaggedFileComponent ( Stream inStream, Stream outStream, StreamProcessor.Transform invTransformRectangular, int[] szAry, int[] hwPre ){ string msg; int h; int w; int[] pass; if ( 1 < hwPre.Length ) { h = hwPre[0]; w = hwPre[1]; pass = new int[2]; pass[0] = h; pass[1] = w; } else { h = szAry[0]; w = szAry[1]; pass = new int[0]; } // Separate the rectangular skew array from the spillover. inStream.Position = 0; byte[] buf = new byte[h * w]; Io.Result rtn = StreamProcessor.ReadByteStream( buf, 0, buf.Length, inStream ); switch ( rtn ) { case Io.Result.Underflow : case Io.Result.Overflow : string tag = Io.GetResultTag( rtn ); msg = "SimZip.InvTransformJaggedFileComponent(Stream,Stream,StreamProcessor.Transform,int[],int[]): '"+tag+"' signal from StreamProcessor.StreamToArray2D"; throw new SimZipException( msg ); case Io.Result.OK : break; } // inStream.Position now points to the first byte of spillover. MemoryStream rectStream = new MemoryStream(); try { MemoryStream skewStream = new MemoryStream(); skewStream.Write( buf, 0, h * w ); skewStream.Position = 0; try { rtn = invTransformRectangular( skewStream, rectStream, pass ); } catch ( Exception ex ) { msg = "Caught in SimZip.InvTransformJaggedFileComponent(Stream,Stream,StreamProcessor.Transform,int[],int[])"; throw new SimZipException( msg, ex ); } finally { skewStream.Close(); } switch ( rtn ) { case Io.Result.Mismatch : rectStream.Close(); string tag = Io.GetResultTag( rtn ); msg = "SimZip.InvTransformJaggedFileComponent(Stream,Stream,StreamProcessor.Transform,int[],int[]): '" + tag + "' signal from StreamProcessor.Transform"; throw new SimZipException( msg ); case Io.Result.OK : break; } // rectStream now holds the rectangular portion of the decompressed file component. h = szAry[0]; w = szAry[1]; rectStream.Position = 0; outStream.Position = 0; // Write the output. for ( int i = 0; i < h; ++i ) { for ( int j = 0; j < w; ++j ) { int next = rectStream.ReadByte(); if ( next < 0 ) { rectStream.Close(); return Io.Result.Underflow; } outStream.WriteByte( (byte) next ); } // Append any spillover bytes to the end of each row. if ( 2 + i < szAry.Length ) { int lim = szAry[2 + i]; for ( int j = 0; j < lim; ++j ) { int next = inStream.ReadByte(); if ( next < 0 ) { rectStream.Close(); return Io.Result.Underflow; } outStream.WriteByte( (byte) next ); } } } if ((rectStream.Position < rectStream.Length) || (inStream.Position < inStream.Length)) { rtn = Io.Result.Overflow; } } catch ( Exception ex ) { msg = "Caught in SimZip.InvTransformJaggedFileComponent(Stream,Stream,StreamProcessor.Transform,int[],int[])"; throw new SimZipException( msg, ex ); } finally { rectStream.Close(); } return rtn; } // method InvTransformJaggedFileComponent // #endregion #region Data of class SimZip // Versioning info - The two arrays are correspondingly indexed. private string[] verSupported = { "SimFile1.0" }; // valid Version Id's private int[] flgSupported = { 2 }; // byte-length of flag segment (includes semaphore) // #endregion // } // class SimZip } // namespace SimFile