mirror of
https://github.com/crskycode/GARbro.git
synced 2026-07-08 01:30:18 +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)
|
if (null == image_info)
|
||||||
return null;
|
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);
|
int count = file.View.ReadInt32 (0x20);
|
||||||
if (0 == count)
|
if (0 == count)
|
||||||
count = 1;
|
count = 1;
|
||||||
|
|||||||
@@ -28,6 +28,8 @@ using GameRes.Utility;
|
|||||||
using System;
|
using System;
|
||||||
using System.ComponentModel.Composition;
|
using System.ComponentModel.Composition;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Text;
|
||||||
|
using System.Windows;
|
||||||
using System.Windows.Media;
|
using System.Windows.Media;
|
||||||
using System.Windows.Media.Imaging;
|
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)
|
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;
|
var meta = (HzcMetaData)info;
|
||||||
stream.Position = 12 + meta.HeaderSize;
|
stream.Position = 12 + meta.HeaderSize;
|
||||||
using (var decoder = new HzcDecoder (stream, meta, true))
|
using (var decoder = new HzcDecoder (stream, meta, true))
|
||||||
return decoder.Image;
|
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)
|
public override void Write (Stream file, ImageData image)
|
||||||
{
|
{
|
||||||
throw new System.NotImplementedException ("HzcFormat.Write not implemented");
|
throw new System.NotImplementedException ("HzcFormat.Write not implemented");
|
||||||
|
|||||||
Reference in New Issue
Block a user