mirror of
https://github.com/crskycode/GARbro.git
synced 2024-12-23 19:34:15 +08:00
migration to IBinaryStream interface.
This commit is contained in:
parent
0b96ef8f77
commit
503b734645
@ -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))
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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 ()
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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")]
|
||||
|
Loading…
x
Reference in New Issue
Block a user