From 75d7d3307d2d7525b3212acf643f3d6627cb8edb Mon Sep 17 00:00:00 2001 From: morkt Date: Fri, 31 Aug 2018 04:32:13 +0400 Subject: [PATCH] (BgiFormat): restore scrambled pixels. --- ArcFormats/Ethornell/ImageBGI.cs | 63 ++++++++++++++++++++++++++++---- 1 file changed, 55 insertions(+), 8 deletions(-) diff --git a/ArcFormats/Ethornell/ImageBGI.cs b/ArcFormats/Ethornell/ImageBGI.cs index 99edac15..b2630569 100644 --- a/ArcFormats/Ethornell/ImageBGI.cs +++ b/ArcFormats/Ethornell/ImageBGI.cs @@ -34,6 +34,11 @@ using System.Threading.Tasks; namespace GameRes.Formats.BGI { + internal class BgiMetaData : ImageMetaData + { + public bool IsScrambled; + } + [Export(typeof(ImageFormat))] public class BgiFormat : ImageFormat { @@ -43,7 +48,7 @@ namespace GameRes.Formats.BGI public BgiFormat () { - Extensions = new string[] { "", "bgi" }; + Extensions = new string[] { "", "bgi", "_bg" }; } public override void Write (Stream file, ImageData image) @@ -57,21 +62,26 @@ namespace GameRes.Formats.BGI int height = stream.ReadInt16(); if (width <= 0 || height <= 0) return null; - int bpp = stream.ReadInt32(); + int bpp = stream.ReadInt16(); if (24 != bpp && 32 != bpp && 8 != bpp) return null; + int flag = stream.ReadInt16(); + if (flag != 1 && flag != 0) + return null; if (0 != stream.ReadInt64()) return null; - return new ImageMetaData + return new BgiMetaData { Width = (uint)width, Height = (uint)height, BPP = bpp, + IsScrambled = flag != 0, }; } public override ImageData Read (IBinaryStream stream, ImageMetaData info) { + var meta = (BgiMetaData)info; PixelFormat format; if (24 == info.BPP) format = PixelFormats.Bgr24; @@ -79,14 +89,51 @@ namespace GameRes.Formats.BGI format = PixelFormats.Bgra32; else format = PixelFormats.Gray8; - int stride = (int)info.Width*((info.BPP+7)/8); - var pixels = new byte[stride*info.Height]; + int stride = (int)info.Width * ((info.BPP+7)/8); + var pixels = new byte[stride * (int)info.Height]; stream.Position = 0x10; - int read = stream.Read (pixels, 0, pixels.Length); - if (read != pixels.Length) - throw new InvalidFormatException(); + if (!meta.IsScrambled) + { + int read = stream.Read (pixels, 0, pixels.Length); + if (read != pixels.Length) + throw new InvalidFormatException(); + } + else + { + RestorePixels (stream, pixels, meta); + } return ImageData.Create (info, format, null, pixels, stride); } + + void RestorePixels (IBinaryStream input, byte[] output, BgiMetaData info) + { + int bpp = info.BPP / 8; + int stride = (int)info.Width * bpp; + for (int i = 0; i < bpp; ++i) + { + int dst = i; + byte incr = 0; + for (int h = (int)info.Height; h > 0; --h) + { + for (uint w = 0; w < info.Width; ++w) + { + incr += input.ReadUInt8(); + output[dst] = incr; + dst += bpp; + } + if (--h == 0) + break; + dst += stride; + int pos = dst; + for (uint w = 0; w < info.Width; ++w) + { + pos -= bpp; + incr += input.ReadUInt8(); + output[pos] = incr; + } + } + } + } } internal class CbgMetaData : ImageMetaData