added some IImageDecoder implementations.

This commit is contained in:
morkt
2016-10-26 05:10:30 +04:00
parent d02a9b180a
commit 2c06c1cbcd
8 changed files with 196 additions and 95 deletions

View File

@@ -52,7 +52,7 @@ namespace GameRes.Formats.CatSystem
uint section_size = file.View.ReadUInt32 (offset+0x40);
var entry = new Entry
{
Name = string.Format ("{0}#{1:D4}.tga", base_name, i),
Name = string.Format ("{0}#{1:D4}", base_name, i),
Type = "image",
Offset = offset,
};
@@ -71,9 +71,8 @@ namespace GameRes.Formats.CatSystem
return new ArcFile (file, this, dir);
}
public override Stream OpenEntry (ArcFile arc, Entry entry)
public override IImageDecoder OpenImage (ArcFile arc, Entry entry)
{
// emulate TGA image
var offset = entry.Offset;
var info = new Hg2MetaData
{
@@ -90,11 +89,8 @@ namespace GameRes.Formats.CatSystem
OffsetX = arc.File.View.ReadInt32 (offset+0x34),
OffsetY = arc.File.View.ReadInt32 (offset+0x38),
};
using (var input = arc.File.CreateStream (entry.Offset, entry.Size))
using (var reader = new Hg2Reader (input, info))
{
return TgaStream.Create (info, reader.Unpack(), true);
}
var input = arc.File.CreateStream (entry.Offset, entry.Size);
return new Hg2Reader (input, info);
}
}
}

View File

@@ -55,7 +55,7 @@ namespace GameRes.Formats.CatSystem
{
var entry = new Entry
{
Name = string.Format ("{0}#{1:D4}.tga", base_name, i),
Name = string.Format ("{0}#{1:D4}", base_name, i),
Type = "image",
Offset = offset + 8,
Size = section_size - 8,
@@ -70,9 +70,8 @@ namespace GameRes.Formats.CatSystem
return new ArcFile (file, this, dir);
}
public override Stream OpenEntry (ArcFile arc, Entry entry)
public override IImageDecoder OpenImage (ArcFile arc, Entry entry)
{
// emulate TGA image
var offset = entry.Offset+8;
var info = new HgMetaData
{
@@ -85,12 +84,8 @@ namespace GameRes.Formats.CatSystem
CanvasWidth = arc.File.View.ReadUInt32 (offset+0x1C),
CanvasHeight = arc.File.View.ReadUInt32 (offset+0x20),
};
using (var input = arc.File.CreateStream (entry.Offset, entry.Size))
using (var reader = new Hg3Reader (input, info))
{
var pixels = reader.Unpack();
return TgaStream.Create (info, pixels, reader.Flipped);
}
var input = arc.File.CreateStream (entry.Offset, entry.Size);
return new Hg3Reader (input, info);
}
}
}

View File

