diff --git a/ImageDecode/Format40.cs b/ImageDecode/Format40.cs
index 3e6d6736f9..71f022a210 100644
--- a/ImageDecode/Format40.cs
+++ b/ImageDecode/Format40.cs
@@ -22,18 +22,6 @@ namespace ImageDecode
return inp + ( ReadByte( input ) << 8 );
}
- //static void ReplicatePrevious( byte[] dest, int destIndex, int srcIndex, int count )
- //{
- // for( int i = 0 ; i < Math.Min( count, destIndex - srcIndex ) ; i++ )
- // dest[ destIndex + i ] = dest[ srcIndex + i ];
-
- // if( srcIndex + count <= destIndex )
- // return;
-
- // for( int i = destIndex + destIndex - srcIndex ; i < destIndex + count ; i++ )
- // dest[ i ] = dest[ destIndex - 1 ];
- //}
-
public static int DecodeInto( MemoryStream input, byte[] dest )
{
int destIndex = 0;
diff --git a/ImageDecode/ImageDecode.csproj b/ImageDecode/ImageDecode.csproj
index f297956fa4..4d0cf29896 100644
--- a/ImageDecode/ImageDecode.csproj
+++ b/ImageDecode/ImageDecode.csproj
@@ -5,7 +5,7 @@
8.0.50727
2.0
{39352FD2-28B0-4DF5-97C7-499CE1AECCB9}
- Exe
+ Library
Properties
ImageDecode
ImageDecode
@@ -40,7 +40,6 @@
-
diff --git a/ImageDecode/Program.cs b/ImageDecode/Program.cs
deleted file mode 100644
index 50ad4ba1d2..0000000000
--- a/ImageDecode/Program.cs
+++ /dev/null
@@ -1,17 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Text;
-using System.IO;
-using System.Drawing;
-
-namespace ImageDecode
-{
- public static class Program
- {
- [STAThread]
- public static void Main()
- {
- ShpReader.Read( File.OpenRead( "stek.shp" ) );
- }
- }
-}
diff --git a/ImageDecode/ShpReader.cs b/ImageDecode/ShpReader.cs
index dbe651d95b..46db699288 100644
--- a/ImageDecode/ShpReader.cs
+++ b/ImageDecode/ShpReader.cs
@@ -10,8 +10,11 @@ namespace ImageDecode
{
public uint Offset;
public Format Format;
+
public uint RefOffset;
public Format RefFormat;
+ public ImageHeader RefImage;
+
public byte[] Image;
public ImageHeader( BinaryReader reader )
@@ -32,53 +35,125 @@ namespace ImageDecode
Format80 = 0x80,
}
- public static class ShpReader
+ public class ShpReader : IEnumerable
{
- public static IEnumerable Read( Stream stream )
+ public readonly int ImageCount;
+ public readonly ushort Width;
+ public readonly ushort Height;
+
+ private readonly List headers = new List();
+
+ int recurseDepth = 0;
+
+ public ShpReader( Stream stream )
{
BinaryReader reader = new BinaryReader( stream );
- ushort numImages = reader.ReadUInt16();
+ ImageCount = reader.ReadUInt16();
reader.ReadUInt16();
reader.ReadUInt16();
- ushort width = reader.ReadUInt16();
- ushort height = reader.ReadUInt16();
+ Width = reader.ReadUInt16();
+ Height = reader.ReadUInt16();
reader.ReadUInt32();
- List headers = new List();
- for( int i = 0 ; i < numImages ; i++ )
+ for( int i = 0 ; i < ImageCount ; i++ )
headers.Add( new ImageHeader( reader ) );
new ImageHeader( reader ); // end-of-file header
new ImageHeader( reader ); // all-zeroes header
+ Dictionary offsets = new Dictionary();
foreach( ImageHeader h in headers )
- {
- reader.BaseStream.Position = h.Offset;
- switch( h.Format )
- {
- case Format.Format20:
- //throw new NotImplementedException();
- break;
- case Format.Format40:
- //throw new NotImplementedException();
- break;
- case Format.Format80:
- {
- byte[] compressedBytes = reader.ReadBytes( (int)( reader.BaseStream.Length - reader.BaseStream.Position ) );
- MemoryStream ms = new MemoryStream( compressedBytes );
- byte[] imageBytes = new byte[ width * height ];
- Format80.DecodeInto( ms, imageBytes );
- h.Image = imageBytes;
- break;
- }
- default:
- throw new InvalidDataException();
- }
+ offsets.Add( h.Offset, h );
- if( h.Image != null )
- yield return h.Image;
+ for( int i = 0 ; i < ImageCount ; i++ )
+ {
+ ImageHeader h = headers[ i ];
+ if( h.Format == Format.Format20 )
+ h.RefImage = headers[ i - 1 ];
+
+ else if( h.Format == Format.Format40 )
+ {
+ if( !offsets.TryGetValue( h.RefOffset, out h.RefImage ) )
+ throw new InvalidDataException( string.Format( "Reference doesnt point to image data {0}->{1}", h.Offset, h.RefOffset ) );
+ }
}
+
+ foreach( ImageHeader h in headers )
+ Decompress( stream, h );
+ }
+
+ public ImageHeader this[ int index ]
+ {
+ get { return headers[ index ]; }
+ }
+
+ void Decompress( Stream stream, ImageHeader h )
+ {
+ if( recurseDepth > ImageCount )
+ throw new InvalidDataException( "Format20/40 headers contain infinite loop" );
+
+ switch( h.Format )
+ {
+ case Format.Format20:
+ case Format.Format40:
+ {
+ if( h.RefImage.Image == null )
+ {
+ ++recurseDepth;
+ Decompress( stream, h.RefImage );
+ --recurseDepth;
+ }
+
+ h.Image = CopyImageData( h.RefImage.Image );
+
+ MemoryStream ms = ReadCompressedData( stream, h );
+ Format40.DecodeInto( ms, h.Image );
+ break;
+ }
+ case Format.Format80:
+ {
+ MemoryStream ms = ReadCompressedData( stream, h );
+ byte[] imageBytes = new byte[ Width * Height ];
+ Format80.DecodeInto( ms, imageBytes );
+ h.Image = imageBytes;
+ break;
+ }
+ default:
+ throw new InvalidDataException();
+ }
+ }
+
+ private static MemoryStream ReadCompressedData( Stream stream, ImageHeader h )
+ {
+ stream.Position = h.Offset;
+ // Actually, far too big. There's no length field with the correct length though :(
+ int compressedLength = (int)( stream.Length - stream.Position );
+
+ byte[] compressedBytes = new byte[ compressedLength ];
+ stream.Read( compressedBytes, 0, compressedLength );
+
+ MemoryStream ms = new MemoryStream( compressedBytes );
+ return ms;
+ }
+
+ private byte[] CopyImageData( byte[] baseImage )
+ {
+ byte[] imageData = new byte[ Width * Height ];
+ for( int i = 0 ; i < Width * Height ; i++ )
+ imageData[ i ] = baseImage[ i ];
+
+ return imageData;
+ }
+
+ public IEnumerator GetEnumerator()
+ {
+ return headers.GetEnumerator();
+ }
+
+ System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
+ {
+ return GetEnumerator();
}
}
}
diff --git a/OpenRa.sln b/OpenRa.sln
index e2659cf82e..bbe10aaa7a 100644
--- a/OpenRa.sln
+++ b/OpenRa.sln
@@ -1,12 +1,14 @@
Microsoft Visual Studio Solution File, Format Version 9.00
-# Visual Studio 2005
+# Visual C# Express 2005
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MixBrowser", "MixBrowser\MixBrowser.csproj", "{E183D00B-FD2C-4001-8336-DF345DE281DA}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MixDecrypt", "MixDecrypt\MixDecrypt.vcproj", "{6F5D4280-3D23-41FF-AE2A-511B5553E377}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ImageDecode", "ImageDecode\ImageDecode.csproj", "{39352FD2-28B0-4DF5-97C7-499CE1AECCB9}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ShpViewer", "ShpViewer\ShpViewer.csproj", "{4303FE72-B07F-4EBB-8CD2-5F33E44801B3}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -47,6 +49,16 @@ Global
{39352FD2-28B0-4DF5-97C7-499CE1AECCB9}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{39352FD2-28B0-4DF5-97C7-499CE1AECCB9}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{39352FD2-28B0-4DF5-97C7-499CE1AECCB9}.Release|Win32.ActiveCfg = Release|Any CPU
+ {4303FE72-B07F-4EBB-8CD2-5F33E44801B3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {4303FE72-B07F-4EBB-8CD2-5F33E44801B3}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {4303FE72-B07F-4EBB-8CD2-5F33E44801B3}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {4303FE72-B07F-4EBB-8CD2-5F33E44801B3}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {4303FE72-B07F-4EBB-8CD2-5F33E44801B3}.Debug|Win32.ActiveCfg = Debug|Any CPU
+ {4303FE72-B07F-4EBB-8CD2-5F33E44801B3}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {4303FE72-B07F-4EBB-8CD2-5F33E44801B3}.Release|Any CPU.Build.0 = Release|Any CPU
+ {4303FE72-B07F-4EBB-8CD2-5F33E44801B3}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {4303FE72-B07F-4EBB-8CD2-5F33E44801B3}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {4303FE72-B07F-4EBB-8CD2-5F33E44801B3}.Release|Win32.ActiveCfg = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/ShpViewer/Program.cs b/ShpViewer/Program.cs
new file mode 100644
index 0000000000..f18dc2c1f9
--- /dev/null
+++ b/ShpViewer/Program.cs
@@ -0,0 +1,32 @@
+using System;
+using System.Collections.Generic;
+using System.Windows.Forms;
+using System.IO;
+
+namespace ShpViewer
+{
+ static class Program
+ {
+ ///
+ /// The main entry point for the application.
+ ///
+ [STAThread]
+ static void Main()
+ {
+ Application.EnableVisualStyles();
+ Application.SetCompatibleTextRenderingDefault( false );
+
+ try
+ {
+ OpenFileDialog ofd = new OpenFileDialog();
+ ofd.Filter = "SHP Files|*.shp";
+ if( ofd.ShowDialog() == DialogResult.OK )
+ Application.Run( new ShpViewForm( ofd.FileName ) );
+ }
+ catch( Exception e )
+ {
+ MessageBox.Show( e.ToString() );
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/ShpViewer/Properties/AssemblyInfo.cs b/ShpViewer/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000000..b69d4a9b40
--- /dev/null
+++ b/ShpViewer/Properties/AssemblyInfo.cs
@@ -0,0 +1,33 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle( "ShpViewer" )]
+[assembly: AssemblyDescription( "" )]
+[assembly: AssemblyConfiguration( "" )]
+[assembly: AssemblyCompany( "" )]
+[assembly: AssemblyProduct( "ShpViewer" )]
+[assembly: AssemblyCopyright( "Copyright © 2007" )]
+[assembly: AssemblyTrademark( "" )]
+[assembly: AssemblyCulture( "" )]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible( false )]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid( "69816600-0431-4ad8-b648-47f5ac2d545c" )]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+[assembly: AssemblyVersion( "1.0.0.0" )]
+[assembly: AssemblyFileVersion( "1.0.0.0" )]
diff --git a/ShpViewer/Properties/Resources.Designer.cs b/ShpViewer/Properties/Resources.Designer.cs
new file mode 100644
index 0000000000..40bbc98e45
--- /dev/null
+++ b/ShpViewer/Properties/Resources.Designer.cs
@@ -0,0 +1,71 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+// Runtime Version:2.0.50727.1318
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+namespace ShpViewer.Properties
+{
+
+
+ ///
+ /// A strongly-typed resource class, for looking up localized strings, etc.
+ ///
+ // This class was auto-generated by the StronglyTypedResourceBuilder
+ // class via a tool like ResGen or Visual Studio.
+ // To add or remove a member, edit your .ResX file then rerun ResGen
+ // with the /str option, or rebuild your VS project.
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute( "System.Resources.Tools.StronglyTypedResourceBuilder", "2.0.0.0" )]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ internal class Resources
+ {
+
+ private static global::System.Resources.ResourceManager resourceMan;
+
+ private static global::System.Globalization.CultureInfo resourceCulture;
+
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute( "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode" )]
+ internal Resources()
+ {
+ }
+
+ ///
+ /// Returns the cached ResourceManager instance used by this class.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute( global::System.ComponentModel.EditorBrowsableState.Advanced )]
+ internal static global::System.Resources.ResourceManager ResourceManager
+ {
+ get
+ {
+ if( ( resourceMan == null ) )
+ {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager( "ShpViewer.Properties.Resources", typeof( Resources ).Assembly );
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ ///
+ /// Overrides the current thread's CurrentUICulture property for all
+ /// resource lookups using this strongly typed resource class.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute( global::System.ComponentModel.EditorBrowsableState.Advanced )]
+ internal static global::System.Globalization.CultureInfo Culture
+ {
+ get
+ {
+ return resourceCulture;
+ }
+ set
+ {
+ resourceCulture = value;
+ }
+ }
+ }
+}
diff --git a/ShpViewer/Properties/Resources.resx b/ShpViewer/Properties/Resources.resx
new file mode 100644
index 0000000000..ffecec851a
--- /dev/null
+++ b/ShpViewer/Properties/Resources.resx
@@ -0,0 +1,117 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/ShpViewer/Properties/Settings.Designer.cs b/ShpViewer/Properties/Settings.Designer.cs
new file mode 100644
index 0000000000..08f469110c
--- /dev/null
+++ b/ShpViewer/Properties/Settings.Designer.cs
@@ -0,0 +1,30 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+// Runtime Version:2.0.50727.1318
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+namespace ShpViewer.Properties
+{
+
+
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute( "Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "8.0.0.0" )]
+ internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
+ {
+
+ private static Settings defaultInstance = ( (Settings)( global::System.Configuration.ApplicationSettingsBase.Synchronized( new Settings() ) ) );
+
+ public static Settings Default
+ {
+ get
+ {
+ return defaultInstance;
+ }
+ }
+ }
+}
diff --git a/ShpViewer/Properties/Settings.settings b/ShpViewer/Properties/Settings.settings
new file mode 100644
index 0000000000..abf36c5d3d
--- /dev/null
+++ b/ShpViewer/Properties/Settings.settings
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/ShpViewer/ShpViewForm.Designer.cs b/ShpViewer/ShpViewForm.Designer.cs
new file mode 100644
index 0000000000..b7c79d6e04
--- /dev/null
+++ b/ShpViewer/ShpViewForm.Designer.cs
@@ -0,0 +1,39 @@
+namespace ShpViewer
+{
+ partial class ShpViewForm
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose( bool disposing )
+ {
+ if( disposing && ( components != null ) )
+ {
+ components.Dispose();
+ }
+ base.Dispose( disposing );
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ this.components = new System.ComponentModel.Container();
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.Text = "Form1";
+ }
+
+ #endregion
+ }
+}
+
diff --git a/ShpViewer/ShpViewForm.cs b/ShpViewer/ShpViewForm.cs
new file mode 100644
index 0000000000..8c52754d70
--- /dev/null
+++ b/ShpViewer/ShpViewForm.cs
@@ -0,0 +1,48 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Text;
+using System.Windows.Forms;
+using ImageDecode;
+using System.IO;
+
+namespace ShpViewer
+{
+ public partial class ShpViewForm : Form
+ {
+ ShpReader shpReader;
+ List bitmaps = new List();
+
+ public ShpViewForm( string filename )
+ {
+ shpReader = new ShpReader( File.OpenRead( filename ) );
+
+ foreach( ImageHeader h in shpReader )
+ {
+ byte[] imageBytes = h.Image;
+
+ Bitmap bitmap = new System.Drawing.Bitmap( shpReader.Width, shpReader.Height );
+ for( int x = 0 ; x < shpReader.Width ; x++ )
+ for( int y = 0 ; y < shpReader.Height ; y++ )
+ bitmap.SetPixel( x, y, Color.FromArgb( imageBytes[ x + shpReader.Width * y ], 0, 0 ) );
+ bitmaps.Add( bitmap );
+ }
+
+ InitializeComponent();
+ }
+
+ protected override void OnPaint( PaintEventArgs e )
+ {
+ base.OnPaint( e );
+
+ int y = 10;
+ foreach( Bitmap b in bitmaps )
+ {
+ e.Graphics.DrawImage( b, 10, y );
+ y += 10 + b.Height;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/ShpViewer/ShpViewer.csproj b/ShpViewer/ShpViewer.csproj
new file mode 100644
index 0000000000..7287f38e41
--- /dev/null
+++ b/ShpViewer/ShpViewer.csproj
@@ -0,0 +1,82 @@
+
+
+ Debug
+ AnyCPU
+ 8.0.50727
+ 2.0
+ {4303FE72-B07F-4EBB-8CD2-5F33E44801B3}
+ WinExe
+ Properties
+ ShpViewer
+ ShpViewer
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+ false
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+ false
+
+
+
+
+
+
+
+
+
+
+
+ Form
+
+
+ ShpViewForm.cs
+
+
+
+
+ ResXFileCodeGenerator
+ Resources.Designer.cs
+ Designer
+
+
+ True
+ Resources.resx
+
+
+ SettingsSingleFileGenerator
+ Settings.Designer.cs
+
+
+ True
+ Settings.settings
+ True
+
+
+
+
+ {39352FD2-28B0-4DF5-97C7-499CE1AECCB9}
+ ImageDecode
+
+
+
+
+
\ No newline at end of file