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)
{
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))

View File

@ -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)

View File

@ -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

View File

@ -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);

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 ()
{
if (m_interface.IsHierarchic)

View File

@ -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<AudioFormat> (signature);

View File

@ -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;
}
}

View File

@ -32,7 +32,7 @@ using GameRes.Utility;
namespace GameRes
{
public interface IBinaryStream
public interface IBinaryStream : IDisposable
{
/// <summary>
/// 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<uint> (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 ()

View File

@ -50,7 +50,10 @@ namespace GameRes
/// </summary>
Stream OpenStream (Entry entry);
Stream OpenSeekableStream (Entry entry);
/// <summary>
/// Open file for reading as seekable binary stream.
/// </summary>
IBinaryStream OpenBinaryStream (Entry entry);
/// <summary>
/// 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)

View File

@ -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<ImageFormat, ImageMetaData> 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<ImageFormat, ImageMetaData> FindFormat (IBinaryStream file)
{
uint signature = file.Signature;
Lazy<string> ext = null;
if (!string.IsNullOrEmpty (filename))
ext = new Lazy<string> (() => Path.GetExtension (filename).TrimStart ('.').ToLowerInvariant(), false);
if (!string.IsNullOrEmpty (file.Name))
ext = new Lazy<string> (() => Path.GetExtension (file.Name).TrimStart ('.').ToLowerInvariant(), false);
for (;;)
{
var range = FormatCatalog.Instance.LookupSignature<ImageFormat> (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);
}
}

View File

@ -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;

View File

@ -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;
}
}
}

View File

@ -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;
}
}
}

View File

@ -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;

View File

@ -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
}
}

View File

@ -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")]