diff --git a/ArcFormats/Liar/ImageLIM.cs b/ArcFormats/Liar/ImageLIM.cs index 8b222876..65f077f1 100644 --- a/ArcFormats/Liar/ImageLIM.cs +++ b/ArcFormats/Liar/ImageLIM.cs @@ -31,6 +31,11 @@ using GameRes.Utility; namespace GameRes.Formats.Liar { + internal class LimMetaData : ImageMetaData + { + public int Flags; + } + [Export(typeof(ImageFormat))] public class LimFormat : ImageFormat { @@ -42,14 +47,13 @@ namespace GameRes.Formats.Liar { if (0x4C != stream.ReadByte() || 0x4D != stream.ReadByte()) return null; - int flag = stream.ReadByte() & 0xF; - if (flag != 2 && flag != 3) - return null; - stream.ReadByte(); using (var file = new ArcView.Reader (stream)) { + int flag = file.ReadUInt16(); + if ((flag & 0xF) != 2 && (flag & 0xF) != 3) + return null; int bpp = 0x10 == file.ReadUInt16() ? 16 : 32; - var meta = new ImageMetaData { BPP = bpp }; + var meta = new LimMetaData { BPP = bpp, Flags = flag }; file.ReadUInt16(); meta.Width = file.ReadUInt32(); meta.Height = file.ReadUInt32(); @@ -59,8 +63,7 @@ namespace GameRes.Formats.Liar public override ImageData Read (Stream file, ImageMetaData info) { - file.Position = 0x10; - using (var reader = new Reader (file, info)) + using (var reader = new Reader (file, (LimMetaData)info)) { reader.Unpack(); return ImageData.Create (info, reader.Format, null, reader.Data); @@ -81,16 +84,18 @@ namespace GameRes.Formats.Liar int m_width; int m_height; int m_bpp; + int m_flags; public byte[] Data { get { return m_image; } } public PixelFormat Format { get; private set; } - public Reader (Stream file, ImageMetaData info) + public Reader (Stream file, LimMetaData info) { m_input = new ArcView.Reader (file); m_width = (int)info.Width; m_height = (int)info.Height; m_bpp = info.BPP; + m_flags = info.Flags; if (32 == m_bpp) Format = PixelFormats.Bgra32; else if (16 == m_bpp) @@ -106,10 +111,32 @@ namespace GameRes.Formats.Liar public void Unpack () { + m_input.BaseStream.Position = 0x10; if (32 == m_bpp) + { Unpack32bpp(); + } else - Unpack16bpp(); + { + if (0 != (m_flags & 0x10)) + { + if (0 != (m_flags & 0xE0)) + Unpack16bpp(); + else + m_input.Read (m_image, 0, m_image.Length); + } + if (0 != (m_flags & 0x100)) + { + if (0 != (m_flags & 0xE00)) + { + m_output = null; + UnpackChannel (3); + } + else + m_output = m_input.ReadBytes (m_width * m_height); + ApplyAlpha (m_output); + } + } } void Unpack32bpp () @@ -196,24 +223,23 @@ namespace GameRes.Formats.Liar } } } - if (m_input.BaseStream.Position < m_input.BaseStream.Length) + } + + void ApplyAlpha (byte[] alpha) + { + var pixels = new byte[m_width*m_height*4]; + int alpha_src = 0; + int dst = 0; + for (int i = 0; i < m_image.Length; i += 2) { - m_output = null; - UnpackChannel (3); - var pixels = new byte[m_width*m_height*4]; - int alpha_src = 0; - dst = 0; - for (int i = 0; i < m_image.Length; i += 2) - { - int color = LittleEndian.ToUInt16 (m_image, i); - pixels[dst++] = (byte)((color & 0x001F) * 0xFF / 0x1F); - pixels[dst++] = (byte)((color & 0x07E0) * 0xFF / 0x7E0); - pixels[dst++] = (byte)((color & 0xF800) * 0xFF / 0xF800); - pixels[dst++] = (byte)~m_output[alpha_src++]; - } - m_image = pixels; - Format = PixelFormats.Bgra32; + int color = LittleEndian.ToUInt16 (m_image, i); + pixels[dst++] = (byte)((color & 0x001F) * 0xFF / 0x1F); + pixels[dst++] = (byte)((color & 0x07E0) * 0xFF / 0x7E0); + pixels[dst++] = (byte)((color & 0xF800) * 0xFF / 0xF800); + pixels[dst++] = (byte)~alpha[alpha_src++]; } + m_image = pixels; + Format = PixelFormats.Bgra32; } void UnpackChannel (int card) @@ -267,7 +293,7 @@ namespace GameRes.Formats.Liar count += 2; for (int i = 0; i < count; i++) { - if (dst + 1 >= m_output.Length) + if (dst >= m_output.Length) return; m_output[dst++] = m_index[index]; }