From 7eb760d2347b8c10eb17287b236f8b77a6c58154 Mon Sep 17 00:00:00 2001 From: morkt Date: Wed, 28 Feb 2018 11:45:51 +0400 Subject: [PATCH] (GALX): support 8bpp images. --- ArcFormats/LiveMaker/ArcGALX.cs | 32 +++++------------- ArcFormats/LiveMaker/ImageGALX.cs | 55 +++++++++++++++++++++++-------- 2 files changed, 50 insertions(+), 37 deletions(-) diff --git a/ArcFormats/LiveMaker/ArcGALX.cs b/ArcFormats/LiveMaker/ArcGALX.cs index b8581744..f538f34a 100644 --- a/ArcFormats/LiveMaker/ArcGALX.cs +++ b/ArcFormats/LiveMaker/ArcGALX.cs @@ -33,8 +33,8 @@ namespace GameRes.Formats.LiveMaker { internal class GalXEntry : Entry { - public GalReader.Frame Frame; public GalXMetaData Info; + public XmlNode Layers; public bool AlphaOn; } @@ -42,7 +42,7 @@ namespace GameRes.Formats.LiveMaker public class GalXOpener : ArchiveFormat { 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 bool IsHierarchic { 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")) { 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 { Name = string.Format ("{0}#{1:D4}", base_name, dir.Count), Type = "image", Offset = gal.Position, - Frame = frame, + Layers = layers, Info = info, }; - if (frame.BPP <= 8) - gal.Seek ((1 << frame.BPP) * 4, SeekOrigin.Current); - bool alpha_set = false; - foreach (XmlNode layer in layers.SelectNodes ("Layer")) + var nodes = layers.SelectNodes ("Layer"); + entry.AlphaOn = nodes.Count > 0 && nodes[0].Attributes["AlphaOn"].Value != "0"; + foreach (XmlNode layer in nodes) { - attr = layer.Attributes; - bool alpha_on = attr["AlphaOn"].Value != "0"; + bool alpha_on = layer.Attributes["AlphaOn"].Value != "0"; uint layer_size = gal.ReadUInt32(); gal.Seek (layer_size, SeekOrigin.Current); if (alpha_on) @@ -90,11 +81,6 @@ namespace GameRes.Formats.LiveMaker uint alpha_size = gal.ReadUInt32(); gal.Seek (alpha_size, SeekOrigin.Current); } - if (!alpha_set) - { - entry.AlphaOn = alpha_on; - alpha_set = true; - } } entry.Size = (uint)(gal.Position - entry.Offset); dir.Add (entry); @@ -137,7 +123,7 @@ namespace GameRes.Formats.LiveMaker 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; } @@ -146,8 +132,6 @@ namespace GameRes.Formats.LiveMaker var frame = m_frames[0]; frame.Layers.Clear(); m_input.Position = 0; - if (frame.BPP <= 8) - frame.Palette = ImageFormat.ReadColorMap (m_input.AsStream, 1 << frame.BPP); int layer_size = m_input.ReadInt32(); var layer = new Layer(); layer.Pixels = UnpackLayer (frame, layer_size); diff --git a/ArcFormats/LiveMaker/ImageGALX.cs b/ArcFormats/LiveMaker/ImageGALX.cs index 57f1e9ae..6eb24729 100644 --- a/ArcFormats/LiveMaker/ImageGALX.cs +++ b/ArcFormats/LiveMaker/ImageGALX.cs @@ -2,7 +2,7 @@ //! \date 2017 Dec 29 //! \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 // of this software and associated documentation files (the "Software"), to @@ -27,6 +27,7 @@ using System; using System.ComponentModel.Composition; using System.IO; using System.Text.RegularExpressions; +using System.Windows.Media; using System.Xml; using GameRes.Compression; using GameRes.Utility; @@ -67,7 +68,7 @@ namespace GameRes.Formats.LiveMaker FrameCount = Int32.Parse (attr["Count"].Value), Shuffled = attr["Randomized"].Value != "0", 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), BlockHeight = Int32.Parse (attr["BlockHeight"].Value), DataOffset = header_size + 12, @@ -123,22 +124,13 @@ namespace GameRes.Formats.LiveMaker { m_input.Position = m_info.DataOffset; var layers = FrameXml.SelectSingleNode ("Frame/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 = ImageFormat.ReadColorMap (m_input.AsStream, 1 << frame.BPP); + var frame = GetFrameFromLayers (layers); m_frames.Add (frame); var layer_nodes = layers.SelectNodes ("Layer"); foreach (XmlNode node in layer_nodes) { - attr = node.Attributes; - bool alpha_on = attr["AlphaOn"].Value != "0"; + bool alpha_on = node.Attributes["AlphaOn"].Value != "0"; int layer_size = m_input.ReadInt32(); var layer = new Layer(); layer.Pixels = UnpackLayer (frame, layer_size); @@ -151,5 +143,42 @@ namespace GameRes.Formats.LiveMaker } 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); + } } }