variation of ABM bitmaps.

This commit is contained in:
morkt 2017-09-17 07:08:58 +04:00
parent 271ede6f07
commit 09793a08d8
2 changed files with 87 additions and 11 deletions

View File

@ -28,7 +28,7 @@ using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.IO;
using System.Windows.Media;
using GameRes.Utility;
using System.Windows.Media.Imaging;
namespace GameRes.Formats.Lilim
{
@ -155,14 +155,40 @@ namespace GameRes.Formats.Lilim
protected override ImageData GetImageData ()
{
if (2 == m_info.Mode)
switch (m_info.Mode)
{
m_bpp = 32;
case 8:
case -8:
m_input.Position = 0x36;
var palette = ImageFormat.ReadPalette (m_input.AsStream);
var bitmap_size = m_info.Width * m_info.Height;
m_output = new byte[bitmap_size];
m_input.Position = m_info.BaseOffset;
m_output = UnpackV2 (m_input);
}
else if (1 == m_info.Mode || 32 == m_info.Mode || 24 == m_info.Mode)
if (8 == m_info.Mode)
{
m_bpp = 8;
if (m_output.Length != m_input.Read (m_output, 0, m_output.Length))
throw new EndOfStreamException();
return ImageData.Create (m_info, PixelFormats.Indexed8, palette, m_output);
}
else
{
var alpha = new byte[bitmap_size];
UnpackStream8 (m_input, m_output, alpha);
m_output = ApplyAlpha (m_output, alpha, palette);
m_bpp = 32;
}
break;
case 2:
m_bpp = 32;
m_input.Position = m_info.FrameOffset;
m_output = UnpackV2 (m_input);
break;
case 1:
case 24:
case 32:
if (1 == m_info.Mode)
m_bpp = 24;
else
@ -180,9 +206,11 @@ namespace GameRes.Formats.Lilim
UnpackStream24 (m_input, m_output, total_length);
else
UnpackStream32 (m_input, m_output, total_length);
}
else
break;
default:
throw new NotImplementedException();
}
if (0 != m_info.FrameOffset)
m_output = Unpack();
PixelFormat format = 24 == m_bpp ? PixelFormats.Bgr24 : PixelFormats.Bgra32;
@ -319,5 +347,50 @@ namespace GameRes.Formats.Lilim
src += frame_w * pixel_size;
}
}
void UnpackStream8 (IBinaryStream input, byte[] output, byte[] alpha)
{
int alpha_dst = 0;
int dst = 0;
while (dst < output.Length)
{
byte rle = input.ReadUInt8();
if (0 == rle)
{
int skip = input.ReadUInt8();
dst += skip;
alpha_dst += skip;
}
else if (rle != 0xFF)
{
output[dst++] = input.ReadUInt8();
alpha[alpha_dst++] = rle;
}
else
{
int count = input.ReadUInt8();
input.Read (output, dst, count);
dst += count;
for (int i = 0; i < count; ++i)
alpha[alpha_dst++] = 0xFF;
}
}
}
byte[] ApplyAlpha (byte[] input, byte[] alpha, BitmapPalette palette)
{
var colors = palette.Colors;
var pixels = new byte[input.Length * 4];
int dst = 0;
for (int i = 0; i < input.Length; ++i)
{
var color = colors[input[i]];
pixels[dst++] = color.B;
pixels[dst++] = color.G;
pixels[dst++] = color.R;
pixels[dst++] = alpha[i];
}
return pixels;
}
}
}

View File

@ -43,8 +43,9 @@ namespace GameRes.Formats.Lilim
var header = stream.ReadHeader (0x46);
if ('B' != header[0] || 'M' != header[1])
return null;
int type = (sbyte)header[0x1C];
int type = header.ToInt16 (0x1C);
uint frame_offset;
int bpp = 24;
if (1 == type || 2 == type)
{
int count = header.ToUInt16 (0x3A);
@ -52,12 +53,14 @@ namespace GameRes.Formats.Lilim
return null;
frame_offset = header.ToUInt32 (0x42);
}
else if (32 == type || 24 == type)
else if (32 == type || 24 == type || 8 == type || -8 == type)
{
uint unpacked_size = header.ToUInt32 (2);
if (0 == unpacked_size || unpacked_size == stream.Length) // probably an ordinary bmp file
return null;
frame_offset = header.ToUInt32 (0xA);
if (8 == type)
bpp = 8;
}
else
return null;
@ -67,7 +70,7 @@ namespace GameRes.Formats.Lilim
{
Width = header.ToUInt32 (0x12),
Height = header.ToUInt32 (0x16),
BPP = 24,
BPP = bpp,
Mode = type,
BaseOffset = frame_offset,
};