@@ -74,11 +74,7 @@ namespace GameRes.Formats.CatSystem
public override ImageData Read (IBinaryStream stream, ImageMetaData info)
{
using (var reader = new Hg2Reader (stream, (Hg2MetaData)info))
{
var pixels = reader.Unpack();
var format = 24 == info.BPP ? PixelFormats.Bgr24 : PixelFormats.Bgra32;
return ImageData.CreateFlipped (info, format, null, pixels, reader.Stride);
}
return reader.Image;
}
public override void Write (Stream file, ImageData image)
@@ -91,6 +87,20 @@ namespace GameRes.Formats.CatSystem
{
Hg2MetaData m_hg2;
public override ImageData Image
{
get
{
if (null == m_image)
{
var pixels = Unpack();
var format = 24 == m_hg2.BPP ? PixelFormats.Bgr24 : PixelFormats.Bgra32;
m_image = ImageData.CreateFlipped (m_hg2, format, null, pixels, Stride);
}
return m_image;
}
}
public Hg2Reader (IBinaryStream input, Hg2MetaData info) : base (input, info)
{
m_hg2 = info;

View File

@@ -77,11 +77,7 @@ namespace GameRes.Formats.CatSystem
using (var input = new BinaryStream (reg, stream.Name))
using (var reader = new Hg3Reader (input, meta))
{
var pixels = reader.Unpack();
if (reader.Flipped)
return ImageData.CreateFlipped (info, PixelFormats.Bgra32, null, pixels, reader.Stride);
else
return ImageData.Create (info, PixelFormats.Bgra32, null, pixels, reader.Stride);
return reader.Image;
}
}
@@ -91,15 +87,18 @@ namespace GameRes.Formats.CatSystem
}
}
internal class HgReader : IDisposable
internal class HgReader : IImageDecoder
{
private IBinaryStream m_input;
protected IBinaryStream m_input;
protected HgMetaData m_info;
protected int m_pixel_size;
protected ImageData m_image;
protected IBinaryStream Input { get { return m_input; } }
protected Stream InputStream { get { return m_input.AsStream; } }
public Stream Input { get { return m_input.AsStream; } }
public int Stride { get; protected set; }
public ImageFormat Format { get { return null; } }
public ImageMetaData Info { get { return m_info; } }
public virtual ImageData Image { get { throw new NotImplementedException(); } }
protected HgReader (IBinaryStream input, HgMetaData info)
{
@@ -113,12 +112,12 @@ namespace GameRes.Formats.CatSystem
{
var ctl_offset = data_offset + data_packed;
var data = new byte[data_unpacked];
using (var z = new StreamRegion (InputStream, data_offset, data_packed, true))
using (var z = new StreamRegion (Input, data_offset, data_packed, true))
using (var data_in = new ZLibStream (z, CompressionMode.Decompress))
if (data.Length != data_in.Read (data, 0, data.Length))
throw new EndOfStreamException();
using (var z = new StreamRegion (InputStream, ctl_offset, ctl_packed, true))
using (var z = new StreamRegion (Input, ctl_offset, ctl_packed, true))
using (var ctl_in = new ZLibStream (z, CompressionMode.Decompress))
using (var bits = new LsbBitStream (ctl_in))
{
@@ -237,14 +236,30 @@ namespace GameRes.Formats.CatSystem
{
public bool Flipped { get; private set; }
public override ImageData Image
{
get
{
if (null == m_image)
{
var pixels = Unpack();
if (Flipped)
m_image = ImageData.CreateFlipped (Info, PixelFormats.Bgra32, null, pixels, Stride);
else
m_image = ImageData.Create (Info, PixelFormats.Bgra32, null, pixels, Stride);
}
return m_image;
}
}
public Hg3Reader (IBinaryStream input, HgMetaData info) : base (input, info)
{
}
public byte[] Unpack ()
{
InputStream.Position = m_info.HeaderSize;
var img_type = Input.ReadBytes (8);
Input.Position = m_info.HeaderSize;
var img_type = m_input.ReadBytes (8);
if (Binary.AsciiEqual (img_type, "img0000\0"))
return UnpackImg0000();
else if (Binary.AsciiEqual (img_type, "img_jpg\0"))
@@ -256,21 +271,21 @@ namespace GameRes.Formats.CatSystem
byte[] UnpackImg0000 ()
{
Flipped = true;
InputStream.Position = m_info.HeaderSize+0x18;
int packed_data_size = Input.ReadInt32();
int data_size = Input.ReadInt32();
int packed_ctl_size = Input.ReadInt32();
int ctl_size = Input.ReadInt32();
Input.Position = m_info.HeaderSize+0x18;
int packed_data_size = m_input.ReadInt32();
int data_size = m_input.ReadInt32();
int packed_ctl_size = m_input.ReadInt32();
int ctl_size = m_input.ReadInt32();
return UnpackStream (m_info.HeaderSize+0x28, packed_data_size, data_size, packed_ctl_size, ctl_size);
}
byte[] UnpackJpeg ()
{
Flipped = false;
Input.ReadInt32();
var jpeg_size = Input.ReadInt32();
long next_section = InputStream.Position + jpeg_size;
var decoder = new JpegBitmapDecoder (InputStream,
m_input.ReadInt32();
var jpeg_size = m_input.ReadInt32();
long next_section = Input.Position + jpeg_size;
var decoder = new JpegBitmapDecoder (Input,
BitmapCreateOptions.None, BitmapCacheOption.OnLoad);
var frame = decoder.Frames[0];
if (frame.Format.BitsPerPixel < 24)
@@ -292,13 +307,13 @@ namespace GameRes.Formats.CatSystem
src += src_pixel_size;
}
Input.Position = next_section;
var section_header = Input.ReadBytes (8);
m_input.Position = next_section;
var section_header = m_input.ReadBytes (8);
if (!Binary.AsciiEqual (section_header, "img_al\0\0"))
return output;
Input.Seek (8, SeekOrigin.Current);
int alpha_size = Input.ReadInt32();
using (var alpha_in = new StreamRegion (InputStream, InputStream.Position+4, alpha_size, true))
m_input.Seek (8, SeekOrigin.Current);
int alpha_size = m_input.ReadInt32();
using (var alpha_in = new StreamRegion (Input, Input.Position+4, alpha_size, true))
using (var alpha = new ZLibStream (alpha_in, CompressionMode.Decompress))
{
for (int i = 3; i < output.Length; i += 4)