mirror of
https://github.com/crskycode/GARbro.git
synced 2026-07-08 01:30:18 +08:00
DRG images implementation updates.
support for 8-bit images; support for alpha-channel in GGA0 images.
This commit is contained in:
@@ -2,7 +2,7 @@
|
|||||||
//! \date Fri Aug 22 05:58:40 2014
|
//! \date Fri Aug 22 05:58:40 2014
|
||||||
//! \brief Digital Romance System image format implementation.
|
//! \brief Digital Romance System image format implementation.
|
||||||
//
|
//
|
||||||
// Copyright (C) 2014 by morkt
|
// Copyright (C) 2014-2015 by morkt
|
||||||
//
|
//
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
// of this software and associated documentation files (the "Software"), to
|
// of this software and associated documentation files (the "Software"), to
|
||||||
@@ -45,7 +45,7 @@ namespace GameRes.Formats.DRS
|
|||||||
public DrgFormat ()
|
public DrgFormat ()
|
||||||
{
|
{
|
||||||
Extensions = new string[] { "drg", "ggd" };
|
Extensions = new string[] { "drg", "ggd" };
|
||||||
Signatures = new uint[] { ~0x4c4c5546u, ~0x45555254u, ~0x48474948u, ~0x47363532u };
|
Signatures = new uint[] { ~0x4c4c5546u, ~0x45555254u, ~0x48474948u };
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Write (Stream file, ImageData image)
|
public override void Write (Stream file, ImageData image)
|
||||||
@@ -65,22 +65,12 @@ namespace GameRes.Formats.DRS
|
|||||||
case 0x4c4c5546: /* fall through */
|
case 0x4c4c5546: /* fall through */
|
||||||
case 0x45555254: bpp = 24; break;
|
case 0x45555254: bpp = 24; break;
|
||||||
case 0x48474948: bpp = 16; break;
|
case 0x48474948: bpp = 16; break;
|
||||||
case 0x47363532: bpp = 8; break;
|
|
||||||
default: return null;
|
default: return null;
|
||||||
}
|
}
|
||||||
using (var input = new BinaryReader (stream, Encoding.ASCII, true))
|
using (var input = new BinaryReader (stream, Encoding.ASCII, true))
|
||||||
{
|
{
|
||||||
uint width, height;
|
uint width = input.ReadUInt16();
|
||||||
if (8 != bpp)
|
uint height = input.ReadUInt16();
|
||||||
{
|
|
||||||
width = input.ReadUInt16();
|
|
||||||
height = input.ReadUInt16();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
width = input.ReadUInt32();
|
|
||||||
height = input.ReadUInt32();
|
|
||||||
}
|
|
||||||
return new ImageMetaData {
|
return new ImageMetaData {
|
||||||
Width = width,
|
Width = width,
|
||||||
Height = height,
|
Height = height,
|
||||||
@@ -90,38 +80,6 @@ namespace GameRes.Formats.DRS
|
|||||||
}
|
}
|
||||||
|
|
||||||
public override ImageData Read (Stream file, ImageMetaData info)
|
public override ImageData Read (Stream file, ImageMetaData info)
|
||||||
{
|
|
||||||
BitmapSource bitmap;
|
|
||||||
if (8 == info.BPP)
|
|
||||||
bitmap = ReadIndexed (file, info);
|
|
||||||
else
|
|
||||||
bitmap = ReadTrue (file, info);
|
|
||||||
bitmap.Freeze();
|
|
||||||
return new ImageData (bitmap, info);
|
|
||||||
}
|
|
||||||
|
|
||||||
private BitmapSource ReadIndexed (Stream file, ImageMetaData info)
|
|
||||||
{
|
|
||||||
file.Position = 44;
|
|
||||||
PixelFormat format = PixelFormats.Indexed8;
|
|
||||||
var palette_data = new byte[0x400];
|
|
||||||
if (palette_data.Length != file.Read (palette_data, 0, palette_data.Length))
|
|
||||||
throw new InvalidFormatException();
|
|
||||||
var palette = new Color[256];
|
|
||||||
for (int i = 0; i < 256; ++i)
|
|
||||||
{
|
|
||||||
palette[i] = Color.FromRgb (palette_data[i*4+2], palette_data[i*4+1], palette_data[i*4]);
|
|
||||||
}
|
|
||||||
var bitmap_palette = new BitmapPalette (palette);
|
|
||||||
file.Position += 4;
|
|
||||||
int stride = (int)info.Width*((info.BPP+7)/8);
|
|
||||||
|
|
||||||
/* indexed GGD image is a LZSS-compressed stream */
|
|
||||||
/* currently not implemented */
|
|
||||||
throw new NotImplementedException ("DrgFormat.ReadIndexed not implemented");
|
|
||||||
}
|
|
||||||
|
|
||||||
private BitmapSource ReadTrue (Stream file, ImageMetaData info)
|
|
||||||
{
|
{
|
||||||
file.Position = 8;
|
file.Position = 8;
|
||||||
PixelFormat format;
|
PixelFormat format;
|
||||||
@@ -134,8 +92,10 @@ namespace GameRes.Formats.DRS
|
|||||||
var pixel_data = DecodeStream (file, stride*(int)info.Height);
|
var pixel_data = DecodeStream (file, stride*(int)info.Height);
|
||||||
if (null == pixel_data)
|
if (null == pixel_data)
|
||||||
throw new InvalidFormatException();
|
throw new InvalidFormatException();
|
||||||
return BitmapSource.Create ((int)info.Width, (int)info.Height, 96, 96,
|
var bitmap = BitmapSource.Create ((int)info.Width, (int)info.Height, 96, 96,
|
||||||
format, null, pixel_data, stride);
|
format, null, pixel_data, stride);
|
||||||
|
bitmap.Freeze();
|
||||||
|
return new ImageData (bitmap, info);
|
||||||
}
|
}
|
||||||
|
|
||||||
byte[] DecodeStream (Stream input, int pixel_count)
|
byte[] DecodeStream (Stream input, int pixel_count)
|
||||||
@@ -458,6 +418,76 @@ namespace GameRes.Formats.DRS
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal class GgdMetaData : ImageMetaData
|
||||||
|
{
|
||||||
|
public uint HeaderSize;
|
||||||
|
public uint BitmapSize;
|
||||||
|
public bool Flipped;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Export(typeof(ImageFormat))]
|
||||||
|
public class DrgIndexedFormat : ImageFormat
|
||||||
|
{
|
||||||
|
public override string Tag { get { return "DRG"; } }
|
||||||
|
public override string Description { get { return "Digital Romance System indexed image format"; } }
|
||||||
|
public override uint Signature { get { return ~0x47363532u; } } // '256G'
|
||||||
|
|
||||||
|
public DrgIndexedFormat ()
|
||||||
|
{
|
||||||
|
Extensions = new string[] { "ggd" };
|
||||||
|
}
|
||||||
|
|
||||||
|
public override ImageMetaData ReadMetaData (Stream stream)
|
||||||
|
{
|
||||||
|
using (var input = new ArcView.Reader (stream))
|
||||||
|
{
|
||||||
|
input.ReadUInt32();
|
||||||
|
var info = new GgdMetaData { BPP = 8 };
|
||||||
|
info.HeaderSize = input.ReadUInt32();
|
||||||
|
info.Width = input.ReadUInt32();
|
||||||
|
int height = input.ReadInt32();
|
||||||
|
if (height < 0)
|
||||||
|
{
|
||||||
|
height = -height;
|
||||||
|
info.Flipped = true;
|
||||||
|
}
|
||||||
|
info.Height = (uint)height;
|
||||||
|
input.ReadInt64();
|
||||||
|
info.BitmapSize = input.ReadUInt32();
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override ImageData Read (Stream file, ImageMetaData info)
|
||||||
|
{
|
||||||
|
var meta = info as GgdMetaData;
|
||||||
|
if (null == meta)
|
||||||
|
throw new ArgumentException ("DrgIndexedFormat.Read should be supplied with GgdMetaData", "info");
|
||||||
|
file.Position = meta.HeaderSize + 4;
|
||||||
|
var palette_data = new byte[0x400];
|
||||||
|
if (palette_data.Length != file.Read (palette_data, 0, palette_data.Length))
|
||||||
|
throw new InvalidFormatException();
|
||||||
|
var colors = new Color[256];
|
||||||
|
for (int i = 0; i < 256; ++i)
|
||||||
|
{
|
||||||
|
colors[i] = Color.FromRgb (palette_data[i*4+2], palette_data[i*4+1], palette_data[i*4]);
|
||||||
|
}
|
||||||
|
file.Seek (4, SeekOrigin.Current);
|
||||||
|
int input_size = (int)(file.Length - file.Position);
|
||||||
|
using (var reader = new LzssReader (file, input_size, (int)meta.BitmapSize))
|
||||||
|
{
|
||||||
|
reader.Unpack();
|
||||||
|
var palette = new BitmapPalette (colors);
|
||||||
|
return ImageData.Create (info, PixelFormats.Indexed8, palette, reader.Data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Write (Stream file, ImageData image)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException ("DrgIndexedFormat.Write not implemented");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[Export(typeof(ImageFormat))]
|
[Export(typeof(ImageFormat))]
|
||||||
public class GgaFormat : ImageFormat
|
public class GgaFormat : ImageFormat
|
||||||
{
|
{
|
||||||
@@ -465,8 +495,14 @@ namespace GameRes.Formats.DRS
|
|||||||
public override string Description { get { return "IKURA GDL image format"; } }
|
public override string Description { get { return "IKURA GDL image format"; } }
|
||||||
public override uint Signature { get { return 0x30414747u; } } // 'GGA0'
|
public override uint Signature { get { return 0x30414747u; } } // 'GGA0'
|
||||||
|
|
||||||
|
public GgaFormat ()
|
||||||
|
{
|
||||||
|
Extensions = new string[] { "gg1", "gg2", "gg3" };
|
||||||
|
}
|
||||||
|
|
||||||
internal class GgaMetaData : ImageMetaData
|
internal class GgaMetaData : ImageMetaData
|
||||||
{
|
{
|
||||||
|
public uint Flags;
|
||||||
public uint HeaderSize;
|
public uint HeaderSize;
|
||||||
public uint CompSize;
|
public uint CompSize;
|
||||||
}
|
}
|
||||||
@@ -486,7 +522,8 @@ namespace GameRes.Formats.DRS
|
|||||||
return new GgaMetaData {
|
return new GgaMetaData {
|
||||||
Width = LittleEndian.ToUInt16 (header, 8),
|
Width = LittleEndian.ToUInt16 (header, 8),
|
||||||
Height = LittleEndian.ToUInt16 (header, 10),
|
Height = LittleEndian.ToUInt16 (header, 10),
|
||||||
BPP = 32,
|
BPP = header[14],
|
||||||
|
Flags = header[15],
|
||||||
HeaderSize = LittleEndian.ToUInt32 (header, 16),
|
HeaderSize = LittleEndian.ToUInt32 (header, 16),
|
||||||
CompSize = LittleEndian.ToUInt32 (header, 20)
|
CompSize = LittleEndian.ToUInt32 (header, 20)
|
||||||
};
|
};
|
||||||
@@ -499,10 +536,8 @@ namespace GameRes.Formats.DRS
|
|||||||
throw new ArgumentException ("GgaFormat.Read should be supplied with GgaMetaData", "info");
|
throw new ArgumentException ("GgaFormat.Read should be supplied with GgaMetaData", "info");
|
||||||
file.Position = meta.HeaderSize;
|
file.Position = meta.HeaderSize;
|
||||||
var pixel_data = DecodeStream (file, meta);
|
var pixel_data = DecodeStream (file, meta);
|
||||||
var bitmap = BitmapSource.Create ((int)info.Width, (int)info.Height, 96, 96,
|
PixelFormat format = 0 == (meta.Flags & 1) ? PixelFormats.Bgr32 : PixelFormats.Bgra32;
|
||||||
PixelFormats.Bgra32, null, pixel_data, (int)info.Width*4);
|
return ImageData.Create (info, format, null, pixel_data);
|
||||||
bitmap.Freeze();
|
|
||||||
return new ImageData (bitmap, info);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
byte[] DecodeStream (Stream file, GgaMetaData meta)
|
byte[] DecodeStream (Stream file, GgaMetaData meta)
|
||||||
@@ -511,7 +546,6 @@ namespace GameRes.Formats.DRS
|
|||||||
var output = new byte[meta.Width*meta.Height*4];
|
var output = new byte[meta.Width*meta.Height*4];
|
||||||
using (var input = new BinaryReader (file, Encoding.ASCII, true))
|
using (var input = new BinaryReader (file, Encoding.ASCII, true))
|
||||||
{
|
{
|
||||||
var buf = new byte[4];
|
|
||||||
var end_pos = input.BaseStream.Position + meta.CompSize;
|
var end_pos = input.BaseStream.Position + meta.CompSize;
|
||||||
while (input.BaseStream.Position < end_pos)
|
while (input.BaseStream.Position < end_pos)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user