mirror of
https://github.com/crskycode/GARbro.git
synced 2024-11-24 06:05:35 +08:00
(DwqFormat): implemented BMP+MASK format.
read BMP images manually as they're not really BMPs suitable for BmpBitmapDecoder.
This commit is contained in:
parent
3a96fd0efd
commit
f0b327594b
@ -78,7 +78,13 @@ namespace GameRes.Formats.BlackCyc
|
|||||||
|
|
||||||
public DwqFormat ()
|
public DwqFormat ()
|
||||||
{
|
{
|
||||||
Signatures = new uint[] { 0x4745504A, 0x20504D42, 0x20474E50, 0x4B434150 };
|
Signatures = new uint[] {
|
||||||
|
0x4745504A, // JPEG
|
||||||
|
0x20504D42, // BMP
|
||||||
|
0x20474E50, // PNG
|
||||||
|
0x4B434150, // PACKBMP
|
||||||
|
0x2B504D42, // BMP+MASK
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
static ImageFormat GetFormat (string tag)
|
static ImageFormat GetFormat (string tag)
|
||||||
@ -94,6 +100,24 @@ namespace GameRes.Formats.BlackCyc
|
|||||||
var header = ResourceHeader.Read (stream);
|
var header = ResourceHeader.Read (stream);
|
||||||
if (null == header)
|
if (null == header)
|
||||||
return null;
|
return null;
|
||||||
|
int packed_size;
|
||||||
|
switch (header.PackType)
|
||||||
|
{
|
||||||
|
case 0: // BMP
|
||||||
|
case 5: // JPEG
|
||||||
|
case 8: // PNG
|
||||||
|
packed_size = (int)(stream.Length-0x40);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2: // BMP+MASK
|
||||||
|
case 3: // PACKBMP+MASK
|
||||||
|
case 7: // JPEG+MASK
|
||||||
|
packed_size = LittleEndian.ToInt32 (header.Bytes, 0x20);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default: // unknown format
|
||||||
|
return null;
|
||||||
|
}
|
||||||
return new DwqMetaData
|
return new DwqMetaData
|
||||||
{
|
{
|
||||||
Width = LittleEndian.ToUInt32 (header.Bytes, 0x24),
|
Width = LittleEndian.ToUInt32 (header.Bytes, 0x24),
|
||||||
@ -113,44 +137,39 @@ namespace GameRes.Formats.BlackCyc
|
|||||||
throw new ArgumentException ("DwqFormat.Read should be supplied with DwqMetaData", "info");
|
throw new ArgumentException ("DwqFormat.Read should be supplied with DwqMetaData", "info");
|
||||||
|
|
||||||
BitmapSource bitmap = null;
|
BitmapSource bitmap = null;
|
||||||
|
using (var input = new StreamRegion (stream, 0x40, meta.PackedSize, true))
|
||||||
|
{
|
||||||
switch (meta.PackType)
|
switch (meta.PackType)
|
||||||
{
|
{
|
||||||
case 5: // JPEG
|
case 5: // JPEG
|
||||||
using (var jpeg = new StreamRegion (stream, 0x40, stream.Length-0x40, true))
|
return JpegFormat.Value.Read (input, info);
|
||||||
return JpegFormat.Value.Read (jpeg, info);
|
|
||||||
|
|
||||||
case 8: // PNG
|
case 8: // PNG
|
||||||
using (var png = new StreamRegion (stream, 0x40, stream.Length-0x40, true))
|
return PngFormat.Value.Read (input, info);
|
||||||
return PngFormat.Value.Read (png, info);
|
|
||||||
|
|
||||||
case 0: // BMP
|
case 0: // BMP
|
||||||
using (var bmp = new StreamRegion (stream, 0x40, stream.Length-0x40, true))
|
case 2: // BMP+MASK
|
||||||
{
|
bitmap = ReadFuckedUpBmpImage (input, info);
|
||||||
var decoder = new BmpBitmapDecoder (bmp, BitmapCreateOptions.None, BitmapCacheOption.OnLoad);
|
|
||||||
// non-conforming BMP, flip image vertically
|
|
||||||
bitmap = new TransformedBitmap (decoder.Frames[0], new ScaleTransform { ScaleY = -1 });
|
|
||||||
return new ImageData (bitmap, info);
|
|
||||||
}
|
|
||||||
|
|
||||||
case 7: // JPEG+MASK
|
|
||||||
using (var jpeg = new StreamRegion (stream, 0x40, meta.PackedSize, true))
|
|
||||||
{
|
|
||||||
var decoder = new JpegBitmapDecoder (jpeg, BitmapCreateOptions.None, BitmapCacheOption.OnLoad);
|
|
||||||
bitmap = decoder.Frames[0];
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 3: // PACKBMP+MASK
|
case 7: // JPEG+MASK
|
||||||
using (var bmp = new StreamRegion (stream, 0x40, meta.PackedSize, true))
|
|
||||||
{
|
{
|
||||||
var reader = new DwqBmpReader (bmp, meta);
|
var decoder = new JpegBitmapDecoder (input, BitmapCreateOptions.None, BitmapCacheOption.OnLoad);
|
||||||
|
bitmap = decoder.Frames[0];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 3: // PACKBMP+MASK
|
||||||
|
{
|
||||||
|
var reader = new DwqBmpReader (input, meta);
|
||||||
reader.Unpack();
|
reader.Unpack();
|
||||||
bitmap = BitmapSource.Create ((int)info.Width, (int)info.Height,
|
bitmap = BitmapSource.Create ((int)info.Width, (int)info.Height,
|
||||||
ImageData.DefaultDpiX, ImageData.DefaultDpiY,
|
ImageData.DefaultDpiX, ImageData.DefaultDpiY,
|
||||||
reader.Format, reader.Palette, reader.Data, reader.Stride);
|
reader.Format, reader.Palette, reader.Data, reader.Stride);
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
if (null == bitmap)
|
if (null == bitmap)
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
if (meta.AType)
|
if (meta.AType)
|
||||||
@ -170,7 +189,7 @@ namespace GameRes.Formats.BlackCyc
|
|||||||
int A = (color.R + color.G + color.B) / 3;
|
int A = (color.R + color.G + color.B) / 3;
|
||||||
alpha[i] = (byte)A;
|
alpha[i] = (byte)A;
|
||||||
}
|
}
|
||||||
bitmap = ApplyAlphaChannel (bitmap, reader.Data);
|
bitmap = ApplyAlphaChannel (bitmap, alpha);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -200,6 +219,39 @@ namespace GameRes.Formats.BlackCyc
|
|||||||
ImageData.DefaultDpiX, ImageData.DefaultDpiY,
|
ImageData.DefaultDpiX, ImageData.DefaultDpiY,
|
||||||
PixelFormats.Bgra32, null, pixels, stride);
|
PixelFormats.Bgra32, null, pixels, stride);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private BitmapSource ReadFuckedUpBmpImage (Stream file, ImageMetaData info)
|
||||||
|
{
|
||||||
|
var header = new byte[0x36];
|
||||||
|
if (header.Length != file.Read (header, 0, header.Length))
|
||||||
|
throw new InvalidFormatException();
|
||||||
|
int bpp = LittleEndian.ToUInt16 (header, 0x1c);
|
||||||
|
if (bpp != 24 && bpp != 32)
|
||||||
|
{
|
||||||
|
file.Position = 0;
|
||||||
|
var decoder = new BmpBitmapDecoder (file, BitmapCreateOptions.None, BitmapCacheOption.OnLoad);
|
||||||
|
// non-conforming BMP, flip image vertically
|
||||||
|
return new TransformedBitmap (decoder.Frames[0], new ScaleTransform { ScaleY = -1 });
|
||||||
|
}
|
||||||
|
int pixel_size = bpp / 8;
|
||||||
|
int stride = ((int)info.Width * pixel_size + 3) & ~3;
|
||||||
|
var pixels = new byte[stride * info.Height];
|
||||||
|
if (pixels.Length != file.Read (pixels, 0, pixels.Length))
|
||||||
|
throw new EndOfStreamException();
|
||||||
|
for (int row = 0; row < pixels.Length; row += stride)
|
||||||
|
{
|
||||||
|
for (int i = 2; i < stride; i += pixel_size)
|
||||||
|
{
|
||||||
|
var t = pixels[row+i];
|
||||||
|
pixels[row+i] = pixels[row+i-2];
|
||||||
|
pixels[row+i-2] = t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PixelFormat format = 32 == bpp ? PixelFormats.Bgr32 : PixelFormats.Bgr24;
|
||||||
|
return BitmapSource.Create ((int)info.Width, (int)info.Height,
|
||||||
|
ImageData.DefaultDpiX, ImageData.DefaultDpiY,
|
||||||
|
format, null, pixels, stride);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class DwqBmpReader
|
internal class DwqBmpReader
|
||||||
|
Loading…
Reference in New Issue
Block a user