mirror of
https://github.com/crskycode/GARbro.git
synced 2024-11-27 07:34:00 +08:00
implemented OpenImage methods for some image archives.
This commit is contained in:
parent
c256563181
commit
e1a0cca0fd
@ -29,6 +29,7 @@ using System.ComponentModel.Composition;
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Windows.Media;
|
using System.Windows.Media;
|
||||||
|
using System.Windows.Media.Imaging;
|
||||||
using GameRes.Utility;
|
using GameRes.Utility;
|
||||||
|
|
||||||
namespace GameRes.Formats.Entis
|
namespace GameRes.Formats.Entis
|
||||||
@ -92,7 +93,7 @@ namespace GameRes.Formats.Entis
|
|||||||
else if ("ImageFrm" == id || "DiffeFrm" == id)
|
else if ("ImageFrm" == id || "DiffeFrm" == id)
|
||||||
{
|
{
|
||||||
var entry = new EriEntry {
|
var entry = new EriEntry {
|
||||||
Name = string.Format ("{0}#{1:D4}.tga", base_name, i++),
|
Name = string.Format ("{0}#{1:D4}", base_name, i++),
|
||||||
Type = "image",
|
Type = "image",
|
||||||
Offset = current_offset,
|
Offset = current_offset,
|
||||||
Size = (uint)section_size,
|
Size = (uint)section_size,
|
||||||
@ -110,17 +111,15 @@ namespace GameRes.Formats.Entis
|
|||||||
return new EriMultiImage (file, this, dir, info, palette);
|
return new EriMultiImage (file, this, dir, info, palette);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Stream OpenEntry (ArcFile arc, Entry entry)
|
public override IImageDecoder OpenImage (ArcFile arc, Entry entry)
|
||||||
{
|
{
|
||||||
var earc = (EriMultiImage)arc;
|
var earc = (EriMultiImage)arc;
|
||||||
var eent = (EriEntry)entry;
|
var eent = (EriEntry)entry;
|
||||||
var pixels = earc.GetFrame (eent.FrameIndex);
|
var pixels = earc.GetFrame (eent.FrameIndex);
|
||||||
if (32 == earc.Info.BPP && 0 == (earc.Info.FormatType & EriType.WithAlpha))
|
BitmapPalette palette = null;
|
||||||
{
|
if (8 == earc.Info.BPP && earc.Palette != null)
|
||||||
for (int p = 3; p < pixels.Length; p += 4)
|
palette = new BitmapPalette (earc.Palette);
|
||||||
pixels[p] = 0xFF;
|
return new BitmapDecoder (pixels, earc.Info, earc.Format, palette);
|
||||||
}
|
|
||||||
return TgaStream.Create (earc.Info, pixels);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,6 +127,7 @@ namespace GameRes.Formats.Entis
|
|||||||
{
|
{
|
||||||
public readonly EriMetaData Info;
|
public readonly EriMetaData Info;
|
||||||
public readonly Color[] Palette;
|
public readonly Color[] Palette;
|
||||||
|
public readonly PixelFormat Format;
|
||||||
byte[][] Frames;
|
byte[][] Frames;
|
||||||
|
|
||||||
public EriMultiImage (ArcView arc, ArchiveFormat impl, ICollection<Entry> dir, EriMetaData info, Color[] palette)
|
public EriMultiImage (ArcView arc, ArchiveFormat impl, ICollection<Entry> dir, EriMetaData info, Color[] palette)
|
||||||
@ -136,6 +136,24 @@ namespace GameRes.Formats.Entis
|
|||||||
Info = info;
|
Info = info;
|
||||||
Palette = palette;
|
Palette = palette;
|
||||||
Frames = new byte[dir.Count][];
|
Frames = new byte[dir.Count][];
|
||||||
|
if (8 == Info.BPP)
|
||||||
|
{
|
||||||
|
if (null == Palette)
|
||||||
|
Format = PixelFormats.Gray8;
|
||||||
|
else
|
||||||
|
Format = PixelFormats.Indexed8;
|
||||||
|
}
|
||||||
|
else if (32 == Info.BPP)
|
||||||
|
{
|
||||||
|
if (0 == (Info.FormatType & EriType.WithAlpha))
|
||||||
|
Format = PixelFormats.Bgr32;
|
||||||
|
else
|
||||||
|
Format = PixelFormats.Bgra32;
|
||||||
|
}
|
||||||
|
else if (16 == Info.BPP)
|
||||||
|
Format = PixelFormats.Bgr555;
|
||||||
|
else
|
||||||
|
Format = PixelFormats.Bgr24;
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] GetFrame (int index)
|
public byte[] GetFrame (int index)
|
||||||
@ -166,4 +184,22 @@ namespace GameRes.Formats.Entis
|
|||||||
public int FrameIndex;
|
public int FrameIndex;
|
||||||
public bool IsDiff;
|
public bool IsDiff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal class BitmapDecoder : IImageDecoder
|
||||||
|
{
|
||||||
|
public Stream Source { get { return null; } }
|
||||||
|
public ImageFormat SourceFormat { get { return null; } }
|
||||||
|
public ImageMetaData Info { get; private set; }
|
||||||
|
public ImageData Image { get; private set; }
|
||||||
|
|
||||||
|
public BitmapDecoder (byte[] pixels, ImageMetaData info, PixelFormat format, BitmapPalette palette)
|
||||||
|
{
|
||||||
|
Info = info;
|
||||||
|
Image = ImageData.Create (info, format, palette, pixels);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose ()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,6 +29,7 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.ComponentModel.Composition;
|
using System.ComponentModel.Composition;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Windows.Media;
|
||||||
|
|
||||||
namespace GameRes.Formats.FC01
|
namespace GameRes.Formats.FC01
|
||||||
{
|
{
|
||||||
@ -69,7 +70,7 @@ namespace GameRes.Formats.FC01
|
|||||||
index_offset += 4;
|
index_offset += 4;
|
||||||
var entry = new Entry
|
var entry = new Entry
|
||||||
{
|
{
|
||||||
Name = string.Format ("{0}#{1:D4}.tga", base_name, i),
|
Name = string.Format ("{0}#{1:D4}", base_name, i),
|
||||||
Offset = next_offset,
|
Offset = next_offset,
|
||||||
Type = "image",
|
Type = "image",
|
||||||
};
|
};
|
||||||
@ -84,31 +85,19 @@ namespace GameRes.Formats.FC01
|
|||||||
return new McaArchive (file, this, dir, options.Key);
|
return new McaArchive (file, this, dir, options.Key);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Stream OpenEntry (ArcFile arc, Entry entry)
|
public override IImageDecoder OpenImage (ArcFile arc, Entry entry)
|
||||||
{
|
{
|
||||||
var mca = arc as McaArchive;
|
var mca = (McaArchive)arc;
|
||||||
int method = arc.File.View.ReadInt32 (entry.Offset);
|
var input = arc.File.CreateStream (entry.Offset, entry.Size);
|
||||||
if (null == mca || method < 0 || method > 1)
|
try
|
||||||
return base.OpenEntry (arc, entry);
|
|
||||||
uint width = arc.File.View.ReadUInt32 (entry.Offset+0xC);
|
|
||||||
uint height = arc.File.View.ReadUInt32 (entry.Offset+0x10);
|
|
||||||
uint packed_size = arc.File.View.ReadUInt32 (entry.Offset+0x14);
|
|
||||||
int unpacked_size = arc.File.View.ReadInt32 (entry.Offset+0x18);
|
|
||||||
|
|
||||||
var data = arc.File.View.ReadBytes (entry.Offset+0x20, packed_size);
|
|
||||||
MrgOpener.Decrypt (data, 0, data.Length, mca.Key);
|
|
||||||
if (method > 0)
|
|
||||||
{
|
{
|
||||||
using (var input = new BinMemoryStream (data))
|
return new McaDecoder (input, mca.Key);
|
||||||
using (var lzss = new MrgLzssReader (input, data.Length, unpacked_size))
|
|
||||||
{
|
|
||||||
lzss.Unpack();
|
|
||||||
data = lzss.Data;
|
|
||||||
}
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
input.Dispose();
|
||||||
|
throw;
|
||||||
}
|
}
|
||||||
int stride = ((int)width * 3 + 3) & ~3;
|
|
||||||
var info = new ImageMetaData { Width = width, Height = height, BPP = 24 };
|
|
||||||
return TgaStream.Create (info, stride, data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override ResourceOptions GetDefaultOptions ()
|
public override ResourceOptions GetDefaultOptions ()
|
||||||
@ -129,4 +118,44 @@ namespace GameRes.Formats.FC01
|
|||||||
return new GUI.WidgetMCG();
|
return new GUI.WidgetMCG();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal sealed class McaDecoder : BinaryImageDecoder
|
||||||
|
{
|
||||||
|
byte m_key;
|
||||||
|
int m_method;
|
||||||
|
int m_packed_size;
|
||||||
|
int m_unpacked_size;
|
||||||
|
|
||||||
|
public McaDecoder (IBinaryStream input, byte key) : base (input)
|
||||||
|
{
|
||||||
|
m_key = key;
|
||||||
|
var header = m_input.ReadHeader (0x20);
|
||||||
|
m_method = header.ToInt32 (0);
|
||||||
|
if (m_method < 0 || m_method > 1)
|
||||||
|
throw new InvalidFormatException();
|
||||||
|
uint width = header.ToUInt32 (0xC);
|
||||||
|
uint height = header.ToUInt32 (0x10);
|
||||||
|
m_packed_size = header.ToInt32 (0x14);
|
||||||
|
m_unpacked_size = header.ToInt32 (0x18);
|
||||||
|
Info = new ImageMetaData { Width = width, Height = height, BPP = 24 };
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override ImageData GetImageData ()
|
||||||
|
{
|
||||||
|
m_input.Position = 0x20;
|
||||||
|
var data = m_input.ReadBytes (m_packed_size);
|
||||||
|
MrgOpener.Decrypt (data, 0, data.Length, m_key);
|
||||||
|
if (m_method > 0)
|
||||||
|
{
|
||||||
|
using (var input = new BinMemoryStream (data))
|
||||||
|
using (var lzss = new MrgLzssReader (input, data.Length, m_unpacked_size))
|
||||||
|
{
|
||||||
|
lzss.Unpack();
|
||||||
|
data = lzss.Data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int stride = ((int)Info.Width * 3 + 3) & ~3;
|
||||||
|
return ImageData.Create (Info, PixelFormats.Bgr24, null, data, stride);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -78,10 +78,10 @@ namespace GameRes.Formats.FVP
|
|||||||
for (int i = 0; i < count; ++i)
|
for (int i = 0; i < count; ++i)
|
||||||
{
|
{
|
||||||
var entry = new Entry {
|
var entry = new Entry {
|
||||||
Name = string.Format ("{0}#{1:D3}.tga", base_name, i),
|
Name = string.Format ("{0}#{1:D3}", base_name, i),
|
||||||
Type = "image",
|
Type = "image",
|
||||||
Offset = frame_size * i,
|
Offset = frame_size * i,
|
||||||
Size = 0x12 + (uint)frame_size,
|
Size = (uint)frame_size,
|
||||||
};
|
};
|
||||||
dir.Add (entry);
|
dir.Add (entry);
|
||||||
}
|
}
|
||||||
@ -94,24 +94,33 @@ namespace GameRes.Formats.FVP
|
|||||||
using (var input = arc.File.CreateStream (0xC+hzc.ImageInfo.HeaderSize))
|
using (var input = arc.File.CreateStream (0xC+hzc.ImageInfo.HeaderSize))
|
||||||
using (var z = new ZLibStream (input, CompressionMode.Decompress))
|
using (var z = new ZLibStream (input, CompressionMode.Decompress))
|
||||||
{
|
{
|
||||||
uint frame_size = entry.Size - 0x12;
|
uint frame_size = entry.Size;
|
||||||
var pixels = new byte[frame_size];
|
var pixels = new byte[frame_size];
|
||||||
uint offset = 0;
|
uint offset = 0;
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
if (pixels.Length != z.Read (pixels, 0, pixels.Length))
|
if (pixels.Length != z.Read (pixels, 0, pixels.Length))
|
||||||
break;
|
throw new EndOfStreamException();
|
||||||
if (offset >= entry.Offset)
|
if (offset >= entry.Offset)
|
||||||
break;
|
break;
|
||||||
offset += frame_size;
|
offset += frame_size;
|
||||||
}
|
}
|
||||||
if (4 == hzc.ImageInfo.Type)
|
return new BinMemoryStream (pixels, entry.Name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override IImageDecoder OpenImage (ArcFile arc, Entry entry)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < pixels.Length; ++i)
|
var hzc = (HzcArchive)arc;
|
||||||
if (1 == pixels[i])
|
var input = arc.File.CreateStream (0xC+hzc.ImageInfo.HeaderSize);
|
||||||
pixels[i] = 0xFF;
|
try
|
||||||
|
{
|
||||||
|
return new HzcDecoder (input, hzc.ImageInfo, entry);
|
||||||
}
|
}
|
||||||
return TgaStream.Create (hzc.ImageInfo, pixels);
|
catch
|
||||||
|
{
|
||||||
|
input.Dispose();
|
||||||
|
throw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -69,32 +69,9 @@ namespace GameRes.Formats.FVP
|
|||||||
public override ImageData Read (IBinaryStream stream, ImageMetaData info)
|
public override ImageData Read (IBinaryStream stream, ImageMetaData info)
|
||||||
{
|
{
|
||||||
var meta = (HzcMetaData)info;
|
var meta = (HzcMetaData)info;
|
||||||
BitmapPalette palette = null;
|
|
||||||
int stride = (int)meta.Width * meta.BPP / 8;
|
|
||||||
PixelFormat format;
|
|
||||||
switch (meta.Type)
|
|
||||||
{
|
|
||||||
default: throw new NotSupportedException();
|
|
||||||
case 0: format = PixelFormats.Bgr24; break;
|
|
||||||
case 1:
|
|
||||||
case 2: format = PixelFormats.Bgra32; break;
|
|
||||||
case 3: format = PixelFormats.Gray8; break;
|
|
||||||
case 4:
|
|
||||||
{
|
|
||||||
format = PixelFormats.Indexed8;
|
|
||||||
var colors = new Color[2] { Color.FromRgb (0,0,0), Color.FromRgb (0xFF,0xFF,0xFF) };
|
|
||||||
palette = new BitmapPalette (colors);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
stream.Position = 12 + meta.HeaderSize;
|
stream.Position = 12 + meta.HeaderSize;
|
||||||
using (var z = new ZLibStream (stream.AsStream, CompressionMode.Decompress, true))
|
using (var decoder = new HzcDecoder (stream, meta, true))
|
||||||
{
|
return decoder.Image;
|
||||||
var pixels = new byte[stride * (int)meta.Height];
|
|
||||||
if (pixels.Length != z.Read (pixels, 0, pixels.Length))
|
|
||||||
throw new EndOfStreamException();
|
|
||||||
return ImageData.Create (info, format, palette, pixels, stride);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Write (Stream file, ImageData image)
|
public override void Write (Stream file, ImageData image)
|
||||||
@ -102,4 +79,87 @@ namespace GameRes.Formats.FVP
|
|||||||
throw new System.NotImplementedException ("HzcFormat.Write not implemented");
|
throw new System.NotImplementedException ("HzcFormat.Write not implemented");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal sealed class HzcDecoder : IImageDecoder
|
||||||
|
{
|
||||||
|
HzcMetaData m_info;
|
||||||
|
ImageData m_image;
|
||||||
|
int m_stride;
|
||||||
|
long m_frame_offset;
|
||||||
|
int m_frame_size;
|
||||||
|
|
||||||
|
public Stream Source { get; private set; }
|
||||||
|
public ImageFormat SourceFormat { get { return null; } }
|
||||||
|
public ImageMetaData Info { get { return m_info; } }
|
||||||
|
public PixelFormat Format { get; private set; }
|
||||||
|
public BitmapPalette Palette { get; private set; }
|
||||||
|
public ImageData Image
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (null == m_image)
|
||||||
|
{
|
||||||
|
var pixels = ReadPixels();
|
||||||
|
m_image = ImageData.Create (Info, Format, Palette, pixels, m_stride);
|
||||||
|
}
|
||||||
|
return m_image;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public HzcDecoder (IBinaryStream input, HzcMetaData info, Entry entry) : this (input, info)
|
||||||
|
{
|
||||||
|
m_frame_offset = entry.Offset;
|
||||||
|
m_frame_size = (int)entry.Size;
|
||||||
|
}
|
||||||
|
|
||||||
|
public HzcDecoder (IBinaryStream input, HzcMetaData info, bool leave_open = false)
|
||||||
|
{
|
||||||
|
m_info = info;
|
||||||
|
m_stride = (int)m_info.Width * m_info.BPP / 8;
|
||||||
|
switch (m_info.Type)
|
||||||
|
{
|
||||||
|
default: throw new NotSupportedException();
|
||||||
|
case 0: Format = PixelFormats.Bgr24; break;
|
||||||
|
case 1:
|
||||||
|
case 2: Format = PixelFormats.Bgra32; break;
|
||||||
|
case 3: Format = PixelFormats.Gray8; break;
|
||||||
|
case 4:
|
||||||
|
{
|
||||||
|
Format = PixelFormats.Indexed8;
|
||||||
|
var colors = new Color[2] { Color.FromRgb (0,0,0), Color.FromRgb (0xFF,0xFF,0xFF) };
|
||||||
|
Palette = new BitmapPalette (colors);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Source = new ZLibStream (input.AsStream, CompressionMode.Decompress, leave_open);
|
||||||
|
m_frame_offset = 0;
|
||||||
|
m_frame_size = m_stride * (int)Info.Height;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] ReadPixels ()
|
||||||
|
{
|
||||||
|
var pixels = new byte[m_frame_size];
|
||||||
|
long offset = 0;
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
if (pixels.Length != Source.Read (pixels, 0, pixels.Length))
|
||||||
|
throw new EndOfStreamException();
|
||||||
|
if (offset >= m_frame_offset)
|
||||||
|
break;
|
||||||
|
offset += m_frame_size;
|
||||||
|
}
|
||||||
|
return pixels;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool m_disposed = false;
|
||||||
|
public void Dispose ()
|
||||||
|
{
|
||||||
|
if (!m_disposed)
|
||||||
|
{
|
||||||
|
Source.Dispose();
|
||||||
|
m_disposed = true;
|
||||||
|
}
|
||||||
|
GC.SuppressFinalize (this);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.ComponentModel.Composition;
|
using System.ComponentModel.Composition;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Windows.Media;
|
||||||
|
|
||||||
namespace GameRes.Formats.Patisserie
|
namespace GameRes.Formats.Patisserie
|
||||||
{
|
{
|
||||||
@ -55,7 +56,7 @@ namespace GameRes.Formats.Patisserie
|
|||||||
while (current_offset < end)
|
while (current_offset < end)
|
||||||
{
|
{
|
||||||
var entry = new Entry {
|
var entry = new Entry {
|
||||||
Name = string.Format ("{0:D4}.tga", i++),
|
Name = string.Format ("{0:D4}", i++),
|
||||||
Type = "image",
|
Type = "image",
|
||||||
Offset = current_offset,
|
Offset = current_offset,
|
||||||
};
|
};
|
||||||
@ -70,7 +71,7 @@ namespace GameRes.Formats.Patisserie
|
|||||||
return new ArcFile (file, this, dir);
|
return new ArcFile (file, this, dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Stream OpenEntry (ArcFile arc, Entry entry)
|
public override IImageDecoder OpenImage (ArcFile arc, Entry entry)
|
||||||
{
|
{
|
||||||
var info = new ImageMetaData
|
var info = new ImageMetaData
|
||||||
{
|
{
|
||||||
@ -81,7 +82,25 @@ namespace GameRes.Formats.Patisserie
|
|||||||
BPP = 32,
|
BPP = 32,
|
||||||
};
|
};
|
||||||
var pixels = arc.File.View.ReadBytes (entry.Offset+0x14, entry.Size-0x14);
|
var pixels = arc.File.View.ReadBytes (entry.Offset+0x14, entry.Size-0x14);
|
||||||
return TgaStream.Create (info, pixels);
|
return new RawDecoder (info, pixels);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal sealed class RawDecoder : IImageDecoder
|
||||||
|
{
|
||||||
|
public Stream Source { get { return null; } }
|
||||||
|
public ImageFormat SourceFormat { get { return null; } }
|
||||||
|
public ImageMetaData Info { get; private set; }
|
||||||
|
public ImageData Image { get; private set; }
|
||||||
|
|
||||||
|
public RawDecoder (ImageMetaData info, byte[] pixels)
|
||||||
|
{
|
||||||
|
Info = info;
|
||||||
|
Image = ImageData.Create (info, PixelFormats.Bgra32, null, pixels);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose ()
|
||||||
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user