From 4901c2f1d346c649f544dc6f17d09166b56529e8 Mon Sep 17 00:00:00 2001 From: morkt Date: Tue, 25 Oct 2016 20:57:04 +0400 Subject: [PATCH] (AImageReader): implemented IImageDecoder interface. --- ArcFormats/Cyberworks/ArcDAT.cs | 76 +++++++++--------------------- ArcFormats/Cyberworks/ImageTINK.cs | 48 ++++++++++++++++--- 2 files changed, 64 insertions(+), 60 deletions(-) diff --git a/ArcFormats/Cyberworks/ArcDAT.cs b/ArcFormats/Cyberworks/ArcDAT.cs index 70b8bde7..35bffd2d 100644 --- a/ArcFormats/Cyberworks/ArcDAT.cs +++ b/ArcFormats/Cyberworks/ArcDAT.cs @@ -194,20 +194,24 @@ namespace GameRes.Formats.Cyberworks public override Stream OpenEntry (ArcFile arc, Entry entry) { - uint entry_size = entry.Size; - Stream input = arc.File.CreateStream (entry.Offset, entry_size); + Stream input = arc.File.CreateStream (entry.Offset, entry.Size); var pent = entry as PackedEntry; if (null != pent && pent.IsPacked) { input = new LzssStream (input); - entry_size = pent.UnpackedSize; } + return input; + } + + public override IImageDecoder OpenImage (ArcFile arc, Entry entry) + { var barc = arc as BellArchive; - if (null == barc || entry.Type != "image" || entry_size < 5) - return input; + if (null == barc || entry.Size < 5) + return base.OpenImage (arc, entry); + var input = arc.OpenBinaryEntry (entry); try { - return DecryptImage (input, entry_size, barc.Scheme); + return DecryptImage (input, barc.Scheme); } catch { @@ -216,47 +220,27 @@ namespace GameRes.Formats.Cyberworks } } - protected virtual Stream DecryptImage (Stream input, uint entry_size, AImageScheme scheme) + protected virtual IImageDecoder DecryptImage (IBinaryStream input, AImageScheme scheme) { - byte[] header = null; - byte type = (byte)input.ReadByte(); + int type = input.ReadByte(); if ('c' == type || 'b' == type) { - header = new byte[5]; - header[0] = type; - input.Read (header, 1, 4); - uint img_size = BigEndian.ToUInt32 (header, 1); - if (entry_size - 5 == img_size) + uint img_size = Binary.BigEndian (input.ReadUInt32()); + if (input.Length - 5 == img_size) { - if (input.CanSeek) - input = new StreamRegion (input, 5, img_size); - return input; + input = BinaryStream.FromStream (new StreamRegion (input.AsStream, 5, img_size), input.Name); } } - else if (scheme != null && 'a' == type && entry_size > 21) + else if (scheme != null && 'a' == type && input.Length > 21) { int id = input.ReadByte(); if (id == scheme.Value2) { - using (var reader = new AImageReader (input, scheme)) - { - reader.Unpack(); - return TgaStream.Create (reader.Info, reader.Data, scheme.Flipped); - } + return new AImageReader (input, scheme); } - header = new byte[2] { type, (byte)id }; } - if (input.CanSeek) - { - input.Position = 0; - } - else - { - if (null == header) - header = new byte[1] { type }; - input = new PrefixStream (header, input); - } - return input; + input.Position = 0; + return new ImageStreamDecoder (input); } uint DecodeDecimal (ArcView file, long offset) @@ -419,27 +403,13 @@ namespace GameRes.Formats.Cyberworks return new BellArchive (file, this, dir, scheme); } - protected override Stream DecryptImage (Stream input, uint entry_size, AImageScheme scheme) + protected override IImageDecoder DecryptImage (IBinaryStream input, AImageScheme scheme) { int id = input.ReadByte(); if (id == scheme.Value2) - { - using (var reader = new AImageReader (input, scheme)) - { - reader.Unpack(); - return TgaStream.Create (reader.Info, reader.Data, scheme.Flipped); - } - } - if (input.CanSeek) - { - input.Position = 0; - } - else - { - var header = new byte[1] { (byte)id }; - input = new PrefixStream (header, input); - } - return input; + return new AImageReader (input, scheme); + input.Position = 0; + return new ImageStreamDecoder (input); } byte[] ReadToc (string toc_name) diff --git a/ArcFormats/Cyberworks/ImageTINK.cs b/ArcFormats/Cyberworks/ImageTINK.cs index 57ddb644..61111542 100644 --- a/ArcFormats/Cyberworks/ImageTINK.cs +++ b/ArcFormats/Cyberworks/ImageTINK.cs @@ -26,6 +26,7 @@ using System; using System.ComponentModel.Composition; using System.IO; +using System.Windows.Media; namespace GameRes.Formats.Cyberworks { @@ -42,19 +43,41 @@ namespace GameRes.Formats.Cyberworks Ignored = Field1, } - internal sealed class AImageReader : IDisposable + internal sealed class AImageReader : IImageDecoder { - public readonly ImageMetaData Info = new ImageMetaData(); + readonly ImageMetaData m_info = new ImageMetaData(); - BinaryReader m_input; + IBinaryStream m_input; byte[] m_output; AImageScheme m_scheme; + ImageData m_image; + + public Stream Input { get { m_input.Position = 0; return m_input.AsStream; } } + public ImageMetaData Info { get { return m_info; } } + public ImageFormat Format { get { return null; } } + + public ImageData Image + { + get + { + if (null == m_image) + { + Unpack(); + int stride = (int)Info.Width * Info.BPP / 8; + if (m_scheme.Flipped) + m_image = ImageData.CreateFlipped (Info, GetPixelFormat(), null, Data, stride); + else + m_image = ImageData.Create (Info, GetPixelFormat(), null, Data, stride); + } + return m_image; + } + } public byte[] Data { get { return m_output; } } - public AImageReader (Stream input, AImageScheme scheme) + public AImageReader (IBinaryStream input, AImageScheme scheme) { - m_input = new ArcView.Reader (input); + m_input = input; m_scheme = scheme; } @@ -231,14 +254,14 @@ namespace GameRes.Formats.Cyberworks int GetInt () { - byte a = m_input.ReadByte(); + byte a = m_input.ReadUInt8(); if (a == m_scheme.Value3) a = 0; int d = 0; int c = 0; for (;;) { - byte a1 = m_input.ReadByte(); + byte a1 = m_input.ReadUInt8(); if (a1 == m_scheme.Value2) break; if (a1 != m_scheme.Value1) @@ -253,6 +276,17 @@ namespace GameRes.Formats.Cyberworks return a + (c + d * m_scheme.Value1) * m_scheme.Value1; } + PixelFormat GetPixelFormat () + { + switch (Info.BPP) + { + case 8: return PixelFormats.Gray8; + case 24: return PixelFormats.Bgr24; + case 32: return PixelFormats.Bgra32; + default: throw new InvalidFormatException(); + } + } + #region IDisposable Members bool _disposed = false; public void Dispose ()