diff --git a/GUI/GarConvert.cs b/GUI/GarConvert.cs index 56ecebb6..739bf79d 100644 --- a/GUI/GarConvert.cs +++ b/GUI/GarConvert.cs @@ -187,7 +187,7 @@ namespace GARbro.GUI void ConvertAudio (string filename) { - using (var file = File.OpenRead (filename)) + using (var file = BinaryStream.FromFile (filename)) using (var input = AudioFormat.Read (file)) { if (null == input) @@ -223,9 +223,9 @@ namespace GARbro.GUI string target_name = Path.GetFileName (filename); string target_ext = m_image_format.Extensions.FirstOrDefault(); target_name = Path.ChangeExtension (target_name, target_ext); - using (var file = File.OpenRead (filename)) + using (var file = BinaryStream.FromFile (filename)) { - var src_format = ImageFormat.FindFormat (file, filename); + var src_format = ImageFormat.FindFormat (file); if (null == src_format) return; if (src_format.Item1 == m_image_format && m_image_format.Extensions.Any (ext => ext == source_ext)) diff --git a/GUI/GarExtract.cs b/GUI/GarExtract.cs index 8c926862..a216ddb7 100644 --- a/GUI/GarExtract.cs +++ b/GUI/GarExtract.cs @@ -306,9 +306,9 @@ namespace GARbro.GUI void ExtractImage (ArcFile arc, Entry entry, ImageFormat target_format) { - using (var file = arc.OpenSeekableEntry (entry)) + using (var file = arc.OpenBinaryEntry (entry)) { - var src_format = ImageFormat.FindFormat (file, entry.Name); + var src_format = ImageFormat.FindFormat (file); if (null == src_format) throw new InvalidFormatException (string.Format ("{1}: {0}", guiStrings.MsgUnableInterpretImage, entry.Name)); file.Position = 0; @@ -318,7 +318,7 @@ namespace GARbro.GUI { // source format is the same as a target, copy file as is using (var output = ArchiveFormat.CreateFile (outname)) - file.CopyTo (output); + file.AsStream.CopyTo (output); return; } ImageData image = src_format.Item1.Read (file, src_format.Item2); @@ -364,7 +364,7 @@ namespace GARbro.GUI static void ExtractAudio (ArcFile arc, Entry entry) { - using (var file = arc.OpenEntry (entry)) + using (var file = arc.OpenBinaryEntry (entry)) using (var sound = AudioFormat.Read (file)) { if (null == sound) diff --git a/GUI/ImagePreview.cs b/GUI/ImagePreview.cs index e7966156..f1caab06 100644 --- a/GUI/ImagePreview.cs +++ b/GUI/ImagePreview.cs @@ -188,17 +188,12 @@ namespace GARbro.GUI } } - Stream OpenPreviewStream (PreviewFile preview) - { - return VFS.OpenSeekableStream (preview.Entry); - } - void LoadPreviewText (PreviewFile preview) { Stream file = null; try { - file = OpenPreviewStream (preview); + file = VFS.OpenBinaryStream (preview.Entry).AsStream; if (!TextView.IsTextFile (file)) { ResetPreviewPane(); @@ -230,9 +225,9 @@ namespace GARbro.GUI { try { - using (var file = OpenPreviewStream (preview)) + using (var file = VFS.OpenBinaryStream (preview.Entry)) { - var data = ImageFormat.Read (preview.Name, file); + var data = ImageFormat.Read (file); if (null != data) SetPreviewImage (preview, data.Bitmap); else diff --git a/GUI/MainWindow.xaml.cs b/GUI/MainWindow.xaml.cs index 303994cc..efc6b9ef 100644 --- a/GUI/MainWindow.xaml.cs +++ b/GUI/MainWindow.xaml.cs @@ -924,7 +924,7 @@ namespace GARbro.GUI try { SetBusyState(); - using (var input = VFS.OpenStream (entry)) + using (var input = VFS.OpenBinaryStream (entry)) { FormatCatalog.Instance.LastError = null; sound = AudioFormat.Read (input); diff --git a/GameRes/ArcFile.cs b/GameRes/ArcFile.cs index 51a6586d..a66cfc12 100644 --- a/GameRes/ArcFile.cs +++ b/GameRes/ArcFile.cs @@ -211,6 +211,14 @@ namespace GameRes } } + public IBinaryStream OpenBinaryEntry (Entry entry) + { + var input = OpenSeekableEntry (entry); + if (input is IBinaryStream) + return input as IBinaryStream; + return new BinaryStream (input, entry.Name); + } + public ArchiveFileSystem CreateFileSystem () { if (m_interface.IsHierarchic) diff --git a/GameRes/Audio.cs b/GameRes/Audio.cs index 24cc0d7e..73ee2242 100644 --- a/GameRes/Audio.cs +++ b/GameRes/Audio.cs @@ -162,34 +162,21 @@ namespace GameRes { public override string Type { get { return "audio"; } } - public abstract SoundInput TryOpen (Stream file); + public abstract SoundInput TryOpen (IBinaryStream file); public virtual void Write (SoundInput source, Stream output) { throw new System.NotImplementedException ("AudioFormat.Write not implemenented"); } - public static SoundInput Read (Stream file) + public static SoundInput Read (IBinaryStream file) { - var input = new MemoryStream(); - file.CopyTo (input); - try - { - var sound = FindFormat (input); - if (null != sound) - input = null; // input stream is owned by sound object now, don't dispose it - return sound; - } - finally - { - if (null != input) - input.Dispose(); - } + return FindFormat (file); } - public static SoundInput FindFormat (Stream file) + public static SoundInput FindFormat (IBinaryStream file) { - uint signature = FormatCatalog.ReadSignature (file); + uint signature = file.Signature; for (;;) { var range = FormatCatalog.Instance.LookupSignature (signature); diff --git a/GameRes/AudioWAV.cs b/GameRes/AudioWAV.cs index ac9c51a4..b61452ae 100644 --- a/GameRes/AudioWAV.cs +++ b/GameRes/AudioWAV.cs @@ -111,17 +111,18 @@ namespace GameRes 0x0055, // MpegLayer3 }; - public override SoundInput TryOpen (Stream file) + public override SoundInput TryOpen (IBinaryStream file) { - SoundInput sound = new WaveInput (file); + SoundInput sound = new WaveInput (file.AsStream); if (EmbeddedFormats.Contains (sound.Format.FormatTag)) { + var bin = new BinaryStream (sound, file.Name); try { - var embedded = AudioFormat.Read (sound); + var embedded = AudioFormat.Read (bin); if (null != embedded) { - sound.Dispose(); +// sound.Dispose(); sound = embedded; } } diff --git a/GameRes/BinaryStream.cs b/GameRes/BinaryStream.cs index 76aa3505..a730e0d1 100644 --- a/GameRes/BinaryStream.cs +++ b/GameRes/BinaryStream.cs @@ -32,7 +32,7 @@ using GameRes.Utility; namespace GameRes { - public interface IBinaryStream + public interface IBinaryStream : IDisposable { /// /// Name of the stream (could be name of the underlying file) or an empty string. @@ -221,16 +221,32 @@ namespace GameRes public BinaryStream (Stream input, string name, bool leave_open = false) { - if (null == name) - name = ""; - m_source = input; - m_should_dispose = !leave_open; m_buffer = new byte[0x10]; m_buffer_pos = 0; m_buffer_end = 0; m_signature = new Lazy (ReadSignature); m_header_size = 0; - Name = name; + Name = name ?? ""; + if (!input.CanSeek) + { + m_source = new MemoryStream(); + input.CopyTo (m_source); + m_should_dispose = true; + if (!leave_open) + input.Dispose(); + m_source.Position = 0; + } + else + { + m_source = input; + m_should_dispose = !leave_open; + } + } + + public static BinaryStream FromFile (string filename) + { + var stream = File.OpenRead (filename); + return new BinaryStream (stream, filename); } uint ReadSignature () diff --git a/GameRes/FileSystem.cs b/GameRes/FileSystem.cs index 31d51ccc..57953d8d 100644 --- a/GameRes/FileSystem.cs +++ b/GameRes/FileSystem.cs @@ -50,7 +50,10 @@ namespace GameRes /// Stream OpenStream (Entry entry); - Stream OpenSeekableStream (Entry entry); + /// + /// Open file for reading as seekable binary stream. + /// + IBinaryStream OpenBinaryStream (Entry entry); /// /// Open file for reading as memory-mapped view. @@ -183,9 +186,10 @@ namespace GameRes return File.OpenRead (entry.Name); } - public Stream OpenSeekableStream (Entry entry) + public IBinaryStream OpenBinaryStream (Entry entry) { - return OpenStream (entry); + var input = OpenStream (entry); + return new BinaryStream (input, entry.Name); } public ArcView OpenView (Entry entry) @@ -229,9 +233,9 @@ namespace GameRes return m_arc.OpenEntry (entry); } - public Stream OpenSeekableStream (Entry entry) + public IBinaryStream OpenBinaryStream (Entry entry) { - return m_arc.OpenSeekableEntry (entry); + return m_arc.OpenBinaryEntry (entry); } public ArcView OpenView (Entry entry) @@ -706,9 +710,9 @@ namespace GameRes return m_vfs.Top.OpenStream (entry); } - public static Stream OpenSeekableStream (Entry entry) + public static IBinaryStream OpenBinaryStream (Entry entry) { - return m_vfs.Top.OpenSeekableStream (entry); + return m_vfs.Top.OpenBinaryStream (entry); } public static ArcView OpenView (Entry entry) @@ -721,9 +725,9 @@ namespace GameRes return m_vfs.Top.OpenStream (m_vfs.Top.FindFile (filename)); } - public static Stream OpenSeekableStream (string filename) + public static IBinaryStream OpenBinaryStream (string filename) { - return m_vfs.Top.OpenSeekableStream (m_vfs.Top.FindFile (filename)); + return m_vfs.Top.OpenBinaryStream (m_vfs.Top.FindFile (filename)); } public static ArcView OpenView (string filename) diff --git a/GameRes/Image.cs b/GameRes/Image.cs index 44799097..9a363730 100644 --- a/GameRes/Image.cs +++ b/GameRes/Image.cs @@ -115,49 +115,32 @@ namespace GameRes { public override string Type { get { return "image"; } } - public abstract ImageMetaData ReadMetaData (Stream file); + public abstract ImageMetaData ReadMetaData (IBinaryStream file); - public abstract ImageData Read (Stream file, ImageMetaData info); + public abstract ImageData Read (IBinaryStream file, ImageMetaData info); public abstract void Write (Stream file, ImageData bitmap); - public static ImageData Read (Stream file) - { - return Read (null, file); - } +// public static ImageData Read (Stream file) +// { +// using (var bin = new BinaryStream (file, true)) +// return Read (null, bin); +// } - public static ImageData Read (string filename, Stream file) + public static ImageData Read (IBinaryStream file) { - bool need_dispose = false; - try - { - if (!file.CanSeek) - { - var stream = new MemoryStream(); - file.CopyTo (stream); - file = stream; - need_dispose = true; - } - var format = FindFormat (file, filename); - if (null == format) - return null; - file.Position = 0; - return format.Item1.Read (file, format.Item2); - } - finally - { - if (need_dispose) - file.Dispose(); - } - } - - public static System.Tuple FindFormat (Stream file, string filename = null) - { - if (file.Length < 4) + var format = FindFormat (file); + if (null == format) return null; - uint signature = FormatCatalog.ReadSignature (file); + file.Position = 0; + return format.Item1.Read (file, format.Item2); + } + + public static System.Tuple FindFormat (IBinaryStream file) + { + uint signature = file.Signature; Lazy ext = null; - if (!string.IsNullOrEmpty (filename)) - ext = new Lazy (() => Path.GetExtension (filename).TrimStart ('.').ToLowerInvariant(), false); + if (!string.IsNullOrEmpty (file.Name)) + ext = new Lazy (() => Path.GetExtension (file.Name).TrimStart ('.').ToLowerInvariant(), false); for (;;) { var range = FormatCatalog.Instance.LookupSignature (signature); @@ -172,7 +155,7 @@ namespace GameRes ImageMetaData metadata = impl.ReadMetaData (file); if (null != metadata) { - metadata.FileName = filename; + metadata.FileName = file.Name; return Tuple.Create (impl, metadata); } } diff --git a/GameRes/ImageBMP.cs b/GameRes/ImageBMP.cs index 9786593b..6e2e74d6 100644 --- a/GameRes/ImageBMP.cs +++ b/GameRes/ImageBMP.cs @@ -42,7 +42,7 @@ namespace GameRes public interface IBmpExtension { - ImageData Read (Stream file, BmpMetaData info); + ImageData Read (IBinaryStream file, BmpMetaData info); } [Export(typeof(ImageFormat))] @@ -60,12 +60,11 @@ namespace GameRes bool EnableExtensions = true; - public override ImageData Read (Stream file, ImageMetaData info) + public override ImageData Read (IBinaryStream file, ImageMetaData info) { var bmp_info = info as BmpMetaData; if (bmp_info != null && EnableExtensions) { - bool can_seek = file.CanSeek; foreach (var ext in m_extensions) { try @@ -78,11 +77,10 @@ namespace GameRes { System.Diagnostics.Trace.WriteLine (X.Message, ext.ToString()); } - if (can_seek) - file.Position = 0; + file.Position = 0; } } - var decoder = new BmpBitmapDecoder (file, + var decoder = new BmpBitmapDecoder (file.AsStream, BitmapCreateOptions.None, BitmapCacheOption.OnLoad); BitmapSource frame = decoder.Frames.First(); frame.Freeze(); @@ -96,10 +94,10 @@ namespace GameRes encoder.Save (file); } - void SkipBytes (BinaryReader file, uint num) + void SkipBytes (IBinaryStream file, uint num) { - if (file.BaseStream.CanSeek) - file.BaseStream.Seek (num, SeekOrigin.Current); + if (file.AsStream.CanSeek) + file.Seek (num, SeekOrigin.Current); else { for (int i = 0; i < num / 4; ++i) @@ -109,49 +107,46 @@ namespace GameRes } } - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream file) { - int c1 = stream.ReadByte(); - int c2 = stream.ReadByte(); + int c1 = file.ReadByte(); + int c2 = file.ReadByte(); if ('B' != c1 || 'M' != c2) return null; - using (var file = new ArcView.Reader (stream)) + uint size = file.ReadUInt32(); + if (size < 14+40) { - uint size = file.ReadUInt32(); - if (size < 14+40) - { - // some otherwise valid bitmaps have size field set to zero - if (size != 0 || !stream.CanSeek) - return null; - size = (uint)stream.Length; - } - SkipBytes (file, 8); - uint header_size = file.ReadUInt32(); - if (header_size < 40 || size-14 < header_size) + // some otherwise valid bitmaps have size field set to zero + if (size != 0 || !file.AsStream.CanSeek) return null; - uint width = file.ReadUInt32(); - uint height = file.ReadUInt32(); - file.ReadInt16(); - int bpp = file.ReadInt16(); - return new BmpMetaData { - Width = width, - Height = height, - OffsetX = 0, - OffsetY = 0, - BPP = bpp, - ImageLength = size, - HeaderLength = header_size + 14, - }; + size = (uint)file.Length; } + SkipBytes (file, 8); + uint header_size = file.ReadUInt32(); + if (header_size < 40 || size-14 < header_size) + return null; + uint width = file.ReadUInt32(); + uint height = file.ReadUInt32(); + file.ReadInt16(); + int bpp = file.ReadInt16(); + return new BmpMetaData { + Width = width, + Height = height, + OffsetX = 0, + OffsetY = 0, + BPP = bpp, + ImageLength = size, + HeaderLength = header_size + 14, + }; } } [Export(typeof(IBmpExtension))] public class BitmapWithAlpha : IBmpExtension { - public ImageData Read (Stream file, BmpMetaData info) + public ImageData Read (IBinaryStream file, BmpMetaData info) { - if (file.CanSeek) + if (file.AsStream.CanSeek) { var width_x_height = info.Width * info.Height; uint bmp_length = width_x_height * (uint)info.BPP/8 + info.HeaderLength; @@ -170,7 +165,7 @@ namespace GameRes return null; } - private ImageData ReadBitmapWithAlpha (Stream file, BmpMetaData info) + private ImageData ReadBitmapWithAlpha (IBinaryStream file, BmpMetaData info) { file.Position = info.ImageLength; var alpha = new byte[info.Width*info.Height]; @@ -193,7 +188,7 @@ namespace GameRes return ImageData.Create (info, PixelFormats.Bgra32, null, pixels, dst_stride); } - private ImageData ReadBitmapBGRA (Stream file, BmpMetaData info) + private ImageData ReadBitmapBGRA (IBinaryStream file, BmpMetaData info) { file.Position = info.HeaderLength; int stride = (int)info.Width * 4; diff --git a/GameRes/ImageJPEG.cs b/GameRes/ImageJPEG.cs index bf0d3183..982318b9 100644 --- a/GameRes/ImageJPEG.cs +++ b/GameRes/ImageJPEG.cs @@ -46,12 +46,12 @@ namespace GameRes { Extensions = new string[] { "jpg", "jpeg" }; Signatures = new uint[] { 0xe0ffd8ffu, 0 }; - Quality = 90; + Quality = 100; } - public override ImageData Read (Stream file, ImageMetaData info) + public override ImageData Read (IBinaryStream file, ImageMetaData info) { - var decoder = new JpegBitmapDecoder (file, + var decoder = new JpegBitmapDecoder (file.AsStream, BitmapCreateOptions.None, BitmapCacheOption.OnLoad); var frame = decoder.Frames[0]; frame.Freeze(); @@ -66,36 +66,33 @@ namespace GameRes encoder.Save (file); } - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream file) { - if (0xff != stream.ReadByte() || 0xd8 != stream.ReadByte()) + if (0xFF != file.ReadByte() || 0xD8 != file.ReadByte()) return null; - using (var file = new ArcView.Reader (stream)) + while (-1 != file.PeekByte()) { - while (-1 != file.PeekChar()) + ushort marker = Binary.BigEndian (file.ReadUInt16()); + if ((marker & 0xff00) != 0xff00) + break; + int length = Binary.BigEndian (file.ReadUInt16()); + if ((marker & 0x00f0) == 0xc0 && marker != 0xffc4) { - ushort marker = Binary.BigEndian (file.ReadUInt16()); - if ((marker & 0xff00) != 0xff00) + if (length < 8) break; - int length = Binary.BigEndian (file.ReadUInt16()); - if ((marker & 0x00f0) == 0xc0 && marker != 0xffc4) - { - if (length < 8) - break; - int bits = file.ReadByte(); - uint height = Binary.BigEndian (file.ReadUInt16()); - uint width = Binary.BigEndian (file.ReadUInt16()); - int components = file.ReadByte(); - return new ImageMetaData { - Width = width, - Height = height, - BPP = bits * components, - }; - } - file.BaseStream.Seek (length-2, SeekOrigin.Current); + int bits = file.ReadByte(); + uint height = Binary.BigEndian (file.ReadUInt16()); + uint width = Binary.BigEndian (file.ReadUInt16()); + int components = file.ReadByte(); + return new ImageMetaData { + Width = width, + Height = height, + BPP = bits * components, + }; } - return null; + file.Seek (length-2, SeekOrigin.Current); } + return null; } } } diff --git a/GameRes/ImagePNG.cs b/GameRes/ImagePNG.cs index 330a2b12..3bd4973a 100644 --- a/GameRes/ImagePNG.cs +++ b/GameRes/ImagePNG.cs @@ -41,11 +41,11 @@ namespace GameRes public override uint Signature { get { return 0x474e5089; } } public override bool CanWrite { get { return true; } } - public override ImageData Read (Stream file, ImageMetaData info) + public override ImageData Read (IBinaryStream file, ImageMetaData info) { - var decoder = new PngBitmapDecoder (file, + var decoder = new PngBitmapDecoder (file.AsStream, BitmapCreateOptions.None, BitmapCacheOption.OnLoad); - BitmapSource frame = decoder.Frames.First(); + BitmapSource frame = decoder.Frames[0]; frame.Freeze(); return new ImageData (frame, info); } @@ -102,10 +102,10 @@ namespace GameRes } } - void SkipBytes (BinaryReader file, uint num) + void SkipBytes (IBinaryStream file, uint num) { - if (file.BaseStream.CanSeek) - file.BaseStream.Seek (num, SeekOrigin.Current); + if (file.AsStream.CanSeek) + file.Seek (num, SeekOrigin.Current); else { for (int i = 0; i < num / 4; ++i) @@ -115,100 +115,72 @@ namespace GameRes } } - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream file) { - ImageMetaData meta = null; - var file = new ArcView.Reader (stream); - try + file.ReadUInt32(); + if (file.ReadUInt32() != 0x0a1a0a0d) + return null; + uint chunk_size = Binary.BigEndian (file.ReadUInt32()); + byte[] chunk_type = file.ReadBytes (4); + if (!Binary.AsciiEqual (chunk_type, "IHDR")) + return null; + + var meta = new ImageMetaData(); + meta.Width = Binary.BigEndian (file.ReadUInt32()); + meta.Height = Binary.BigEndian (file.ReadUInt32()); + int bpp = file.ReadByte(); + int color_type = file.ReadByte(); + switch (color_type) { - file.ReadUInt32(); - if (file.ReadUInt32() != 0x0a1a0a0d) - return null; - uint chunk_size = Binary.BigEndian (file.ReadUInt32()); - char[] chunk_type = new char[4]; + case 2: meta.BPP = bpp*3; break; + case 3: meta.BPP = 24; break; + case 4: meta.BPP = bpp*2; break; + case 6: meta.BPP = bpp*4; break; + default: meta.BPP = bpp; break; + } + SkipBytes (file, 7); + + for (;;) + { + chunk_size = Binary.BigEndian (file.ReadUInt32()); file.Read (chunk_type, 0, 4); - if (!chunk_type.SequenceEqual ("IHDR")) - return null; - - meta = new ImageMetaData(); - meta.Width = Binary.BigEndian (file.ReadUInt32()); - meta.Height = Binary.BigEndian (file.ReadUInt32()); - int bpp = file.ReadByte(); - int color_type = file.ReadByte(); - switch (color_type) + if (Binary.AsciiEqual (chunk_type, "IDAT") || Binary.AsciiEqual (chunk_type, "IEND")) + break; + if (Binary.AsciiEqual (chunk_type, "oFFs")) { - case 2: meta.BPP = bpp*3; break; - case 3: meta.BPP = 24; break; - case 4: meta.BPP = bpp*2; break; - case 6: meta.BPP = bpp*4; break; - default: meta.BPP = bpp; break; - } - SkipBytes (file, 7); - - for (;;) - { - chunk_size = Binary.BigEndian (file.ReadUInt32()); - file.Read (chunk_type, 0, 4); - if (chunk_type.SequenceEqual ("IDAT") || chunk_type.SequenceEqual ("IEND")) - break; - if (chunk_type.SequenceEqual ("oFFs")) + int x = Binary.BigEndian (file.ReadInt32()); + int y = Binary.BigEndian (file.ReadInt32()); + if (0 == file.ReadByte()) { - int x = Binary.BigEndian (file.ReadInt32()); - int y = Binary.BigEndian (file.ReadInt32()); - if (0 == file.ReadByte()) - { - meta.OffsetX = x; - meta.OffsetY = y; - } - break; + meta.OffsetX = x; + meta.OffsetY = y; } - SkipBytes (file, chunk_size+4); + break; } - } - catch - { - meta = null; - } - finally - { - file.Dispose(); - if (stream.CanSeek) - stream.Position = 0; + SkipBytes (file, chunk_size+4); } return meta; } - public static long FindChunk (Stream stream, string chunk) + public static long FindChunk (IBinaryStream file, string chunk) { - long found_offset = -1; - var file = new ArcView.Reader (stream); try { - char[] buf = new char[4]; - file.BaseStream.Position = 8; - while (-1 != file.PeekChar()) + var buf = new byte[4]; + file.Position = 8; + while (-1 != file.PeekByte()) { - long chunk_offset = file.BaseStream.Position; + long chunk_offset = file.Position; uint chunk_size = Binary.BigEndian (file.ReadUInt32()); if (4 != file.Read (buf, 0, 4)) break; - if (chunk.SequenceEqual (buf)) - { - found_offset = chunk_offset; - break; - } - file.BaseStream.Position += chunk_size + 4; + if (Binary.AsciiEqual (buf, chunk)) + return chunk_offset; + file.Position += chunk_size + 4; } } - catch - { - // ignore errors - } - finally - { - file.Dispose(); - } - return found_offset; + catch { /* ignore errors */ } + return -1L; } } } diff --git a/GameRes/ImageTGA.cs b/GameRes/ImageTGA.cs index b9d03e01..f90418b3 100644 --- a/GameRes/ImageTGA.cs +++ b/GameRes/ImageTGA.cs @@ -52,14 +52,11 @@ namespace GameRes public override uint Signature { get { return 0; } } public override bool CanWrite { get { return true; } } - public override ImageData Read (Stream stream, ImageMetaData metadata) + public override ImageData Read (IBinaryStream stream, ImageMetaData metadata) { - var meta = metadata as TgaMetaData; - if (null == meta) - throw new System.ArgumentException ("TgaFormat.Read should be supplied with TgaMetaData", "metadata"); - var reader = new Reader (stream, meta); + var reader = new Reader (stream, (TgaMetaData)metadata); var pixels = reader.Unpack(); - return ImageData.Create (meta, reader.Format, reader.Palette, pixels, reader.Stride); + return ImageData.Create (metadata, reader.Format, reader.Palette, pixels, reader.Stride); } public override void Write (Stream stream, ImageData image) @@ -118,65 +115,62 @@ namespace GameRes } } - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream file) { - using (var file = new ArcView.Reader (stream)) + short id_length = (short)file.ReadByte(); + short colormap_type = (short)file.ReadByte(); + if (colormap_type > 1) + return null; + short image_type = (short)file.ReadByte(); + ushort colormap_first = file.ReadUInt16(); + ushort colormap_length = file.ReadUInt16(); + short colormap_depth = (short)file.ReadByte(); + int pos_x = file.ReadInt16(); + int pos_y = file.ReadInt16(); + uint width = file.ReadUInt16(); + uint height = file.ReadUInt16(); + int bpp = file.ReadByte(); + if (bpp != 32 && bpp != 24 && bpp != 16 && bpp != 15 && bpp != 8) + return null; + short descriptor = (short)file.ReadByte(); + uint colormap_offset = (uint)(18 + id_length); + switch (image_type) { - short id_length = file.ReadByte(); - short colormap_type = file.ReadByte(); - if (colormap_type > 1) + default: return null; + case 1: // Uncompressed, color-mapped images. + case 9: // Runlength encoded color-mapped images. + case 32: // Compressed color-mapped data, using Huffman, Delta, and + // runlength encoding. + case 33: // Compressed color-mapped data, using Huffman, Delta, and + // runlength encoding. 4-pass quadtree-type process. + if (colormap_depth != 24 && colormap_depth != 32) return null; - short image_type = file.ReadByte(); - ushort colormap_first = file.ReadUInt16(); - ushort colormap_length = file.ReadUInt16(); - short colormap_depth = file.ReadByte(); - int pos_x = file.ReadInt16(); - int pos_y = file.ReadInt16(); - uint width = file.ReadUInt16(); - uint height = file.ReadUInt16(); - int bpp = file.ReadByte(); - if (bpp != 32 && bpp != 24 && bpp != 16 && bpp != 15 && bpp != 8) - return null; - short descriptor = file.ReadByte(); - uint colormap_offset = (uint)(18 + id_length); - switch (image_type) - { - default: return null; - case 1: // Uncompressed, color-mapped images. - case 9: // Runlength encoded color-mapped images. - case 32: // Compressed color-mapped data, using Huffman, Delta, and - // runlength encoding. - case 33: // Compressed color-mapped data, using Huffman, Delta, and - // runlength encoding. 4-pass quadtree-type process. - if (colormap_depth != 24 && colormap_depth != 32) - return null; - break; - case 2: // Uncompressed, RGB images. - case 3: // Uncompressed, black and white images. - case 10: // Runlength encoded RGB images. - case 11: // Compressed, black and white images. - break; - } - return new TgaMetaData { - OffsetX = pos_x, - OffsetY = pos_y, - Width = width, - Height = height, - BPP = bpp, - ImageType = image_type, - ColormapType = colormap_type, - ColormapOffset = colormap_offset, - ColormapFirst = colormap_first, - ColormapLength = colormap_length, - ColormapDepth = colormap_depth, - Descriptor = descriptor, - }; + break; + case 2: // Uncompressed, RGB images. + case 3: // Uncompressed, black and white images. + case 10: // Runlength encoded RGB images. + case 11: // Compressed, black and white images. + break; } + return new TgaMetaData { + OffsetX = pos_x, + OffsetY = pos_y, + Width = width, + Height = height, + BPP = bpp, + ImageType = image_type, + ColormapType = colormap_type, + ColormapOffset = colormap_offset, + ColormapFirst = colormap_first, + ColormapLength = colormap_length, + ColormapDepth = colormap_depth, + Descriptor = descriptor, + }; } internal class Reader { - Stream m_input; + IBinaryStream m_input; TgaMetaData m_meta; int m_width; int m_height; @@ -189,7 +183,7 @@ namespace GameRes public int Stride { get { return m_stride; } } public byte[] Data { get { return m_data; } } - public Reader (Stream stream, TgaMetaData meta) + public Reader (IBinaryStream stream, TgaMetaData meta) { m_input = stream; m_meta = meta; diff --git a/GameRes/ImageTIFF.cs b/GameRes/ImageTIFF.cs index 6206542d..00b1ddd9 100644 --- a/GameRes/ImageTIFF.cs +++ b/GameRes/ImageTIFF.cs @@ -46,9 +46,9 @@ namespace GameRes Signatures = new uint[] { 0x002a4949, 0x2a004d4d }; } - public override ImageData Read (Stream file, ImageMetaData info) + public override ImageData Read (IBinaryStream file, ImageMetaData info) { - var decoder = new TiffBitmapDecoder (file, + var decoder = new TiffBitmapDecoder (file.AsStream, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.OnLoad); var frame = decoder.Frames[0]; frame.Freeze(); @@ -63,9 +63,6 @@ namespace GameRes encoder.Save (file); } - private delegate uint UInt32Reader(); - private delegate ushort UInt16Reader(); - enum TIFF { ImageWidth = 0x100, @@ -106,15 +103,15 @@ namespace GameRes Complete = Sufficient|PosX|PosY, } - public override ImageMetaData ReadMetaData (Stream stream) + public override ImageMetaData ReadMetaData (IBinaryStream stream) { using (var file = new Parser (stream)) return file.ReadMetaData(); } - public class Parser : IDisposable + internal sealed class Parser : IDisposable { - private BinaryReader m_file; + private IBinaryStream m_file; private readonly bool m_is_bigendian; private readonly uint m_first_ifd; private readonly uint[] m_type_size = { 0, 1, 1, 2, 4, 8, 1, 1, 2, 4, 8, 4, 8 }; @@ -127,11 +124,10 @@ namespace GameRes UInt32Reader ReadUInt32; UInt64Reader ReadUInt64; - public Parser (Stream file) + public Parser (IBinaryStream file) { - m_file = new ArcView.Reader (file); - uint signature = m_file.ReadUInt32(); - m_is_bigendian = 0x2a004d4d == signature; + m_file = file; + m_is_bigendian = 0x2a004d4d == m_file.Signature; if (m_is_bigendian) { ReadUInt16 = () => Binary.BigEndian (m_file.ReadUInt16()); @@ -152,13 +148,13 @@ namespace GameRes uint ifd = m_first_ifd; for (;;) { - m_file.BaseStream.Position = ifd; + m_file.Position = ifd; uint tag_count = ReadUInt16(); ifd += 2 + tag_count*12; uint ifd_next = ReadUInt32(); if (0 == ifd_next) break; - if (ifd_next == ifd || ifd_next >= m_file.BaseStream.Length) + if (ifd_next == ifd || ifd_next >= m_file.Length) return -1; ifd = ifd_next; } @@ -172,7 +168,7 @@ namespace GameRes uint ifd = m_first_ifd; while (ifd != 0 && parsed != MetaParsed.Complete) { - m_file.BaseStream.Position = ifd; + m_file.Position = ifd; uint tag_count = ReadUInt16(); ifd += 2; for (uint i = 0; i < tag_count && parsed != MetaParsed.Complete; ++i) @@ -208,7 +204,7 @@ namespace GameRes if (count * GetTypeSize (type) > 4) { var bpp_offset = ReadUInt32(); - m_file.BaseStream.Position = bpp_offset; + m_file.Position = bpp_offset; } bpp = 0; for (uint b = 0; b < count; ++b) @@ -224,7 +220,7 @@ namespace GameRes } } ifd += 12; - m_file.BaseStream.Position = ifd; + m_file.Position = ifd; } uint ifd_next = ReadUInt32(); if (ifd_next == ifd) @@ -254,7 +250,7 @@ namespace GameRes bool ReadOffsetValue (TagType type, out int value) { if (GetTypeSize (type) > 4) - m_file.BaseStream.Position = ReadUInt32(); + m_file.Position = ReadUInt32(); return ReadValue (type, out value); } @@ -353,26 +349,10 @@ namespace GameRes } #region IDisposable Members - bool disposed = false; - public void Dispose () { - Dispose (true); GC.SuppressFinalize (this); } - - protected virtual void Dispose (bool disposing) - { - if (!disposed) - { - if (disposing) - { - m_file.Dispose(); - } - m_file = null; - disposed = true; - } - } #endregion } } diff --git a/GameRes/Properties/AssemblyInfo.cs b/GameRes/Properties/AssemblyInfo.cs index 3eeda0be..7bcf7ef1 100644 --- a/GameRes/Properties/AssemblyInfo.cs +++ b/GameRes/Properties/AssemblyInfo.cs @@ -10,7 +10,7 @@ using System.Runtime.InteropServices; [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany ("mørkt")] [assembly: AssemblyProduct("GameRes")] -[assembly: AssemblyCopyright ("Copyright © 2014-2015 mørkt")] +[assembly: AssemblyCopyright ("Copyright © 2014-2016 mørkt")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] @@ -32,5 +32,5 @@ using System.Runtime.InteropServices; // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion ("1.3.21.181")] -[assembly: AssemblyFileVersion ("1.3.21.181")] +[assembly: AssemblyVersion ("1.4.21.187")] +[assembly: AssemblyFileVersion ("1.4.21.187")]