mirror of
https://github.com/crskycode/GARbro.git
synced 2026-07-08 01:30:18 +08:00
improved layered IAR images composition.
This commit is contained in:
@@ -213,11 +213,14 @@ namespace GameRes.Formats.Sas5
|
|||||||
|
|
||||||
IarImage CombineLayers (IarImage layers, IarArchive iarc)
|
IarImage CombineLayers (IarImage layers, IarArchive iarc)
|
||||||
{
|
{
|
||||||
|
layers.Info.Stride = (int)layers.Info.Width * 4;
|
||||||
|
layers.Info.BPP = 32;
|
||||||
|
var pixels = new byte[layers.Info.Stride * (int)layers.Info.Height];
|
||||||
|
var output = new IarImage (layers.Info, pixels);
|
||||||
using (var mem = new MemoryStream (layers.Data))
|
using (var mem = new MemoryStream (layers.Data))
|
||||||
using (var input = new BinaryReader (mem))
|
using (var input = new BinaryReader (mem))
|
||||||
{
|
{
|
||||||
int offset_x = 0, offset_y = 0;
|
int offset_x = 0, offset_y = 0;
|
||||||
IarImage output = null;
|
|
||||||
var dir = (List<Entry>)iarc.Dir;
|
var dir = (List<Entry>)iarc.Dir;
|
||||||
while (input.BaseStream.Position < input.BaseStream.Length)
|
while (input.BaseStream.Position < input.BaseStream.Length)
|
||||||
{
|
{
|
||||||
@@ -230,27 +233,23 @@ namespace GameRes.Formats.Sas5
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x00:
|
case 0x00:
|
||||||
|
case 0x20:
|
||||||
{
|
{
|
||||||
int index = input.ReadInt32();
|
int index = input.ReadInt32();
|
||||||
if (index >= dir.Count)
|
if (index < 0 || index >= dir.Count)
|
||||||
throw new InvalidFormatException ("Invalid image layer index");
|
throw new InvalidFormatException ("Invalid image layer index");
|
||||||
var layer = new IarImage (iarc, dir[index]);
|
var layer = new IarImage (iarc, dir[index]);
|
||||||
layer.Info.OffsetX -= offset_x;
|
layer.Info.OffsetX -= offset_x;
|
||||||
layer.Info.OffsetY -= offset_y;
|
layer.Info.OffsetY -= offset_y;
|
||||||
if (null == output)
|
if (0x20 == cmd)
|
||||||
{
|
output.ApplyMask (layer);
|
||||||
output = layer;
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
output.Blend (layer);
|
output.Blend (layer);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x20:
|
|
||||||
default:
|
default:
|
||||||
Trace.WriteLine (string.Format ("Unknown layer type 0x%02X", cmd), "IAR");
|
Trace.WriteLine (string.Format ("Unknown layer type 0x{0:X2}", cmd), "IAR");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -328,6 +327,9 @@ namespace GameRes.Formats.Sas5
|
|||||||
|
|
||||||
public void Blend (IarImage overlay)
|
public void Blend (IarImage overlay)
|
||||||
{
|
{
|
||||||
|
int pixel_size = Info.Stride / (int)Info.Width;
|
||||||
|
if (pixel_size < 4)
|
||||||
|
return;
|
||||||
var self = new Rectangle (-Info.OffsetX, -Info.OffsetY, (int)Info.Width, (int)Info.Height);
|
var self = new Rectangle (-Info.OffsetX, -Info.OffsetY, (int)Info.Width, (int)Info.Height);
|
||||||
var src = new Rectangle (-overlay.Info.OffsetX, -overlay.Info.OffsetY,
|
var src = new Rectangle (-overlay.Info.OffsetX, -overlay.Info.OffsetY,
|
||||||
(int)overlay.Info.Width, (int)overlay.Info.Height);
|
(int)overlay.Info.Width, (int)overlay.Info.Height);
|
||||||
@@ -338,12 +340,11 @@ namespace GameRes.Formats.Sas5
|
|||||||
src.Y = blend.Top - src.Top;
|
src.Y = blend.Top - src.Top;
|
||||||
src.Width = blend.Width;
|
src.Width = blend.Width;
|
||||||
src.Height= blend.Height;
|
src.Height= blend.Height;
|
||||||
int x = blend.Left - self.Left;
|
|
||||||
int y = blend.Top - self.Top;
|
|
||||||
if (src.Width <= 0 || src.Height <= 0)
|
if (src.Width <= 0 || src.Height <= 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
int pixel_size = Info.Stride / (int)Info.Width;
|
int x = blend.Left - self.Left;
|
||||||
|
int y = blend.Top - self.Top;
|
||||||
int dst = y * Info.Stride + x * pixel_size;
|
int dst = y * Info.Stride + x * pixel_size;
|
||||||
int ov = src.Top * overlay.Info.Stride + src.Left * pixel_size;
|
int ov = src.Top * overlay.Info.Stride + src.Left * pixel_size;
|
||||||
for (int row = 0; row < src.Height; ++row)
|
for (int row = 0; row < src.Height; ++row)
|
||||||
@@ -351,9 +352,9 @@ namespace GameRes.Formats.Sas5
|
|||||||
for (int col = 0; col < src.Width; ++col)
|
for (int col = 0; col < src.Width; ++col)
|
||||||
{
|
{
|
||||||
int src_pixel = ov + col*pixel_size;
|
int src_pixel = ov + col*pixel_size;
|
||||||
if (pixel_size > 3 && overlay.Data[src_pixel+3] > 0)
|
int src_alpha = overlay.Data[src_pixel+3];
|
||||||
|
if (src_alpha > 0)
|
||||||
{
|
{
|
||||||
int src_alpha = overlay.Data[src_pixel+3];
|
|
||||||
int dst_pixel = dst + col*pixel_size;
|
int dst_pixel = dst + col*pixel_size;
|
||||||
if (0xFF == src_alpha || 0 == m_output[dst_pixel+3])
|
if (0xFF == src_alpha || 0 == m_output[dst_pixel+3])
|
||||||
{
|
{
|
||||||
@@ -375,6 +376,41 @@ namespace GameRes.Formats.Sas5
|
|||||||
ov += overlay.Info.Stride;
|
ov += overlay.Info.Stride;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void ApplyMask (IarImage mask)
|
||||||
|
{
|
||||||
|
int pixel_size = Info.Stride / (int)Info.Width;
|
||||||
|
if (pixel_size < 4 || mask.Info.BPP != 8)
|
||||||
|
return;
|
||||||
|
var self = new Rectangle (-Info.OffsetX, -Info.OffsetY, (int)Info.Width, (int)Info.Height);
|
||||||
|
var mask_region = new Rectangle (-mask.Info.OffsetX, -mask.Info.OffsetY,
|
||||||
|
(int)mask.Info.Width, (int)mask.Info.Height);
|
||||||
|
var masked = Rectangle.Intersect (self, mask_region);
|
||||||
|
if (masked.IsEmpty)
|
||||||
|
return;
|
||||||
|
mask_region.X = masked.Left - mask_region.Left;
|
||||||
|
mask_region.Y = masked.Top - mask_region.Top;
|
||||||
|
mask_region.Width = masked.Width;
|
||||||
|
mask_region.Height= masked.Height;
|
||||||
|
if (mask_region.Width <= 0 || mask_region.Height <= 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
int x = masked.Left - self.Left;
|
||||||
|
int y = masked.Top - self.Top;
|
||||||
|
int dst = y * Info.Stride + x * pixel_size;
|
||||||
|
int src = mask_region.Top * mask.Info.Stride + mask_region.Left;
|
||||||
|
for (int row = 0; row < mask_region.Height; ++row)
|
||||||
|
{
|
||||||
|
int dst_pixel = dst+3;
|
||||||
|
for (int col = 0; col < mask_region.Width; ++col)
|
||||||
|
{
|
||||||
|
m_output[dst_pixel] = mask.Data[src+col];
|
||||||
|
dst_pixel += pixel_size;
|
||||||
|
}
|
||||||
|
dst += Info.Stride;
|
||||||
|
src += mask.Info.Stride;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal sealed class IarDecompressor : IDisposable
|
internal sealed class IarDecompressor : IDisposable
|
||||||
|
|||||||
Reference in New Issue
Block a user