(Favorite): support TLG format within HZC

This commit is contained in:
nanami5270
2026-01-26 15:13:38 +08:00
parent c77112e586
commit dba750ba39
2 changed files with 105 additions and 0 deletions

View File

@@ -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;

View File

@@ -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");