(LimFormat): refined 16bpp images support.

This commit is contained in:
morkt 2016-04-25 18:00:02 +04:00
parent 3711e28d79
commit 2c82b05afa

View File

@ -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
{
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,25 +223,24 @@ namespace GameRes.Formats.Liar
}
}
}
if (m_input.BaseStream.Position < m_input.BaseStream.Length)
}
void ApplyAlpha (byte[] alpha)
{
m_output = null;
UnpackChannel (3);
var pixels = new byte[m_width*m_height*4];
int alpha_src = 0;
dst = 0;
int 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++];
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];
}