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)

View File

@ -27,6 +27,7 @@ using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.IO;
using System.Windows.Media;
namespace GameRes.Formats.Kaguya
{
@ -79,7 +80,7 @@ namespace GameRes.Formats.Kaguya
uint height = file.View.ReadUInt32 (current_offset+12);
var entry = new Entry
{
Name = string.Format ("{0}#{1:D2}.tga", base_name, i),
Name = string.Format ("{0}#{1:D2}", base_name, i),
Type = "image",
Offset = current_offset,
Size = 0x10 + 4*width*height,
@ -90,22 +91,34 @@ namespace GameRes.Formats.Kaguya
return new AnmArchive (file, this, dir, base_info);
}
public override Stream OpenEntry (ArcFile arc, Entry entry)
public override IImageDecoder OpenImage (ArcFile arc, Entry entry)
{
var base_info = ((AnmArchive)arc).ImageInfo;
// emulate TGA image
var offset = entry.Offset;
var info = new ImageMetaData
var input = arc.File.CreateStream (entry.Offset, entry.Size);
return new An00Decoder (input, base_info);
}
}
internal class An00Decoder : BinaryImageDecoder
{
public An00Decoder (IBinaryStream input, ImageMetaData base_info) : base (input)
{
Info = new ImageMetaData
{
OffsetX = base_info.OffsetX + arc.File.View.ReadInt32 (offset),
OffsetY = base_info.OffsetY + arc.File.View.ReadInt32 (offset+4),
Width = arc.File.View.ReadUInt32 (offset+8),
Height = arc.File.View.ReadUInt32 (offset+12),
BPP = 32,
OffsetX = base_info.OffsetX + m_input.ReadInt32(),
OffsetY = base_info.OffsetY + m_input.ReadInt32(),
Width = m_input.ReadUInt32(),
Height = m_input.ReadUInt32(),
BPP = 32,
};
offset += 0x10;
var pixels = arc.File.View.ReadBytes (offset, 4*info.Width*info.Height);
return TgaStream.Create (info, pixels, true);
}
protected override ImageData GetImageData ()
{
m_input.Position = 0x10;
int stride = 4*(int)Info.Width;
var pixels = m_input.ReadBytes (stride*(int)Info.Height);
return ImageData.CreateFlipped (Info, PixelFormats.Bgra32, null, pixels, stride);
}
}
@ -163,7 +176,7 @@ namespace GameRes.Formats.Kaguya
uint depth = file.View.ReadUInt32 (current_offset+0x10);
var entry = new Entry
{
Name = string.Format ("{0}#{1:D2}.tga", base_name, i),
Name = string.Format ("{0}#{1:D2}", base_name, i),
Type = "image",
Offset = current_offset,
Size = 0x14 + depth*width*height,
@ -174,22 +187,45 @@ namespace GameRes.Formats.Kaguya
return new AnmArchive (file, this, dir, base_info);
}
public override Stream OpenEntry (ArcFile arc, Entry entry)
public override IImageDecoder OpenImage (ArcFile arc, Entry entry)
{
var base_info = ((AnmArchive)arc).ImageInfo;
// emulate TGA image
var offset = entry.Offset;
var info = new ImageMetaData
var input = arc.File.CreateStream (entry.Offset, entry.Size);
return new An20Decoder (input, base_info);
}
}
internal class An20Decoder : BinaryImageDecoder
{
public An20Decoder (IBinaryStream input, ImageMetaData base_info) : base (input)
{
Info = new ImageMetaData
{
OffsetX = base_info.OffsetX + arc.File.View.ReadInt32 (offset),
OffsetY = base_info.OffsetY + arc.File.View.ReadInt32 (offset+4),
Width = arc.File.View.ReadUInt32 (offset+8),
Height = arc.File.View.ReadUInt32 (offset+0xC),
BPP = arc.File.View.ReadInt32 (offset+0x10) * 8,
OffsetX = base_info.OffsetX + m_input.ReadInt32(),
OffsetY = base_info.OffsetY + m_input.ReadInt32(),
Width = m_input.ReadUInt32(),
Height = m_input.ReadUInt32(),
BPP = m_input.ReadInt32() * 8,
};
offset += 0x14;
var pixels = arc.File.View.ReadBytes (offset, (uint)info.BPP/8*info.Width*info.Height);
return TgaStream.Create (info, pixels, true);
}
protected override ImageData GetImageData ()
{
m_input.Position = 0x14;
int stride = info.BPP/8*(int)Info.Width;
var pixels = m_input.ReadBytes (stride*(int)info.Height);
return ImageData.CreateFlipped (Info, GetFormat(), null, pixels, stride);
}
PixelFormat GetFormat ()
{
switch (Info.BPP)
{
case 8: return PixelFormats.Gray8;
case 24: return PixelFormats.Bgr24;
case 32: return PixelFormats.Bgra32;
default: throw new InvalidFormatException();
}
}
}
}

