(BgiFormat): restore scrambled pixels.

This commit is contained in:
morkt 2018-08-31 04:32:13 +04:00
parent 36544eddd0
commit 75d7d3307d

View File

@ -34,6 +34,11 @@ using System.Threading.Tasks;
namespace GameRes.Formats.BGI namespace GameRes.Formats.BGI
{ {
internal class BgiMetaData : ImageMetaData
{
public bool IsScrambled;
}
[Export(typeof(ImageFormat))] [Export(typeof(ImageFormat))]
public class BgiFormat : ImageFormat public class BgiFormat : ImageFormat
{ {
@ -43,7 +48,7 @@ namespace GameRes.Formats.BGI
public BgiFormat () public BgiFormat ()
{ {
Extensions = new string[] { "", "bgi" }; Extensions = new string[] { "", "bgi", "_bg" };
} }
public override void Write (Stream file, ImageData image) public override void Write (Stream file, ImageData image)
@ -57,21 +62,26 @@ namespace GameRes.Formats.BGI
int height = stream.ReadInt16(); int height = stream.ReadInt16();
if (width <= 0 || height <= 0) if (width <= 0 || height <= 0)
return null; return null;
int bpp = stream.ReadInt32(); int bpp = stream.ReadInt16();
if (24 != bpp && 32 != bpp && 8 != bpp) if (24 != bpp && 32 != bpp && 8 != bpp)
return null; return null;
int flag = stream.ReadInt16();
if (flag != 1 && flag != 0)
return null;
if (0 != stream.ReadInt64()) if (0 != stream.ReadInt64())
return null; return null;
return new ImageMetaData return new BgiMetaData
{ {
Width = (uint)width, Width = (uint)width,
Height = (uint)height, Height = (uint)height,
BPP = bpp, BPP = bpp,
IsScrambled = flag != 0,
}; };
} }
public override ImageData Read (IBinaryStream stream, ImageMetaData info) public override ImageData Read (IBinaryStream stream, ImageMetaData info)
{ {
var meta = (BgiMetaData)info;
PixelFormat format; PixelFormat format;
if (24 == info.BPP) if (24 == info.BPP)
format = PixelFormats.Bgr24; format = PixelFormats.Bgr24;
@ -79,14 +89,51 @@ namespace GameRes.Formats.BGI
format = PixelFormats.Bgra32; format = PixelFormats.Bgra32;
else else
format = PixelFormats.Gray8; format = PixelFormats.Gray8;
int stride = (int)info.Width*((info.BPP+7)/8); int stride = (int)info.Width * ((info.BPP+7)/8);
var pixels = new byte[stride*info.Height]; var pixels = new byte[stride * (int)info.Height];
stream.Position = 0x10; stream.Position = 0x10;
int read = stream.Read (pixels, 0, pixels.Length); if (!meta.IsScrambled)
if (read != pixels.Length) {
throw new InvalidFormatException(); 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); 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 internal class CbgMetaData : ImageMetaData