(PDT): support 'PDT11' images.

This commit is contained in:
morkt 2017-12-29 01:14:46 +04:00
parent 186444f957
commit 12fa5adb31

View File

@ -34,6 +34,7 @@ namespace GameRes.Formats.RealLive
{ {
internal class PdtMetaData : ImageMetaData internal class PdtMetaData : ImageMetaData
{ {
public int Version;
public uint AlphaOffset; public uint AlphaOffset;
} }
@ -47,13 +48,15 @@ namespace GameRes.Formats.RealLive
public override ImageMetaData ReadMetaData (IBinaryStream stream) public override ImageMetaData ReadMetaData (IBinaryStream stream)
{ {
var header = stream.ReadHeader (32); var header = stream.ReadHeader (32);
if (!header.AsciiEqual ("PDT10\0")) int version = header[4] - '0';
if (version < 0 || version > 1)
return null; return null;
return new PdtMetaData return new PdtMetaData
{ {
Width = header.ToUInt32 (0x0C), Width = header.ToUInt32 (0x0C),
Height = header.ToUInt32 (0x10), Height = header.ToUInt32 (0x10),
BPP = 32, BPP = 32,
Version = version,
AlphaOffset = header.ToUInt32 (0x1C), AlphaOffset = header.ToUInt32 (0x1C),
}; };
} }
@ -87,16 +90,27 @@ namespace GameRes.Formats.RealLive
{ {
m_input = input; m_input = input;
m_info = info; m_info = info;
m_output = new byte[m_info.Width * m_info.Height * 4]; if (0 != m_info.AlphaOffset)
if (0 == m_info.AlphaOffset)
Format = PixelFormats.Bgr32;
else
Format = PixelFormats.Bgra32; Format = PixelFormats.Bgra32;
else if (1 == m_info.Version)
Format = PixelFormats.Indexed8;
else
Format = PixelFormats.Bgr32;
m_output = new byte[m_info.Width * m_info.Height * Format.BitsPerPixel / 8];
} }
public void Unpack () public void Unpack ()
{ {
m_input.Position = 0x20; m_input.Position = 0x20;
if (0 == m_info.Version)
UnpackV0();
else
UnpackV1();
}
void UnpackV0 ()
{
Unpack24(); Unpack24();
if (0 != m_info.AlphaOffset) if (0 != m_info.AlphaOffset)
{ {
@ -110,6 +124,21 @@ namespace GameRes.Formats.RealLive
} }
} }
void UnpackV1 ()
{
Palette = ImageFormat.ReadPalette (m_input.AsStream);
var offsets = new int[16];
for (int i = 0; i < offsets.Length; ++i)
offsets[i] = m_input.ReadInt32();
LzUnpack (offsets);
if (0 != m_info.AlphaOffset)
{
m_input.Position = m_info.AlphaOffset;
var alpha = Unpack8();
}
}
void Unpack24 () void Unpack24 ()
{ {
int dst = 0; int dst = 0;
@ -168,6 +197,43 @@ namespace GameRes.Formats.RealLive
return output; return output;
} }
void LzUnpack (int[] offsets)
{
int dst = 0;
int bits = 0;
int mask = 0;
while (dst < m_output.Length)
{
mask >>= 1;
if (0 == mask)
{
bits = m_input.ReadUInt8();
mask = 0x80;
}
if (0 != (bits & mask))
{
m_output[dst++] = m_input.ReadUInt8();
}
else
{
int offset = m_input.ReadUInt8();
int count = Math.Min (2 + (offset >> 4), m_output.Length - dst);
offset = offsets[offset & 0xF];
if (dst < offset)
{
int gap = Math.Min (offset - dst, count);
dst += gap;
count -= gap;
}
if (count > 0)
{
Binary.CopyOverlapped (m_output, dst-offset, dst, count);
dst += count;
}
}
}
}
#region IDisposable Members #region IDisposable Members
public void Dispose () public void Dispose ()
{ {