Use family palettes for PCX textures
This commit is contained in:
parent
c14f74b108
commit
21b018298c
|
@ -1,20 +1,55 @@
|
|||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using System.Text;
|
||||
using Godot;
|
||||
|
||||
namespace KeepersCompound.TMV;
|
||||
|
||||
public partial class TextureLoader
|
||||
{
|
||||
// TODO: Support more types of PCX just in case
|
||||
// TODO: We need to load the palette from an external file!!!
|
||||
|
||||
// References:
|
||||
// - https://www.fileformat.info/format/pcx/egff.htm
|
||||
// - http://www.fysnet.net/pcxfile.htm
|
||||
private static Godot.ImageTexture LoadPcx(string path)
|
||||
private static ImageTexture LoadPcx(string path)
|
||||
{
|
||||
static Color[] LoadFamilyPalette(string famPath)
|
||||
{
|
||||
var numColors = 256;
|
||||
var bytesPerColor = 3;
|
||||
var paletteSize = numColors * bytesPerColor;
|
||||
var palette = new Color[numColors];
|
||||
|
||||
var options = new EnumerationOptions
|
||||
{
|
||||
MatchCasing = MatchCasing.CaseInsensitive
|
||||
};
|
||||
var paths = Directory.GetFiles(famPath, "full.pcx", options);
|
||||
if (paths.Length != 0)
|
||||
{
|
||||
var palettePath = paths[0];
|
||||
using MemoryStream stream = new(File.ReadAllBytes(palettePath));
|
||||
using BinaryReader reader = new(stream, Encoding.UTF8, false);
|
||||
stream.Seek(-paletteSize, SeekOrigin.End);
|
||||
|
||||
for (var i = 0; i < numColors; i++)
|
||||
{
|
||||
var r = reader.ReadByte() / 255.0f;
|
||||
var g = reader.ReadByte() / 255.0f;
|
||||
var b = reader.ReadByte() / 255.0f;
|
||||
palette[i] = new Color(r, g, b);
|
||||
}
|
||||
}
|
||||
|
||||
return palette;
|
||||
}
|
||||
|
||||
static System.Numerics.Vector2 ReadVec2(BinaryReader reader)
|
||||
{
|
||||
return new(reader.ReadUInt16(), reader.ReadUInt16());
|
||||
}
|
||||
|
||||
using MemoryStream stream = new(File.ReadAllBytes(path));
|
||||
using BinaryReader reader = new(stream, Encoding.UTF8, false);
|
||||
|
||||
|
@ -23,17 +58,16 @@ public partial class TextureLoader
|
|||
var version = reader.ReadByte();
|
||||
var compression = reader.ReadByte();
|
||||
var bytesPerPixel = reader.ReadByte();
|
||||
var min = new Vector2(reader.ReadUInt16(), reader.ReadUInt16());
|
||||
var max = new Vector2(reader.ReadUInt16(), reader.ReadUInt16());
|
||||
var dpi = new Vector2(reader.ReadUInt16(), reader.ReadUInt16());
|
||||
var min = ReadVec2(reader);
|
||||
var max = ReadVec2(reader);
|
||||
var dpi = ReadVec2(reader);
|
||||
var headerPalette = reader.ReadBytes(48);
|
||||
reader.ReadByte();
|
||||
var numPlanes = reader.ReadByte();
|
||||
var bytesPerRow = reader.ReadUInt16();
|
||||
var paletteMode = reader.ReadUInt16();
|
||||
var dpiSrc = new Vector2(reader.ReadUInt16(), reader.ReadUInt16());
|
||||
var dpiSrc = ReadVec2(reader);
|
||||
reader.ReadBytes(54);
|
||||
var dataOffset = stream.Position;
|
||||
|
||||
// Validation
|
||||
if (tag != 0x0A)
|
||||
|
@ -54,13 +88,12 @@ public partial class TextureLoader
|
|||
throw new System.Exception("Unsupported bpp/plane format");
|
||||
}
|
||||
|
||||
var palette = LoadPcxPalette(reader);
|
||||
var palette = LoadFamilyPalette(path.GetBaseDir());
|
||||
|
||||
// Read pixels
|
||||
stream.Seek(dataOffset, SeekOrigin.Begin);
|
||||
// Read run length encoded pixel Data
|
||||
var width = (int)(max.X - min.X + 1);
|
||||
var height = (int)(max.Y - min.Y + 1);
|
||||
var image = Godot.Image.Create(width, height, false, Godot.Image.Format.Rgba8);
|
||||
var image = Image.Create(width, height, false, Image.Format.Rgba8);
|
||||
for (var y = 0; y < height; y++)
|
||||
{
|
||||
var x = 0;
|
||||
|
@ -85,24 +118,6 @@ public partial class TextureLoader
|
|||
}
|
||||
}
|
||||
|
||||
return Godot.ImageTexture.CreateFromImage(image);
|
||||
}
|
||||
|
||||
private static Godot.Color[] LoadPcxPalette(BinaryReader reader)
|
||||
{
|
||||
var numColors = 256;
|
||||
var bytesPerColor = 3;
|
||||
var paletteSize = numColors * bytesPerColor;
|
||||
reader.BaseStream.Seek(-paletteSize, SeekOrigin.End);
|
||||
|
||||
var palette = new Godot.Color[numColors];
|
||||
for (var i = 0; i < numColors; i++)
|
||||
{
|
||||
var r = reader.ReadByte() / 255.0f;
|
||||
var g = reader.ReadByte() / 255.0f;
|
||||
var b = reader.ReadByte() / 255.0f;
|
||||
palette[i] = new Godot.Color(r, g, b);
|
||||
}
|
||||
return palette;
|
||||
return ImageTexture.CreateFromImage(image);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue