mirror of
https://github.com/crskycode/GARbro.git
synced 2024-12-24 03:44:13 +08:00
more IImageDecoder implementations.
This commit is contained in:
parent
c771b13d4e
commit
02e1ee11dd
@ -27,6 +27,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.Composition;
|
||||
using System.IO;
|
||||
using System.Windows.Media;
|
||||
using GameRes.Utility;
|
||||
|
||||
namespace GameRes.Formats.Lilim
|
||||
@ -92,7 +93,7 @@ namespace GameRes.Formats.Lilim
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
var entry = new AbmEntry {
|
||||
Name = string.Format ("{0}#{1:D4}.tga", base_name, i),
|
||||
Name = string.Format ("{0}#{1:D4}", base_name, i),
|
||||
Type = "image",
|
||||
Offset = next_offset,
|
||||
Index = i,
|
||||
@ -123,12 +124,12 @@ namespace GameRes.Formats.Lilim
|
||||
return new AbmArchive (file, this, dir, image_info);
|
||||
}
|
||||
|
||||
public override Stream OpenEntry (ArcFile arc, Entry entry)
|
||||
public override IImageDecoder OpenImage (ArcFile arc, Entry entry)
|
||||
{
|
||||
var abm = arc as AbmArchive;
|
||||
var frame = entry as AbmEntry;
|
||||
if (null == abm || null == frame)
|
||||
return arc.File.CreateStream (entry.Offset, entry.Size);
|
||||
return base.OpenImage (arc, entry);
|
||||
|
||||
var frame_info = abm.FrameInfo;
|
||||
if (frame.Index != 0)
|
||||
@ -136,40 +137,45 @@ namespace GameRes.Formats.Lilim
|
||||
frame_info = frame_info.Clone();
|
||||
frame_info.FrameOffset = (uint)frame.Offset;
|
||||
}
|
||||
using (var input = arc.File.CreateStream (0, (uint)arc.File.MaxOffset))
|
||||
using (var reader = new AbmReader (input, frame_info))
|
||||
{
|
||||
// emulate TGA image
|
||||
var header = new byte[0x12];
|
||||
header[2] = 2;
|
||||
LittleEndian.Pack ((ushort)frame_info.Width, header, 0xC);
|
||||
LittleEndian.Pack ((ushort)frame_info.Height, header, 0xE);
|
||||
header[0x10] = (byte)reader.BPP;
|
||||
header[0x11] = 0x20;
|
||||
var pixels = reader.Unpack();
|
||||
return new PrefixStream (header, new MemoryStream (pixels));
|
||||
}
|
||||
var input = arc.File.CreateStream (0, (uint)arc.File.MaxOffset);
|
||||
return new AbmReader (input, frame_info);
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class AbmReader : IDisposable
|
||||
internal sealed class AbmReader : IImageDecoder
|
||||
{
|
||||
IBinaryStream m_input;
|
||||
byte[] m_output;
|
||||
AbmImageData m_info;
|
||||
ImageData m_image;
|
||||
int m_bpp;
|
||||
|
||||
public byte[] Data { get { return m_output; } }
|
||||
public int BPP { get { return m_bpp; } }
|
||||
public Stream Source { get { return m_input.AsStream; } }
|
||||
public ImageFormat SourceFormat { get { return null; } }
|
||||
public ImageMetaData Info { get { return m_info; } }
|
||||
public ImageData Image
|
||||
{
|
||||
get
|
||||
{
|
||||
if (null == m_image)
|
||||
m_image = ReadImage();
|
||||
return m_image;
|
||||
}
|
||||
}
|
||||
|
||||
public AbmReader (IBinaryStream file, AbmImageData info)
|
||||
{
|
||||
m_info = info;
|
||||
m_input = file;
|
||||
}
|
||||
|
||||
ImageData ReadImage ()
|
||||
{
|
||||
if (2 == m_info.Mode)
|
||||
{
|
||||
m_bpp = 32;
|
||||
file.Position = m_info.BaseOffset;
|
||||
m_output = UnpackV2 (file);
|
||||
m_input.Position = m_info.BaseOffset;
|
||||
m_output = UnpackV2 (m_input);
|
||||
}
|
||||
else if (1 == m_info.Mode || 32 == m_info.Mode || 24 == m_info.Mode)
|
||||
{
|
||||
@ -180,23 +186,23 @@ namespace GameRes.Formats.Lilim
|
||||
|
||||
int total_length = (int)(m_info.Width * m_info.Height * m_bpp / 8);
|
||||
m_output = new byte[total_length];
|
||||
file.Position = m_info.BaseOffset;
|
||||
m_input.Position = m_info.BaseOffset;
|
||||
if (1 == m_info.Mode)
|
||||
{
|
||||
if (total_length != file.Read (m_output, 0, (total_length)))
|
||||
if (total_length != m_input.Read (m_output, 0, (total_length)))
|
||||
throw new EndOfStreamException ();
|
||||
}
|
||||
else if (24 == m_bpp)
|
||||
UnpackStream24 (file, m_output, total_length);
|
||||
UnpackStream24 (m_input, m_output, total_length);
|
||||
else
|
||||
UnpackStream32 (file, m_output, total_length);
|
||||
UnpackStream32 (m_input, m_output, total_length);
|
||||
}
|
||||
else
|
||||
throw new NotImplementedException();
|
||||
if (0 != m_info.FrameOffset)
|
||||
{
|
||||
m_input = file;
|
||||
}
|
||||
m_output = Unpack();
|
||||
PixelFormat format = 24 == m_bpp ? PixelFormats.Bgr24 : PixelFormats.Bgra32;
|
||||
return ImageData.Create (m_info, format, null, m_output);
|
||||
}
|
||||
|
||||
int frame_x;
|
||||
@ -204,11 +210,8 @@ namespace GameRes.Formats.Lilim
|
||||
int frame_w;
|
||||
int frame_h;
|
||||
|
||||
public byte[] Unpack ()
|
||||
byte[] Unpack ()
|
||||
{
|
||||
if (null == m_input)
|
||||
return m_output;
|
||||
|
||||
m_input.Position = m_info.FrameOffset;
|
||||
if (1 == m_info.Mode)
|
||||
return UnpackStream24 (m_input, m_output, m_output.Length);
|
||||
@ -334,8 +337,14 @@ namespace GameRes.Formats.Lilim
|
||||
}
|
||||
|
||||
#region IDisposable Members
|
||||
bool m_disposed = false;
|
||||
public void Dispose ()
|
||||
{
|
||||
if (!m_disposed)
|
||||
{
|
||||
m_input.Dispose();
|
||||
m_disposed = true;
|
||||
}
|
||||
GC.SuppressFinalize (this);
|
||||
}
|
||||
#endregion
|
||||
|
@ -76,11 +76,7 @@ namespace GameRes.Formats.Lilim
|
||||
public override ImageData Read (IBinaryStream stream, ImageMetaData info)
|
||||
{
|
||||
using (var reader = new AbmReader (stream, (AbmImageData)info))
|
||||
{
|
||||
var pixels = reader.Unpack();
|
||||
PixelFormat format = 32 == reader.BPP ? PixelFormats.Bgra32 : PixelFormats.Bgr24;
|
||||
return ImageData.Create (info, format, null, pixels);
|
||||
}
|
||||
return reader.Image;
|
||||
}
|
||||
|
||||
public override void Write (Stream file, ImageData image)
|
||||
|
@ -68,7 +68,7 @@ namespace GameRes.Formats.Will
|
||||
BPP = 32,
|
||||
};
|
||||
var entry = new PnaEntry {
|
||||
Name = string.Format ("{0}#{1:D3}.tga", base_name, i),
|
||||
Name = string.Format ("{0}#{1:D3}", base_name, i),
|
||||
Size = size,
|
||||
Offset = current_offset,
|
||||
Info = imginfo,
|
||||
@ -83,14 +83,47 @@ namespace GameRes.Formats.Will
|
||||
return new ArcFile (file, this, dir);
|
||||
}
|
||||
|
||||
public override Stream OpenEntry (ArcFile arc, Entry entry)
|
||||
public override IImageDecoder OpenImage (ArcFile arc, Entry entry)
|
||||
{
|
||||
var pent = entry as PnaEntry;
|
||||
if (null == pent)
|
||||
return base.OpenEntry (arc, entry);
|
||||
ImageData image;
|
||||
using (var input = arc.File.CreateStream (entry.Offset, entry.Size))
|
||||
image = ImageFormat.Read (input);
|
||||
var pent = (PnaEntry)entry;
|
||||
var input = arc.File.CreateStream (entry.Offset, entry.Size);
|
||||
return new PnaDecoder (input, pent.Info);
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class PnaDecoder : IImageDecoder
|
||||
{
|
||||
IBinaryStream m_input;
|
||||
ImageMetaData m_info;
|
||||
ImageData m_image;
|
||||
|
||||
public Stream Source { get { m_input.Position = 0; return m_input.AsStream; } }
|
||||
public ImageFormat SourceFormat { get { return null; } }
|
||||
public ImageMetaData Info { get { return m_info; } }
|
||||
public ImageData Image
|
||||
{
|
||||
get
|
||||
{
|
||||
if (null == m_image)
|
||||
{
|
||||
var pixels = ReadPixels();
|
||||
m_image = ImageData.Create (m_info, PixelFormats.Bgra32, null, pixels);
|
||||
}
|
||||
return m_image;
|
||||
}
|
||||
}
|
||||
|
||||
public PnaDecoder (IBinaryStream input, ImageMetaData info)
|
||||
{
|
||||
m_input = input;
|
||||
m_info = info;
|
||||
}
|
||||
|
||||
byte[] ReadPixels ()
|
||||
{
|
||||
var image = ImageFormat.Read (m_input);
|
||||
if (null == image)
|
||||
throw new InvalidFormatException();
|
||||
var bitmap = image.Bitmap;
|
||||
if (bitmap.Format.BitsPerPixel != 32)
|
||||
{
|
||||
@ -111,7 +144,17 @@ namespace GameRes.Formats.Will
|
||||
pixels[i+2] = (byte)(pixels[i+2] * 0xFF / alpha);
|
||||
}
|
||||
}
|
||||
return TgaStream.Create (pent.Info, pixels);
|
||||
return pixels;
|
||||
}
|
||||
|
||||
bool m_disposed = false;
|
||||
public void Dispose ()
|
||||
{
|
||||
if (!m_disposed)
|
||||
{
|
||||
m_input.Dispose();
|
||||
m_disposed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user