使用 WPF:Color,保存和加载 ColorTable[] 的最快方法是什么?是否可以在不进行任何复制的情况下完成?
可以使用类似的东西:
Color[] ColorTable = new Color[]
{
Colors.Red,
Colors.Green,
Colors.Blue,
};
File.WriteAllBytes(GetColorTablePath(), ColorTable);
byte[] bytesColorTable = File.ReadAllBytes(GetColorTablePath());
我尝试 Span,但出现错误:“System.ArgumentException:'无法使用类型'System.Windows.Media.Color'。仅支持没有指针或引用的值类型。'”在以下代码中:
public static void SaveColors()
{
Span<Color> colors = _colorTable;
Span<byte> bytesColorTable = MemoryMarshal.AsBytes(colors);
File.WriteAllBytes(GetColorTablePath(), bytesColorTable.ToArray());
}
仅供参考:
我没有找到不复制直接保存Color的方法。在我看来,我们不能使用 Span 或 Memory,因为 WPF Color 类型似乎是不透明的,其中 uint 字段对用户隐藏。
所以我就这样做了(等待更好的解决方案):
public static Color[]? LoadColors()
{
if (File.Exists(GetColorTablePath()))
{
byte[] bytesColorTable = File.ReadAllBytes(GetColorTablePath());
Span<byte> spanTable = bytesColorTable;
if (spanTable.Length % 4 != 0)
{
return null;
}
Span<uint> spanColors = MemoryMarshal.Cast<byte, uint>(bytesColorTable);
Color[] colors = new Color[spanColors.Length];
for (int index = 0; index < spanColors.Length; index++)
{
colors[index] = ColorUtil.FromUInt32(spanColors[index]);
}
return colors;
}
return null;
}
public static void SaveColors()
{
if (ColorTable.Length > 0)
{
uint[] uintTable = new uint[ColorTable.Length];
for (int index = 0; index < ColorTable.Length; index++)
{
uintTable[index] = ColorTable[index].ToUInt32();
}
Span<uint> uintSpan = new Span<uint>(uintTable);
Span<byte> bytesTable = MemoryMarshal.AsBytes(uintSpan);
using var file = File.OpenWrite(GetColorTablePath());
file.Write(bytesTable);
}
}
namespace WpfColorGenerator
{
public static class ColorUtil
{
public static uint ToUInt32(byte a, byte r, byte g, byte b)
{
return (uint)(a << 24 | r << 16 | g << 8 | b);
}
public static uint ToUInt32(this Color color)
{
return (uint)(color.A << 24 | color.R << 16 | color.G << 8 | color.B);
}
public static void FromUInt32(uint color, out byte a, out byte r, out byte g, out byte b)
{
a = (byte)(color >> 24 & 0xFF);
r = (byte)(color >> 16 & 0xFF);
g = (byte)(color >> 8 & 0xFF);
b = (byte)(color & 0xFF);
}
public static Color FromUInt32(uint color)
{
return Color.FromArgb((byte)(color >> 24 & 0xFF), (byte)(color >> 16 & 0xFF), (byte)(color >> 8 & 0xFF), (byte)(color & 0xFF));
}
}
}