mirror of
https://github.com/crskycode/GARbro.git
synced 2024-11-26 23:24:00 +08:00
(Gx4Lib): support diff images.
This commit is contained in:
parent
8f21e7558a
commit
bd79789a30
@ -23,6 +23,8 @@
|
||||
// IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.Composition;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
@ -32,6 +34,13 @@ using GameRes.Utility;
|
||||
|
||||
namespace GameRes.Formats.Unity.Gx4Lib
|
||||
{
|
||||
internal class VisualDiffData
|
||||
{
|
||||
public string BaseFileName;
|
||||
public int PosX;
|
||||
public int PosY;
|
||||
}
|
||||
|
||||
[Export(typeof(ArchiveFormat))]
|
||||
public class DatOpener : ArchiveFormat
|
||||
{
|
||||
@ -41,6 +50,8 @@ namespace GameRes.Formats.Unity.Gx4Lib
|
||||
public override bool IsHierarchic { get { return false; } }
|
||||
public override bool CanWrite { get { return false; } }
|
||||
|
||||
Lazy<Dictionary<string, VisualDiffData>> DefaultVisualMap = new Lazy<Dictionary<string, VisualDiffData>> (ReadVisualData);
|
||||
|
||||
public override ArcFile TryOpen (ArcView file)
|
||||
{
|
||||
uint index_size = file.View.ReadUInt32 (0);
|
||||
@ -103,6 +114,25 @@ namespace GameRes.Formats.Unity.Gx4Lib
|
||||
int buf_width = input.ReadInt32();
|
||||
int buf_height = input.ReadInt32();
|
||||
var info = new ImageMetaData { Width = width, Height = height, BPP = 32 };
|
||||
if (DefaultVisualMap.Value.ContainsKey (entry.Name))
|
||||
{
|
||||
var diff_info = DefaultVisualMap.Value[entry.Name];
|
||||
if (VFS.FileExists (diff_info.BaseFileName))
|
||||
{
|
||||
var base_entry = VFS.FindFile (diff_info.BaseFileName);
|
||||
using (var visbase = VFS.OpenImage (base_entry))
|
||||
{
|
||||
var base_decoder = visbase as Gx4ImageDecoder;
|
||||
if (base_decoder != null)
|
||||
{
|
||||
info.OffsetX = diff_info.PosX;
|
||||
info.OffsetY = diff_info.PosY;
|
||||
var pixels = base_decoder.ReadPixels();
|
||||
return new Gx4OverlayDecoder (pixels, base_decoder.Info, input, info);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return new Gx4ImageDecoder (input, info);
|
||||
}
|
||||
|
||||
@ -204,26 +234,97 @@ namespace GameRes.Formats.Unity.Gx4Lib
|
||||
bits >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
internal static Dictionary<string, VisualDiffData> ReadVisualData ()
|
||||
{
|
||||
var map = new Dictionary<string, VisualDiffData>();
|
||||
try
|
||||
{
|
||||
FormatCatalog.Instance.ReadFileList ("gx4_bsz_visual.lst", (line) => {
|
||||
var parts = line.Split (':', ',');
|
||||
if (parts.Length > 3)
|
||||
{
|
||||
var diff = new VisualDiffData { BaseFileName = parts[1] };
|
||||
if (int.TryParse (parts[2], out diff.PosX) && int.TryParse (parts[3], out diff.PosY))
|
||||
map[parts[0]] = diff;
|
||||
}
|
||||
});
|
||||
}
|
||||
catch { /* ignore errors */ }
|
||||
return map;
|
||||
}
|
||||
}
|
||||
|
||||
internal class Gx4ImageDecoder : BinaryImageDecoder
|
||||
{
|
||||
public int Stride { get; private set; }
|
||||
|
||||
public Gx4ImageDecoder (IBinaryStream input, ImageMetaData info) : base (input, info)
|
||||
{
|
||||
Stride = (int)info.Width * 4;
|
||||
}
|
||||
|
||||
protected override ImageData GetImageData ()
|
||||
public byte[] ReadPixels ()
|
||||
{
|
||||
m_input.Position = 0x10;
|
||||
int stride = (int)Info.Width * 4;
|
||||
var pixels = m_input.ReadBytes (stride * (int)Info.Height);
|
||||
var pixels = m_input.ReadBytes (Stride * (int)Info.Height);
|
||||
for (int i = 0; i < pixels.Length; i += 4)
|
||||
{
|
||||
byte t = pixels[i];
|
||||
pixels[i] = pixels[i+2];
|
||||
pixels[i+2] = t;
|
||||
}
|
||||
return ImageData.CreateFlipped (Info, PixelFormats.Bgra32, null, pixels, stride);
|
||||
return pixels;
|
||||
}
|
||||
|
||||
protected override ImageData GetImageData ()
|
||||
{
|
||||
var pixels = ReadPixels();
|
||||
return ImageData.CreateFlipped (Info, PixelFormats.Bgra32, null, pixels, Stride);
|
||||
}
|
||||
}
|
||||
|
||||
internal class Gx4OverlayDecoder : BinaryImageDecoder
|
||||
{
|
||||
byte[] m_pixels;
|
||||
|
||||
ImageMetaData OverlayInfo { get; set; }
|
||||
|
||||
public Gx4OverlayDecoder (byte[] pixels, ImageMetaData info, IBinaryStream input, ImageMetaData overlay_info)
|
||||
: base (input, info)
|
||||
{
|
||||
m_pixels = pixels;
|
||||
OverlayInfo = overlay_info;
|
||||
}
|
||||
|
||||
protected override ImageData GetImageData ()
|
||||
{
|
||||
m_input.Position = 0x10;
|
||||
int base_stride = (int)Info.Width * 4;
|
||||
int diff_stride = (int)OverlayInfo.Width * 4;
|
||||
var diff = m_input.ReadBytes (diff_stride * (int)OverlayInfo.Height);
|
||||
int dst_line = m_pixels.Length - base_stride * (OverlayInfo.OffsetY + 1) + OverlayInfo.OffsetX * 4;
|
||||
int src_line = diff.Length - diff_stride;
|
||||
for (int y = 0; y < (int)OverlayInfo.Height; ++y)
|
||||
{
|
||||
int dst = dst_line;
|
||||
int src = src_line;
|
||||
for (int x = 0; x < (int)OverlayInfo.Width; ++x)
|
||||
{
|
||||
if (!(0 == diff[src] && 0 == diff[src+1] && 0 == diff[src+2] && 0xFF == diff[src+3]))
|
||||
{
|
||||
m_pixels[dst ] = diff[src+2];
|
||||
m_pixels[dst+1] = diff[src+1];
|
||||
m_pixels[dst+2] = diff[src ];
|
||||
m_pixels[dst+3] = diff[src+3];
|
||||
}
|
||||
dst += 4;
|
||||
src += 4;
|
||||
}
|
||||
dst_line -= base_stride;
|
||||
src_line -= diff_stride;
|
||||
}
|
||||
return ImageData.CreateFlipped (Info, PixelFormats.Bgra32, null, m_pixels, base_stride);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user