View File

@ -69,7 +69,7 @@ namespace GameRes.Formats.Musica
for (int i = 0; i < count; ++i)
{
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 = file.View.ReadUInt32 (index_offset),
Size = file.View.ReadUInt32 (index_offset+4),
@ -82,15 +82,51 @@ namespace GameRes.Formats.Musica
return new SqzArchive (file, this, dir, info);
}
public override Stream OpenEntry (ArcFile arc, Entry entry)
public override IImageDecoder OpenImage (ArcFile arc, Entry entry)
{
var sqarc = (SqzArchive)arc;
using (var input = arc.File.CreateStream (entry.Offset, entry.Size))
using (var zs = new ZLibStream (input, CompressionMode.Decompress))
var input = arc.File.CreateStream (entry.Offset, entry.Size);
var zs = new ZLibStream (input, CompressionMode.Decompress);
return new SqzReader (zs, sqarc.Info);
}
internal sealed class SqzReader : IImageDecoder
{
Stream m_input;
ImageMetaData m_info;
ImageData m_image;
public Stream Input { get { return m_input; } }
public ImageFormat Format { get { return null; } }
public ImageMetaData Info { get { return m_info; } }
public ImageData Image
{
var pixels = new byte[sqarc.Info.Width * sqarc.Info.Height * 4];
zs.Read (pixels, 0, pixels.Length);
return TgaStream.Create (sqarc.Info, pixels);
get
{
if (null == m_image)
{
var pixels = new byte[m_info.Width * m_info.Height * 4];
m_input.Read (pixels, 0, pixels.Length);
m_image = ImageData.Create (m_info, PixelFormats.Bgra32, null, pixels);
}
return m_image;
}
}
public SqzReader (Stream input, ImageMetaData info)
{
m_input = input;
m_info = info;
}
bool m_disposed = false;
public void Dispose ()
{
if (!m_disposed)
{
m_input.Dispose();
m_disposed = true;
}
}
}
}

View File

@ -59,7 +59,7 @@ namespace GameRes.Formats.ShiinaRio
{
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,
};
@ -79,9 +79,8 @@ namespace GameRes.Formats.ShiinaRio
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 S25MetaData
{
@ -93,11 +92,8 @@ namespace GameRes.Formats.ShiinaRio
FirstOffset = (uint)(offset + 0x14),
Incremental = 0 != (arc.File.View.ReadUInt32 (offset+0x10) & 0x80000000u),
};
using (var input = arc.File.CreateStream (0, (uint)arc.File.MaxOffset))
using (var reader = new S25Format.Reader (input, info))
{
return TgaStream.Create (info, reader.Unpack());
}
var input = arc.File.CreateStream (0, (uint)arc.File.MaxOffset);
return new S25Format.Reader (input, info);
}
}
}

View File

@ -76,10 +76,7 @@ namespace GameRes.Formats.ShiinaRio
public override ImageData Read (IBinaryStream stream, ImageMetaData info)
{
using (var reader = new Reader (stream, (S25MetaData)info))
{
var pixels = reader.Unpack();
return ImageData.Create (info, PixelFormats.Bgra32, null, pixels);
}
return reader.Image;
}
public override void Write (Stream file, ImageData image)
@ -87,7 +84,7 @@ namespace GameRes.Formats.ShiinaRio
throw new NotImplementedException ("S25Format.Write not implemented");
}
internal sealed class Reader : IDisposable
internal sealed class Reader : IImageDecoder
{
IBinaryStream m_input;
int m_width;
@ -95,6 +92,25 @@ namespace GameRes.Formats.ShiinaRio
uint m_origin;
byte[] m_output;
bool m_incremental;
ImageMetaData m_info;
ImageData m_image;
public Stream Input { get { m_input.Position = 0; return m_input.AsStream; } }
public ImageMetaData Info { get { return m_info; } }
public ImageFormat Format { get { return null; } }
public ImageData Image
{
get
{
if (null == m_image)
{
var pixels = Unpack();
m_image = ImageData.Create (m_info, PixelFormats.Bgra32, null, pixels);
}
return m_image;
}
}
public byte[] Data { get { return m_output; } }
@ -106,6 +122,7 @@ namespace GameRes.Formats.ShiinaRio
m_input = file;
m_origin = info.FirstOffset;
m_incremental = info.Incremental;
m_info = info;
}
public byte[] Unpack ()