implemented OpenImage methods for some image archives.

This commit is contained in:
morkt
2016-12-26 03:15:15 +04:00
parent c256563181
commit e1a0cca0fd
5 changed files with 223 additions and 70 deletions

View File

@@ -78,10 +78,10 @@ namespace GameRes.Formats.FVP
for (int i = 0; i < count; ++i)
{
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",
Offset = frame_size * i,
Size = 0x12 + (uint)frame_size,
Size = (uint)frame_size,
};
dir.Add (entry);
}
@@ -94,24 +94,33 @@ namespace GameRes.Formats.FVP
using (var input = arc.File.CreateStream (0xC+hzc.ImageInfo.HeaderSize))
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];
uint offset = 0;
for (;;)
{
if (pixels.Length != z.Read (pixels, 0, pixels.Length))
break;
throw new EndOfStreamException();
if (offset >= entry.Offset)
break;
offset += frame_size;
}
if (4 == hzc.ImageInfo.Type)
{
for (int i = 0; i < pixels.Length; ++i)
if (1 == pixels[i])
pixels[i] = 0xFF;
}
return TgaStream.Create (hzc.ImageInfo, pixels);
return new BinMemoryStream (pixels, entry.Name);
}
}
public override IImageDecoder OpenImage (ArcFile arc, Entry entry)
{
var hzc = (HzcArchive)arc;
var input = arc.File.CreateStream (0xC+hzc.ImageInfo.HeaderSize);
try
{
return new HzcDecoder (input, hzc.ImageInfo, entry);
}
catch
{
input.Dispose();
throw;
}
}
}

View File

@@ -69,32 +69,9 @@ namespace GameRes.Formats.FVP
public override ImageData Read (IBinaryStream stream, ImageMetaData 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;
using (var z = new ZLibStream (stream.AsStream, CompressionMode.Decompress, true))
{
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);
}
using (var decoder = new HzcDecoder (stream, meta, true))
return decoder.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");
}
}
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);
}
}
}