mirror of
https://github.com/crskycode/GARbro.git
synced 2026-06-06 05:38:48 +08:00
(Favorite): support TLG format within HZC
This commit is contained in:
@@ -69,6 +69,12 @@ namespace GameRes.Formats.FVP
|
||||
if (null == image_info)
|
||||
return null;
|
||||
}
|
||||
// This is a atlas image, all clips are placed into a single TLG image
|
||||
if (file.View.AsciiEqual (0x2C, "TLG"))
|
||||
return null;
|
||||
// This is a diff image
|
||||
if (0x64 == file.View.ReadByte (0x2C))
|
||||
return null;
|
||||
int count = file.View.ReadInt32 (0x20);
|
||||
if (0 == count)
|
||||
count = 1;
|
||||
|
||||
@@ -28,6 +28,8 @@ using GameRes.Utility;
|
||||
using System;
|
||||
using System.ComponentModel.Composition;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Windows;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
|
||||
@@ -66,14 +68,111 @@ namespace GameRes.Formats.FVP
|
||||
};
|
||||
}
|
||||
|
||||
private static ImageFormat s_TlgFormat = null;
|
||||
|
||||
public override ImageData Read (IBinaryStream stream, ImageMetaData info)
|
||||
{
|
||||
stream.Position = 0x2C;
|
||||
PixelFormat format = PixelFormats.Bgra32;
|
||||
WriteableBitmap bitmap = null;
|
||||
if (0x64 == stream.PeekByte ())
|
||||
{
|
||||
// This is a diff image, try to read base image
|
||||
stream.Position += 1;
|
||||
var name = stream.ReadCString (Encoding.UTF8);
|
||||
if (!string.IsNullOrEmpty (name))
|
||||
{
|
||||
var entry = VFS.FindFile (Path.ChangeExtension (name, "hzc"));
|
||||
if (null != entry)
|
||||
{
|
||||
var decoder = VFS.OpenImage (entry);
|
||||
var image = decoder.Image;
|
||||
if (null == image)
|
||||
throw new InvalidFormatException ("Failed to decode base image.");
|
||||
var converted = image.Bitmap;
|
||||
if (converted.Format != format)
|
||||
converted = new FormatConvertedBitmap (converted, format, null, 0);
|
||||
var stride = converted.PixelWidth * 4;
|
||||
var size = stride * converted.PixelHeight;
|
||||
var pixels = new byte[size];
|
||||
converted.CopyPixels (pixels, stride, 0);
|
||||
bitmap = new WriteableBitmap (converted.PixelWidth, converted.PixelHeight,
|
||||
ImageData.DefaultDpiX, ImageData.DefaultDpiY, format, null);
|
||||
var rect = new Int32Rect (0, 0, converted.PixelWidth, converted.PixelHeight);
|
||||
bitmap.WritePixels (rect, pixels, stride, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (stream.ReadBytes (3).AsciiEqual ("TLG"))
|
||||
{
|
||||
// Read the TLG image
|
||||
var tlg_stream = new BinaryStream (new StreamRegion (stream.AsStream, stream.Position-3, true), stream.Name);
|
||||
if (null == s_TlgFormat)
|
||||
s_TlgFormat = FindByTag ("TLG");
|
||||
var tlg_info = s_TlgFormat.ReadMetaData (tlg_stream);
|
||||
var image = s_TlgFormat.Read (tlg_stream, tlg_info);
|
||||
// No base image
|
||||
if (null == bitmap)
|
||||
return image;
|
||||
// Size should be the same as the base image
|
||||
if (image.Width != bitmap.PixelWidth || image.Height != bitmap.PixelHeight)
|
||||
return image;
|
||||
// Blend two images
|
||||
var converted = image.Bitmap;
|
||||
if (converted.Format != format)
|
||||
converted = new FormatConvertedBitmap (converted, format, null, 0);
|
||||
var rect = new Int32Rect (0, 0, converted.PixelWidth, converted.PixelHeight);
|
||||
BlendBitmap (converted, rect, bitmap, 0, 0);
|
||||
bitmap.Freeze ();
|
||||
return new ImageData (bitmap, tlg_info);
|
||||
}
|
||||
var meta = (HzcMetaData)info;
|
||||
stream.Position = 12 + meta.HeaderSize;
|
||||
using (var decoder = new HzcDecoder (stream, meta, true))
|
||||
return decoder.Image;
|
||||
}
|
||||
|
||||
void BlendBitmap (BitmapSource bitmap, Int32Rect source, WriteableBitmap output, int x, int y)
|
||||
{
|
||||
int src_stride = source.Width * 4;
|
||||
var pixels = new byte[src_stride * source.Height];
|
||||
bitmap.CopyPixels (source, pixels, src_stride, 0);
|
||||
unsafe
|
||||
{
|
||||
int dst_stride = output.BackBufferStride;
|
||||
int offset = y * dst_stride + x * 4;
|
||||
byte* buffer = (byte*)(output.BackBuffer + offset);
|
||||
int src = 0;
|
||||
for (int h = 0; h < source.Height; ++h)
|
||||
{
|
||||
int dst = 0;
|
||||
for (int w = 0; w < source.Width; ++w)
|
||||
{
|
||||
byte src_alpha = pixels[src+3];
|
||||
if (src_alpha > 0)
|
||||
{
|
||||
if (0xFF == src_alpha || 0 == buffer[dst+3])
|
||||
{
|
||||
buffer[dst ] = pixels[src];
|
||||
buffer[dst+1] = pixels[src+1];
|
||||
buffer[dst+2] = pixels[src+2];
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer[dst+0] = (byte)((pixels[src+0] * src_alpha + buffer[dst+0] * (0xFF - src_alpha)) / 0xFF);
|
||||
buffer[dst+1] = (byte)((pixels[src+1] * src_alpha + buffer[dst+1] * (0xFF - src_alpha)) / 0xFF);
|
||||
buffer[dst+2] = (byte)((pixels[src+2] * src_alpha + buffer[dst+2] * (0xFF - src_alpha)) / 0xFF);
|
||||
}
|
||||
buffer[dst+3] = src_alpha;
|
||||
}
|
||||
dst += 4;
|
||||
src += 4;
|
||||
}
|
||||
buffer += dst_stride;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void Write (Stream file, ImageData image)
|
||||
{
|
||||
throw new System.NotImplementedException ("HzcFormat.Write not implemented");
|
||||
|
||||
Reference in New Issue
Block a user