migration to IBinaryStream interface.

This commit is contained in:
morkt 2016-10-15 09:34:46 +04:00
parent 0b96ef8f77
commit 503b734645
16 changed files with 264 additions and 332 deletions

View File

@ -187,7 +187,7 @@ namespace GARbro.GUI
void ConvertAudio (string filename) void ConvertAudio (string filename)
{ {
using (var file = File.OpenRead (filename)) using (var file = BinaryStream.FromFile (filename))
using (var input = AudioFormat.Read (file)) using (var input = AudioFormat.Read (file))
{ {
if (null == input) if (null == input)
@ -223,9 +223,9 @@ namespace GARbro.GUI
string target_name = Path.GetFileName (filename); string target_name = Path.GetFileName (filename);
string target_ext = m_image_format.Extensions.FirstOrDefault(); string target_ext = m_image_format.Extensions.FirstOrDefault();
target_name = Path.ChangeExtension (target_name, target_ext); 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) if (null == src_format)
return; return;
if (src_format.Item1 == m_image_format && m_image_format.Extensions.Any (ext => ext == source_ext)) if (src_format.Item1 == m_image_format && m_image_format.Extensions.Any (ext => ext == source_ext))

View File

@ -306,9 +306,9 @@ namespace GARbro.GUI
void ExtractImage (ArcFile arc, Entry entry, ImageFormat target_format) 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) if (null == src_format)
throw new InvalidFormatException (string.Format ("{1}: {0}", guiStrings.MsgUnableInterpretImage, entry.Name)); throw new InvalidFormatException (string.Format ("{1}: {0}", guiStrings.MsgUnableInterpretImage, entry.Name));
file.Position = 0; file.Position = 0;
@ -318,7 +318,7 @@ namespace GARbro.GUI
{ {
// source format is the same as a target, copy file as is // source format is the same as a target, copy file as is
using (var output = ArchiveFormat.CreateFile (outname)) using (var output = ArchiveFormat.CreateFile (outname))
file.CopyTo (output); file.AsStream.CopyTo (output);
return; return;
} }
ImageData image = src_format.Item1.Read (file, src_format.Item2); ImageData image = src_format.Item1.Read (file, src_format.Item2);
@ -364,7 +364,7 @@ namespace GARbro.GUI
static void ExtractAudio (ArcFile arc, Entry entry) 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)) using (var sound = AudioFormat.Read (file))
{ {
if (null == sound) if (null == sound)

View File

@ -188,17 +188,12 @@ namespace GARbro.GUI
} }
} }
Stream OpenPreviewStream (PreviewFile preview)
{
return VFS.OpenSeekableStream (preview.Entry);
}
void LoadPreviewText (PreviewFile preview) void LoadPreviewText (PreviewFile preview)
{ {
Stream file = null; Stream file = null;
try try
{ {
file = OpenPreviewStream (preview); file = VFS.OpenBinaryStream (preview.Entry).AsStream;
if (!TextView.IsTextFile (file)) if (!TextView.IsTextFile (file))
{ {
ResetPreviewPane(); ResetPreviewPane();
@ -230,9 +225,9 @@ namespace GARbro.GUI
{ {
try 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) if (null != data)
SetPreviewImage (preview, data.Bitmap); SetPreviewImage (preview, data.Bitmap);
else else

View File

@ -924,7 +924,7 @@ namespace GARbro.GUI
try try
{ {
SetBusyState(); SetBusyState();
using (var input = VFS.OpenStream (entry)) using (var input = VFS.OpenBinaryStream (entry))
{ {
FormatCatalog.Instance.LastError = null; FormatCatalog.Instance.LastError = null;
sound = AudioFormat.Read (input); sound = AudioFormat.Read (input);

View File

@ -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 () public ArchiveFileSystem CreateFileSystem ()
{ {
if (m_interface.IsHierarchic) if (m_interface.IsHierarchic)

View File

@ -162,34 +162,21 @@ namespace GameRes
{ {
public override string Type { get { return "audio"; } } 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) public virtual void Write (SoundInput source, Stream output)
{ {
throw new System.NotImplementedException ("AudioFormat.Write not implemenented"); throw new System.NotImplementedException ("AudioFormat.Write not implemenented");
} }
public static SoundInput Read (Stream file) public static SoundInput Read (IBinaryStream file)
{ {
var input = new MemoryStream(); return FindFormat (file);
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();
}
} }
public static SoundInput FindFormat (Stream file) public static SoundInput FindFormat (IBinaryStream file)
{ {
uint signature = FormatCatalog.ReadSignature (file); uint signature = file.Signature;
for (;;) for (;;)
{ {
var range = FormatCatalog.Instance.LookupSignature<AudioFormat> (signature); var range = FormatCatalog.Instance.LookupSignature<AudioFormat> (signature);

View File

@ -111,17 +111,18 @@ namespace GameRes
0x0055, // MpegLayer3 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)) if (EmbeddedFormats.Contains (sound.Format.FormatTag))
{ {
var bin = new BinaryStream (sound, file.Name);
try try
{ {
var embedded = AudioFormat.Read (sound); var embedded = AudioFormat.Read (bin);
if (null != embedded) if (null != embedded)
{ {
sound.Dispose(); // sound.Dispose();
sound = embedded; sound = embedded;
} }
} }

View File

@ -32,7 +32,7 @@ using GameRes.Utility;
namespace GameRes namespace GameRes
{ {
public interface IBinaryStream public interface IBinaryStream : IDisposable
{ {
/// <summary> /// <summary>
/// Name of the stream (could be name of the underlying file) or an empty string. /// 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) 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 = new byte[0x10];
m_buffer_pos = 0; m_buffer_pos = 0;
m_buffer_end = 0; m_buffer_end = 0;
m_signature = new Lazy<uint> (ReadSignature); m_signature = new Lazy<uint> (ReadSignature);
m_header_size = 0; 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 () uint ReadSignature ()

View File

@ -50,7 +50,10 @@ namespace GameRes
/// </summary> /// </summary>
Stream OpenStream (Entry entry); Stream OpenStream (Entry entry);
Stream OpenSeekableStream (Entry entry); /// <summary>
/// Open file for reading as seekable binary stream.
/// </summary>
IBinaryStream OpenBinaryStream (Entry entry);
/// <summary> /// <summary>
/// Open file for reading as memory-mapped view. /// Open file for reading as memory-mapped view.
@ -183,9 +186,10 @@ namespace GameRes
return File.OpenRead (entry.Name); 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) public ArcView OpenView (Entry entry)
@ -229,9 +233,9 @@ namespace GameRes
return m_arc.OpenEntry (entry); 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) public ArcView OpenView (Entry entry)
@ -706,9 +710,9 @@ namespace GameRes
return m_vfs.Top.OpenStream (entry); 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) public static ArcView OpenView (Entry entry)
@ -721,9 +725,9 @@ namespace GameRes
return m_vfs.Top.OpenStream (m_vfs.Top.FindFile (filename)); 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) public static ArcView OpenView (string filename)

View File

@ -115,49 +115,32 @@ namespace GameRes
{ {
public override string Type { get { return "image"; } } 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 abstract void Write (Stream file, ImageData bitmap);
public static ImageData Read (Stream file) // public static ImageData Read (Stream file)
{ // {
return Read (null, 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; var format = FindFormat (file);
try
{
if (!file.CanSeek)
{
var stream = new MemoryStream();
file.CopyTo (stream);
file = stream;
need_dispose = true;
}
var format = FindFormat (file, filename);
if (null == format) if (null == format)
return null; return null;
file.Position = 0; file.Position = 0;
return format.Item1.Read (file, format.Item2); return format.Item1.Read (file, format.Item2);
} }
finally
{
if (need_dispose)
file.Dispose();
}
}
public static System.Tuple<ImageFormat, ImageMetaData> FindFormat (Stream file, string filename = null) public static System.Tuple<ImageFormat, ImageMetaData> FindFormat (IBinaryStream file)
{ {
if (file.Length < 4) uint signature = file.Signature;
return null;
uint signature = FormatCatalog.ReadSignature (file);
Lazy<string> ext = null; Lazy<string> ext = null;
if (!string.IsNullOrEmpty (filename)) if (!string.IsNullOrEmpty (file.Name))
ext = new Lazy<string> (() => Path.GetExtension (filename).TrimStart ('.').ToLowerInvariant(), false); ext = new Lazy<string> (() => Path.GetExtension (file.Name).TrimStart ('.').ToLowerInvariant(), false);
for (;;) for (;;)
{ {
var range = FormatCatalog.Instance.LookupSignature<ImageFormat> (signature); var range = FormatCatalog.Instance.LookupSignature<ImageFormat> (signature);
@ -172,7 +155,7 @@ namespace GameRes
ImageMetaData metadata = impl.ReadMetaData (file); ImageMetaData metadata = impl.ReadMetaData (file);
if (null != metadata) if (null != metadata)
{ {
metadata.FileName = filename; metadata.FileName = file.Name;
return Tuple.Create (impl, metadata); return Tuple.Create (impl, metadata);
} }
} }

View File

@ -42,7 +42,7 @@ namespace GameRes
public interface IBmpExtension public interface IBmpExtension
{ {
ImageData Read (Stream file, BmpMetaData info); ImageData Read (IBinaryStream file, BmpMetaData info);
} }
[Export(typeof(ImageFormat))] [Export(typeof(ImageFormat))]
@ -60,12 +60,11 @@ namespace GameRes
bool EnableExtensions = true; 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; var bmp_info = info as BmpMetaData;
if (bmp_info != null && EnableExtensions) if (bmp_info != null && EnableExtensions)
{ {
bool can_seek = file.CanSeek;
foreach (var ext in m_extensions) foreach (var ext in m_extensions)
{ {
try try
@ -78,11 +77,10 @@ namespace GameRes
{ {
System.Diagnostics.Trace.WriteLine (X.Message, ext.ToString()); 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); BitmapCreateOptions.None, BitmapCacheOption.OnLoad);
BitmapSource frame = decoder.Frames.First(); BitmapSource frame = decoder.Frames.First();
frame.Freeze(); frame.Freeze();
@ -96,10 +94,10 @@ namespace GameRes
encoder.Save (file); encoder.Save (file);
} }
void SkipBytes (BinaryReader file, uint num) void SkipBytes (IBinaryStream file, uint num)
{ {
if (file.BaseStream.CanSeek) if (file.AsStream.CanSeek)
file.BaseStream.Seek (num, SeekOrigin.Current); file.Seek (num, SeekOrigin.Current);
else else
{ {
for (int i = 0; i < num / 4; ++i) for (int i = 0; i < num / 4; ++i)
@ -109,21 +107,19 @@ namespace GameRes
} }
} }
public override ImageMetaData ReadMetaData (Stream stream) public override ImageMetaData ReadMetaData (IBinaryStream file)
{ {
int c1 = stream.ReadByte(); int c1 = file.ReadByte();
int c2 = stream.ReadByte(); int c2 = file.ReadByte();
if ('B' != c1 || 'M' != c2) if ('B' != c1 || 'M' != c2)
return null; return null;
using (var file = new ArcView.Reader (stream))
{
uint size = file.ReadUInt32(); uint size = file.ReadUInt32();
if (size < 14+40) if (size < 14+40)
{ {
// some otherwise valid bitmaps have size field set to zero // some otherwise valid bitmaps have size field set to zero
if (size != 0 || !stream.CanSeek) if (size != 0 || !file.AsStream.CanSeek)
return null; return null;
size = (uint)stream.Length; size = (uint)file.Length;
} }
SkipBytes (file, 8); SkipBytes (file, 8);
uint header_size = file.ReadUInt32(); uint header_size = file.ReadUInt32();
@ -144,14 +140,13 @@ namespace GameRes
}; };
} }
} }
}
[Export(typeof(IBmpExtension))] [Export(typeof(IBmpExtension))]
public class BitmapWithAlpha : 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; var width_x_height = info.Width * info.Height;
uint bmp_length = width_x_height * (uint)info.BPP/8 + info.HeaderLength; uint bmp_length = width_x_height * (uint)info.BPP/8 + info.HeaderLength;
@ -170,7 +165,7 @@ namespace GameRes
return null; return null;
} }
private ImageData ReadBitmapWithAlpha (Stream file, BmpMetaData info) private ImageData ReadBitmapWithAlpha (IBinaryStream file, BmpMetaData info)
{ {
file.Position = info.ImageLength; file.Position = info.ImageLength;
var alpha = new byte[info.Width*info.Height]; var alpha = new byte[info.Width*info.Height];
@ -193,7 +188,7 @@ namespace GameRes
return ImageData.Create (info, PixelFormats.Bgra32, null, pixels, dst_stride); 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; file.Position = info.HeaderLength;
int stride = (int)info.Width * 4; int stride = (int)info.Width * 4;

View File

@ -46,12 +46,12 @@ namespace GameRes
{ {
Extensions = new string[] { "jpg", "jpeg" }; Extensions = new string[] { "jpg", "jpeg" };
Signatures = new uint[] { 0xe0ffd8ffu, 0 }; 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); BitmapCreateOptions.None, BitmapCacheOption.OnLoad);
var frame = decoder.Frames[0]; var frame = decoder.Frames[0];
frame.Freeze(); frame.Freeze();
@ -66,13 +66,11 @@ namespace GameRes
encoder.Save (file); 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; return null;
using (var file = new ArcView.Reader (stream)) while (-1 != file.PeekByte())
{
while (-1 != file.PeekChar())
{ {
ushort marker = Binary.BigEndian (file.ReadUInt16()); ushort marker = Binary.BigEndian (file.ReadUInt16());
if ((marker & 0xff00) != 0xff00) if ((marker & 0xff00) != 0xff00)
@ -92,10 +90,9 @@ namespace GameRes
BPP = bits * components, BPP = bits * components,
}; };
} }
file.BaseStream.Seek (length-2, SeekOrigin.Current); file.Seek (length-2, SeekOrigin.Current);
} }
return null; return null;
} }
} }
}
} }

View File

@ -41,11 +41,11 @@ namespace GameRes
public override uint Signature { get { return 0x474e5089; } } public override uint Signature { get { return 0x474e5089; } }
public override bool CanWrite { get { return true; } } 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); BitmapCreateOptions.None, BitmapCacheOption.OnLoad);
BitmapSource frame = decoder.Frames.First(); BitmapSource frame = decoder.Frames[0];
frame.Freeze(); frame.Freeze();
return new ImageData (frame, info); 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) if (file.AsStream.CanSeek)
file.BaseStream.Seek (num, SeekOrigin.Current); file.Seek (num, SeekOrigin.Current);
else else
{ {
for (int i = 0; i < num / 4; ++i) for (int i = 0; i < num / 4; ++i)
@ -115,22 +115,17 @@ 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(); file.ReadUInt32();
if (file.ReadUInt32() != 0x0a1a0a0d) if (file.ReadUInt32() != 0x0a1a0a0d)
return null; return null;
uint chunk_size = Binary.BigEndian (file.ReadUInt32()); uint chunk_size = Binary.BigEndian (file.ReadUInt32());
char[] chunk_type = new char[4]; byte[] chunk_type = file.ReadBytes (4);
file.Read (chunk_type, 0, 4); if (!Binary.AsciiEqual (chunk_type, "IHDR"))
if (!chunk_type.SequenceEqual ("IHDR"))
return null; return null;
meta = new ImageMetaData(); var meta = new ImageMetaData();
meta.Width = Binary.BigEndian (file.ReadUInt32()); meta.Width = Binary.BigEndian (file.ReadUInt32());
meta.Height = Binary.BigEndian (file.ReadUInt32()); meta.Height = Binary.BigEndian (file.ReadUInt32());
int bpp = file.ReadByte(); int bpp = file.ReadByte();
@ -149,9 +144,9 @@ namespace GameRes
{ {
chunk_size = Binary.BigEndian (file.ReadUInt32()); chunk_size = Binary.BigEndian (file.ReadUInt32());
file.Read (chunk_type, 0, 4); file.Read (chunk_type, 0, 4);
if (chunk_type.SequenceEqual ("IDAT") || chunk_type.SequenceEqual ("IEND")) if (Binary.AsciiEqual (chunk_type, "IDAT") || Binary.AsciiEqual (chunk_type, "IEND"))
break; break;
if (chunk_type.SequenceEqual ("oFFs")) if (Binary.AsciiEqual (chunk_type, "oFFs"))
{ {
int x = Binary.BigEndian (file.ReadInt32()); int x = Binary.BigEndian (file.ReadInt32());
int y = Binary.BigEndian (file.ReadInt32()); int y = Binary.BigEndian (file.ReadInt32());
@ -164,51 +159,28 @@ namespace GameRes
} }
SkipBytes (file, chunk_size+4); SkipBytes (file, chunk_size+4);
} }
}
catch
{
meta = null;
}
finally
{
file.Dispose();
if (stream.CanSeek)
stream.Position = 0;
}
return meta; 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 try
{ {
char[] buf = new char[4]; var buf = new byte[4];
file.BaseStream.Position = 8; file.Position = 8;
while (-1 != file.PeekChar()) while (-1 != file.PeekByte())
{ {
long chunk_offset = file.BaseStream.Position; long chunk_offset = file.Position;
uint chunk_size = Binary.BigEndian (file.ReadUInt32()); uint chunk_size = Binary.BigEndian (file.ReadUInt32());
if (4 != file.Read (buf, 0, 4)) if (4 != file.Read (buf, 0, 4))
break; break;
if (chunk.SequenceEqual (buf)) if (Binary.AsciiEqual (buf, chunk))
{ return chunk_offset;
found_offset = chunk_offset; file.Position += chunk_size + 4;
break;
}
file.BaseStream.Position += chunk_size + 4;
} }
} }
catch catch { /* ignore errors */ }
{ return -1L;
// ignore errors
}
finally
{
file.Dispose();
}
return found_offset;
} }
} }
} }

View File

@ -52,14 +52,11 @@ namespace GameRes
public override uint Signature { get { return 0; } } public override uint Signature { get { return 0; } }
public override bool CanWrite { get { return true; } } 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; var reader = new Reader (stream, (TgaMetaData)metadata);
if (null == meta)
throw new System.ArgumentException ("TgaFormat.Read should be supplied with TgaMetaData", "metadata");
var reader = new Reader (stream, meta);
var pixels = reader.Unpack(); 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) public override void Write (Stream stream, ImageData image)
@ -118,18 +115,16 @@ 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();
short id_length = file.ReadByte();
short colormap_type = file.ReadByte();
if (colormap_type > 1) if (colormap_type > 1)
return null; return null;
short image_type = file.ReadByte(); short image_type = (short)file.ReadByte();
ushort colormap_first = file.ReadUInt16(); ushort colormap_first = file.ReadUInt16();
ushort colormap_length = file.ReadUInt16(); ushort colormap_length = file.ReadUInt16();
short colormap_depth = file.ReadByte(); short colormap_depth = (short)file.ReadByte();
int pos_x = file.ReadInt16(); int pos_x = file.ReadInt16();
int pos_y = file.ReadInt16(); int pos_y = file.ReadInt16();
uint width = file.ReadUInt16(); uint width = file.ReadUInt16();
@ -137,7 +132,7 @@ namespace GameRes
int bpp = file.ReadByte(); int bpp = file.ReadByte();
if (bpp != 32 && bpp != 24 && bpp != 16 && bpp != 15 && bpp != 8) if (bpp != 32 && bpp != 24 && bpp != 16 && bpp != 15 && bpp != 8)
return null; return null;
short descriptor = file.ReadByte(); short descriptor = (short)file.ReadByte();
uint colormap_offset = (uint)(18 + id_length); uint colormap_offset = (uint)(18 + id_length);
switch (image_type) switch (image_type)
{ {
@ -172,11 +167,10 @@ namespace GameRes
Descriptor = descriptor, Descriptor = descriptor,
}; };
} }
}
internal class Reader internal class Reader
{ {
Stream m_input; IBinaryStream m_input;
TgaMetaData m_meta; TgaMetaData m_meta;
int m_width; int m_width;
int m_height; int m_height;
@ -189,7 +183,7 @@ namespace GameRes
public int Stride { get { return m_stride; } } public int Stride { get { return m_stride; } }
public byte[] Data { get { return m_data; } } public byte[] Data { get { return m_data; } }
public Reader (Stream stream, TgaMetaData meta) public Reader (IBinaryStream stream, TgaMetaData meta)
{ {
m_input = stream; m_input = stream;
m_meta = meta; m_meta = meta;

View File

@ -46,9 +46,9 @@ namespace GameRes
Signatures = new uint[] { 0x002a4949, 0x2a004d4d }; 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); BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.OnLoad);
var frame = decoder.Frames[0]; var frame = decoder.Frames[0];
frame.Freeze(); frame.Freeze();
@ -63,9 +63,6 @@ namespace GameRes
encoder.Save (file); encoder.Save (file);
} }
private delegate uint UInt32Reader();
private delegate ushort UInt16Reader();
enum TIFF enum TIFF
{ {
ImageWidth = 0x100, ImageWidth = 0x100,
@ -106,15 +103,15 @@ namespace GameRes
Complete = Sufficient|PosX|PosY, Complete = Sufficient|PosX|PosY,
} }
public override ImageMetaData ReadMetaData (Stream stream) public override ImageMetaData ReadMetaData (IBinaryStream stream)
{ {
using (var file = new Parser (stream)) using (var file = new Parser (stream))
return file.ReadMetaData(); 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 bool m_is_bigendian;
private readonly uint m_first_ifd; 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 }; 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; UInt32Reader ReadUInt32;
UInt64Reader ReadUInt64; UInt64Reader ReadUInt64;
public Parser (Stream file) public Parser (IBinaryStream file)
{ {
m_file = new ArcView.Reader (file); m_file = file;
uint signature = m_file.ReadUInt32(); m_is_bigendian = 0x2a004d4d == m_file.Signature;
m_is_bigendian = 0x2a004d4d == signature;
if (m_is_bigendian) if (m_is_bigendian)
{ {
ReadUInt16 = () => Binary.BigEndian (m_file.ReadUInt16()); ReadUInt16 = () => Binary.BigEndian (m_file.ReadUInt16());
@ -152,13 +148,13 @@ namespace GameRes
uint ifd = m_first_ifd; uint ifd = m_first_ifd;
for (;;) for (;;)
{ {
m_file.BaseStream.Position = ifd; m_file.Position = ifd;
uint tag_count = ReadUInt16(); uint tag_count = ReadUInt16();
ifd += 2 + tag_count*12; ifd += 2 + tag_count*12;
uint ifd_next = ReadUInt32(); uint ifd_next = ReadUInt32();
if (0 == ifd_next) if (0 == ifd_next)
break; break;
if (ifd_next == ifd || ifd_next >= m_file.BaseStream.Length) if (ifd_next == ifd || ifd_next >= m_file.Length)
return -1; return -1;
ifd = ifd_next; ifd = ifd_next;
} }
@ -172,7 +168,7 @@ namespace GameRes
uint ifd = m_first_ifd; uint ifd = m_first_ifd;
while (ifd != 0 && parsed != MetaParsed.Complete) while (ifd != 0 && parsed != MetaParsed.Complete)
{ {
m_file.BaseStream.Position = ifd; m_file.Position = ifd;
uint tag_count = ReadUInt16(); uint tag_count = ReadUInt16();
ifd += 2; ifd += 2;
for (uint i = 0; i < tag_count && parsed != MetaParsed.Complete; ++i) for (uint i = 0; i < tag_count && parsed != MetaParsed.Complete; ++i)
@ -208,7 +204,7 @@ namespace GameRes
if (count * GetTypeSize (type) > 4) if (count * GetTypeSize (type) > 4)
{ {
var bpp_offset = ReadUInt32(); var bpp_offset = ReadUInt32();
m_file.BaseStream.Position = bpp_offset; m_file.Position = bpp_offset;
} }
bpp = 0; bpp = 0;
for (uint b = 0; b < count; ++b) for (uint b = 0; b < count; ++b)
@ -224,7 +220,7 @@ namespace GameRes
} }
} }
ifd += 12; ifd += 12;
m_file.BaseStream.Position = ifd; m_file.Position = ifd;
} }
uint ifd_next = ReadUInt32(); uint ifd_next = ReadUInt32();
if (ifd_next == ifd) if (ifd_next == ifd)
@ -254,7 +250,7 @@ namespace GameRes
bool ReadOffsetValue (TagType type, out int value) bool ReadOffsetValue (TagType type, out int value)
{ {
if (GetTypeSize (type) > 4) if (GetTypeSize (type) > 4)
m_file.BaseStream.Position = ReadUInt32(); m_file.Position = ReadUInt32();
return ReadValue (type, out value); return ReadValue (type, out value);
} }
@ -353,26 +349,10 @@ namespace GameRes
} }
#region IDisposable Members #region IDisposable Members
bool disposed = false;
public void Dispose () public void Dispose ()
{ {
Dispose (true);
GC.SuppressFinalize (this); GC.SuppressFinalize (this);
} }
protected virtual void Dispose (bool disposing)
{
if (!disposed)
{
if (disposing)
{
m_file.Dispose();
}
m_file = null;
disposed = true;
}
}
#endregion #endregion
} }
} }

View File

@ -10,7 +10,7 @@ using System.Runtime.InteropServices;
[assembly: AssemblyConfiguration("")] [assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany ("mørkt")] [assembly: AssemblyCompany ("mørkt")]
[assembly: AssemblyProduct("GameRes")] [assembly: AssemblyProduct("GameRes")]
[assembly: AssemblyCopyright ("Copyright © 2014-2015 mørkt")] [assembly: AssemblyCopyright ("Copyright © 2014-2016 mørkt")]
[assembly: AssemblyTrademark("")] [assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")] [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 // You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below: // by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")] // [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion ("1.3.21.181")] [assembly: AssemblyVersion ("1.4.21.187")]
[assembly: AssemblyFileVersion ("1.3.21.181")] [assembly: AssemblyFileVersion ("1.4.21.187")]