mirror of
https://github.com/crskycode/GARbro.git
synced 2024-12-12 22:36:58 +08:00
(WIP): added alpha mask application.
disabled in production build.
This commit is contained in:
parent
97beaba189
commit
5c9d56c841
@ -51,6 +51,8 @@ namespace GameRes.Formats.Will
|
|||||||
Extensions = new string[] { "wip", "msk", "mos" };
|
Extensions = new string[] { "wip", "msk", "mos" };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool ApplyMask = false;
|
||||||
|
|
||||||
public override ImageMetaData ReadMetaData (IBinaryStream file)
|
public override ImageMetaData ReadMetaData (IBinaryStream file)
|
||||||
{
|
{
|
||||||
file.Position = 4;
|
file.Position = 4;
|
||||||
@ -87,27 +89,24 @@ namespace GameRes.Formats.Will
|
|||||||
public override ImageData Read (IBinaryStream file, ImageMetaData info)
|
public override ImageData Read (IBinaryStream file, ImageMetaData info)
|
||||||
{
|
{
|
||||||
var meta = (WipMetaData)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))
|
using (var reader = new Reader (file, meta))
|
||||||
{
|
{
|
||||||
reader.Unpack();
|
reader.Unpack();
|
||||||
if (24 == meta.BPP)
|
if (24 == meta.BPP)
|
||||||
{
|
{
|
||||||
byte[] raw = reader.Data;
|
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;
|
int size = (int)meta.Width * (int)meta.Height;
|
||||||
byte[] pixels = new byte[size*3];
|
byte[] pixels = new byte[size*3];
|
||||||
int dst = 0;
|
int dst = 0;
|
||||||
@ -122,7 +121,7 @@ namespace GameRes.Formats.Will
|
|||||||
else if (8 == meta.BPP)
|
else if (8 == meta.BPP)
|
||||||
{
|
{
|
||||||
byte[] pixels = reader.Data;
|
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);
|
return ImageData.Create (meta, PixelFormats.Indexed8, bmp_palette, pixels, (int)meta.Width);
|
||||||
}
|
}
|
||||||
else
|
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
|
internal sealed class Reader : IDisposable
|
||||||
{
|
{
|
||||||
private IBinaryStream m_input;
|
private IBinaryStream m_input;
|
||||||
private uint m_length;
|
private uint m_length;
|
||||||
private byte[] m_data;
|
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)
|
public Reader (IBinaryStream file, WipMetaData info)
|
||||||
{
|
{
|
||||||
@ -145,6 +177,9 @@ namespace GameRes.Formats.Will
|
|||||||
int stride = (int)info.Width*4;
|
int stride = (int)info.Width*4;
|
||||||
m_data = new byte[stride * (int)info.Height];
|
m_data = new byte[stride * (int)info.Height];
|
||||||
m_input = file;
|
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];
|
private byte[] m_window = new byte[0x1000];
|
||||||
|
Loading…
Reference in New Issue
Block a user