(WIP): added alpha mask application.

disabled in production build.
This commit is contained in:
morkt 2017-02-01 16:39:51 +04:00
parent 97beaba189
commit 5c9d56c841

View File

@ -51,6 +51,8 @@ namespace GameRes.Formats.Will
Extensions = new string[] { "wip", "msk", "mos" };
}
public bool ApplyMask = false;
public override ImageMetaData ReadMetaData (IBinaryStream file)
{
file.Position = 4;
@ -87,27 +89,24 @@ namespace GameRes.Formats.Will
public override ImageData Read (IBinaryStream file, ImageMetaData info)
{
var meta = (WipMetaData)info;
if (meta.FrameCount > 1)
Trace.WriteLine ("Extra frames ignored", info.FileName);
file.Position = 8 + 24 * meta.FrameCount;
Color[] palette = null;
if (8 == meta.BPP)
{
var palette_data = new byte[0x400];
if (palette_data.Length != file.Read (palette_data, 0, palette_data.Length))
throw new InvalidFormatException();
palette = new Color[0x100];
for (int i = 0; i < 0x100; ++i)
{
palette[i] = Color.FromRgb (palette_data[i*4], palette_data[i*4+1], palette_data[i*4+2]);
}
}
using (var reader = new Reader (file, meta))
{
reader.Unpack();
if (24 == meta.BPP)
{
byte[] raw = reader.Data;
if (ApplyMask && !meta.FileName.EndsWith (".msk", StringComparison.InvariantCultureIgnoreCase))
{
var mask_name = Path.ChangeExtension (meta.FileName, "msk");
if (VFS.FileExists (mask_name))
{
try
{
return ApplyMaskToWipData (meta, raw, mask_name);
}
catch { /* ignore mask read errors */ }
}
}
int size = (int)meta.Width * (int)meta.Height;
byte[] pixels = new byte[size*3];
int dst = 0;
@ -122,7 +121,7 @@ namespace GameRes.Formats.Will
else if (8 == meta.BPP)
{
byte[] pixels = reader.Data;
var bmp_palette = new BitmapPalette (palette);
var bmp_palette = new BitmapPalette (reader.Palette);
return ImageData.Create (meta, PixelFormats.Indexed8, bmp_palette, pixels, (int)meta.Width);
}
else
@ -130,13 +129,46 @@ namespace GameRes.Formats.Will
}
}
ImageData ApplyMaskToWipData (ImageMetaData info, byte[] image, string mask_name)
{
using (var mask_file = VFS.OpenBinaryStream (mask_name))
{
if (mask_file.Signature != Signature)
throw new InvalidFormatException();
var mask_info = ReadMetaData (mask_file) as WipMetaData;
if (null == mask_info || 8 != mask_info.BPP
|| info.Width != mask_info.Width || info.Height != mask_info.Height)
throw new InvalidFormatException();
using (var reader = new Reader (mask_file, mask_info))
{
reader.Unpack();
var palette = reader.Palette;
int dst_stride = (int)info.Width * 4;
var pixels = new byte[dst_stride * (int)info.Height];
int plane_size = (int)info.Width * (int)info.Height;
var alpha = reader.Data;
int dst = 0;
for (int src = 0; src < plane_size; ++src)
{
pixels[dst++] = image[src];
pixels[dst++] = image[src+plane_size];
pixels[dst++] = image[src+plane_size*2];
var color = palette[alpha[src]];
pixels[dst++] = (byte)((color.B + color.G + color.R) / 3);
}
return ImageData.Create (info, PixelFormats.Bgra32, null, pixels, dst_stride);
}
}
}
internal sealed class Reader : IDisposable
{
private IBinaryStream m_input;
private uint m_length;
private byte[] m_data;
public byte[] Data { get { return m_data; } }
public byte[] Data { get { return m_data; } }
public Color[] Palette { get; private set; }
public Reader (IBinaryStream file, WipMetaData info)
{
@ -145,6 +177,9 @@ namespace GameRes.Formats.Will
int stride = (int)info.Width*4;
m_data = new byte[stride * (int)info.Height];
m_input = file;
m_input.Position = 8 + 24 * info.FrameCount;
if (8 == info.BPP)
Palette = ReadColorMap (file.AsStream, 0x100, PaletteFormat.RgbX);
}
private byte[] m_window = new byte[0x1000];