mirror of
https://github.com/crskycode/GARbro.git
synced 2026-07-08 01:30:18 +08:00
(GALX): support 8bpp images.
This commit is contained in:
@@ -33,8 +33,8 @@ namespace GameRes.Formats.LiveMaker
|
|||||||
{
|
{
|
||||||
internal class GalXEntry : Entry
|
internal class GalXEntry : Entry
|
||||||
{
|
{
|
||||||
public GalReader.Frame Frame;
|
|
||||||
public GalXMetaData Info;
|
public GalXMetaData Info;
|
||||||
|
public XmlNode Layers;
|
||||||
public bool AlphaOn;
|
public bool AlphaOn;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -42,7 +42,7 @@ namespace GameRes.Formats.LiveMaker
|
|||||||
public class GalXOpener : ArchiveFormat
|
public class GalXOpener : ArchiveFormat
|
||||||
{
|
{
|
||||||
public override string Tag { get { return "GAL/X"; } }
|
public override string Tag { get { return "GAL/X"; } }
|
||||||
public override string Description { get { return "LiveMaker engine multi-frame image"; } }
|
public override string Description { get { return "LiveMaker engine multi-frame image"; } }
|
||||||
public override uint Signature { get { return 0x656C6147; } } // 'GaleX200'
|
public override uint Signature { get { return 0x656C6147; } } // 'GaleX200'
|
||||||
public override bool IsHierarchic { get { return false; } }
|
public override bool IsHierarchic { get { return false; } }
|
||||||
public override bool CanWrite { get { return false; } }
|
public override bool CanWrite { get { return false; } }
|
||||||
@@ -62,27 +62,18 @@ namespace GameRes.Formats.LiveMaker
|
|||||||
foreach (XmlNode node in info.FrameXml.SelectNodes ("Frame"))
|
foreach (XmlNode node in info.FrameXml.SelectNodes ("Frame"))
|
||||||
{
|
{
|
||||||
var layers = node.SelectSingleNode ("Layers");
|
var layers = node.SelectSingleNode ("Layers");
|
||||||
var attr = layers.Attributes;
|
|
||||||
int layer_count = Int32.Parse (attr["Count"].Value);
|
|
||||||
var frame = new GalReader.Frame (layer_count);
|
|
||||||
frame.Width = Int32.Parse (attr["Width"].Value);
|
|
||||||
frame.Height = Int32.Parse (attr["Height"].Value);
|
|
||||||
frame.BPP = Int32.Parse (attr["Bpp"].Value);
|
|
||||||
frame.SetStride();
|
|
||||||
var entry = new GalXEntry {
|
var entry = new GalXEntry {
|
||||||
Name = string.Format ("{0}#{1:D4}", base_name, dir.Count),
|
Name = string.Format ("{0}#{1:D4}", base_name, dir.Count),
|
||||||
Type = "image",
|
Type = "image",
|
||||||
Offset = gal.Position,
|
Offset = gal.Position,
|
||||||
Frame = frame,
|
Layers = layers,
|
||||||
Info = info,
|
Info = info,
|
||||||
};
|
};
|
||||||
if (frame.BPP <= 8)
|
var nodes = layers.SelectNodes ("Layer");
|
||||||
gal.Seek ((1 << frame.BPP) * 4, SeekOrigin.Current);
|
entry.AlphaOn = nodes.Count > 0 && nodes[0].Attributes["AlphaOn"].Value != "0";
|
||||||
bool alpha_set = false;
|
foreach (XmlNode layer in nodes)
|
||||||
foreach (XmlNode layer in layers.SelectNodes ("Layer"))
|
|
||||||
{
|
{
|
||||||
attr = layer.Attributes;
|
bool alpha_on = layer.Attributes["AlphaOn"].Value != "0";
|
||||||
bool alpha_on = attr["AlphaOn"].Value != "0";
|
|
||||||
uint layer_size = gal.ReadUInt32();
|
uint layer_size = gal.ReadUInt32();
|
||||||
gal.Seek (layer_size, SeekOrigin.Current);
|
gal.Seek (layer_size, SeekOrigin.Current);
|
||||||
if (alpha_on)
|
if (alpha_on)
|
||||||
@@ -90,11 +81,6 @@ namespace GameRes.Formats.LiveMaker
|
|||||||
uint alpha_size = gal.ReadUInt32();
|
uint alpha_size = gal.ReadUInt32();
|
||||||
gal.Seek (alpha_size, SeekOrigin.Current);
|
gal.Seek (alpha_size, SeekOrigin.Current);
|
||||||
}
|
}
|
||||||
if (!alpha_set)
|
|
||||||
{
|
|
||||||
entry.AlphaOn = alpha_on;
|
|
||||||
alpha_set = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
entry.Size = (uint)(gal.Position - entry.Offset);
|
entry.Size = (uint)(gal.Position - entry.Offset);
|
||||||
dir.Add (entry);
|
dir.Add (entry);
|
||||||
@@ -137,7 +123,7 @@ namespace GameRes.Formats.LiveMaker
|
|||||||
|
|
||||||
public GalXDecoder (IBinaryStream input, GalXEntry entry) : base (input, entry.Info, 0)
|
public GalXDecoder (IBinaryStream input, GalXEntry entry) : base (input, entry.Info, 0)
|
||||||
{
|
{
|
||||||
m_frames.Add (entry.Frame);
|
m_frames.Add (GetFrameFromLayers (entry.Layers));
|
||||||
m_alpha_on = entry.AlphaOn;
|
m_alpha_on = entry.AlphaOn;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -146,8 +132,6 @@ namespace GameRes.Formats.LiveMaker
|
|||||||
var frame = m_frames[0];
|
var frame = m_frames[0];
|
||||||
frame.Layers.Clear();
|
frame.Layers.Clear();
|
||||||
m_input.Position = 0;
|
m_input.Position = 0;
|
||||||
if (frame.BPP <= 8)
|
|
||||||
frame.Palette = ImageFormat.ReadColorMap (m_input.AsStream, 1 << frame.BPP);
|
|
||||||
int layer_size = m_input.ReadInt32();
|
int layer_size = m_input.ReadInt32();
|
||||||
var layer = new Layer();
|
var layer = new Layer();
|
||||||
layer.Pixels = UnpackLayer (frame, layer_size);
|
layer.Pixels = UnpackLayer (frame, layer_size);
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
//! \date 2017 Dec 29
|
//! \date 2017 Dec 29
|
||||||
//! \brief LiveMaker GaleX image format.
|
//! \brief LiveMaker GaleX image format.
|
||||||
//
|
//
|
||||||
// Copyright (C) 2017 by morkt
|
// Copyright (C) 2017-2018 by morkt
|
||||||
//
|
//
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
// of this software and associated documentation files (the "Software"), to
|
// of this software and associated documentation files (the "Software"), to
|
||||||
@@ -27,6 +27,7 @@ using System;
|
|||||||
using System.ComponentModel.Composition;
|
using System.ComponentModel.Composition;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
|
using System.Windows.Media;
|
||||||
using System.Xml;
|
using System.Xml;
|
||||||
using GameRes.Compression;
|
using GameRes.Compression;
|
||||||
using GameRes.Utility;
|
using GameRes.Utility;
|
||||||
@@ -67,7 +68,7 @@ namespace GameRes.Formats.LiveMaker
|
|||||||
FrameCount = Int32.Parse (attr["Count"].Value),
|
FrameCount = Int32.Parse (attr["Count"].Value),
|
||||||
Shuffled = attr["Randomized"].Value != "0",
|
Shuffled = attr["Randomized"].Value != "0",
|
||||||
Compression = Int32.Parse (attr["CompType"].Value),
|
Compression = Int32.Parse (attr["CompType"].Value),
|
||||||
Mask = UInt32.Parse (attr["BGColor"].Value),
|
Mask = (uint)Int32.Parse (attr["BGColor"].Value),
|
||||||
BlockWidth = Int32.Parse (attr["BlockWidth"].Value),
|
BlockWidth = Int32.Parse (attr["BlockWidth"].Value),
|
||||||
BlockHeight = Int32.Parse (attr["BlockHeight"].Value),
|
BlockHeight = Int32.Parse (attr["BlockHeight"].Value),
|
||||||
DataOffset = header_size + 12,
|
DataOffset = header_size + 12,
|
||||||
@@ -123,22 +124,13 @@ namespace GameRes.Formats.LiveMaker
|
|||||||
{
|
{
|
||||||
m_input.Position = m_info.DataOffset;
|
m_input.Position = m_info.DataOffset;
|
||||||
var layers = FrameXml.SelectSingleNode ("Frame/Layers");
|
var layers = FrameXml.SelectSingleNode ("Frame/Layers");
|
||||||
var attr = layers.Attributes;
|
var frame = GetFrameFromLayers (layers);
|
||||||
int layer_count = Int32.Parse (attr["Count"].Value);
|
|
||||||
var frame = new Frame (layer_count);
|
|
||||||
frame.Width = Int32.Parse (attr["Width"].Value);
|
|
||||||
frame.Height = Int32.Parse (attr["Height"].Value);
|
|
||||||
frame.BPP = Int32.Parse (attr["Bpp"].Value);
|
|
||||||
frame.SetStride();
|
|
||||||
if (frame.BPP <= 8)
|
|
||||||
frame.Palette = ImageFormat.ReadColorMap (m_input.AsStream, 1 << frame.BPP);
|
|
||||||
m_frames.Add (frame);
|
m_frames.Add (frame);
|
||||||
|
|
||||||
var layer_nodes = layers.SelectNodes ("Layer");
|
var layer_nodes = layers.SelectNodes ("Layer");
|
||||||
foreach (XmlNode node in layer_nodes)
|
foreach (XmlNode node in layer_nodes)
|
||||||
{
|
{
|
||||||
attr = node.Attributes;
|
bool alpha_on = node.Attributes["AlphaOn"].Value != "0";
|
||||||
bool alpha_on = attr["AlphaOn"].Value != "0";
|
|
||||||
int layer_size = m_input.ReadInt32();
|
int layer_size = m_input.ReadInt32();
|
||||||
var layer = new Layer();
|
var layer = new Layer();
|
||||||
layer.Pixels = UnpackLayer (frame, layer_size);
|
layer.Pixels = UnpackLayer (frame, layer_size);
|
||||||
@@ -151,5 +143,42 @@ namespace GameRes.Formats.LiveMaker
|
|||||||
}
|
}
|
||||||
Flatten (0);
|
Flatten (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal Frame GetFrameFromLayers (XmlNode layers)
|
||||||
|
{
|
||||||
|
var attr = layers.Attributes;
|
||||||
|
int layer_count = Int32.Parse (attr["Count"].Value);
|
||||||
|
var frame = new Frame (layer_count);
|
||||||
|
frame.Width = Int32.Parse (attr["Width"].Value);
|
||||||
|
frame.Height = Int32.Parse (attr["Height"].Value);
|
||||||
|
frame.BPP = Int32.Parse (attr["Bpp"].Value);
|
||||||
|
frame.SetStride();
|
||||||
|
if (frame.BPP <= 8)
|
||||||
|
frame.Palette = ReadColorMap (layers.SelectSingleNode ("RGB").InnerText);
|
||||||
|
return frame;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static Color[] ReadColorMap (string rgb)
|
||||||
|
{
|
||||||
|
int colors = Math.Min (0x100, rgb.Length / 6);
|
||||||
|
var color_map = new Color[colors];
|
||||||
|
int pos = 0;
|
||||||
|
for (int i = 0; i < colors; ++i)
|
||||||
|
{
|
||||||
|
byte r = HexToByte (rgb, pos);
|
||||||
|
byte g = HexToByte (rgb, pos+2);
|
||||||
|
byte b = HexToByte (rgb, pos+4);
|
||||||
|
color_map[i] = Color.FromRgb (r, g, b);
|
||||||
|
pos += 6;
|
||||||
|
}
|
||||||
|
return color_map;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static byte HexToByte (string hex, int pos)
|
||||||
|
{
|
||||||
|
int hi = "0123456789ABCDEF".IndexOf (char.ToUpper (hex[pos]));
|
||||||
|
int lo = "0123456789ABCDEF".IndexOf (char.ToUpper (hex[pos+1]));
|
||||||
|
return (byte)(hi << 4 | lo);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user