1 #region Copyright & License Information 2 /* 3 * Copyright 2007-2020 The OpenRA Developers (see AUTHORS) 4 * This file is part of OpenRA, which is free software. It is made 5 * available to you under the terms of the GNU General Public License 6 * as published by the Free Software Foundation, either version 3 of 7 * the License, or (at your option) any later version. For more 8 * information, see COPYING. 9 */ 10 #endregion 11 12 using System; 13 using System.Collections.Generic; 14 using System.IO; 15 using OpenRA.Primitives; 16 17 namespace OpenRA.Graphics 18 { 19 public interface IPalette 20 { 21 uint this[int index] { get; } CopyToArray(Array destination, int destinationOffset)22 void CopyToArray(Array destination, int destinationOffset); 23 } 24 GetRemappedColor(Color original, int index)25 public interface IPaletteRemap { Color GetRemappedColor(Color original, int index); } 26 27 public static class Palette 28 { 29 public const int Size = 256; 30 GetColor(this IPalette palette, int index)31 public static Color GetColor(this IPalette palette, int index) 32 { 33 return Color.FromArgb((int)palette[index]); 34 } 35 AsReadOnly(this IPalette palette)36 public static IPalette AsReadOnly(this IPalette palette) 37 { 38 if (palette is ImmutablePalette) 39 return palette; 40 return new ReadOnlyPalette(palette); 41 } 42 43 class ReadOnlyPalette : IPalette 44 { 45 IPalette palette; ReadOnlyPalette(IPalette palette)46 public ReadOnlyPalette(IPalette palette) { this.palette = palette; } 47 public uint this[int index] { get { return palette[index]; } } CopyToArray(Array destination, int destinationOffset)48 public void CopyToArray(Array destination, int destinationOffset) 49 { 50 palette.CopyToArray(destination, destinationOffset); 51 } 52 } 53 } 54 55 public class ImmutablePalette : IPalette 56 { 57 readonly uint[] colors = new uint[Palette.Size]; 58 59 public uint this[int index] 60 { 61 get { return colors[index]; } 62 } 63 CopyToArray(Array destination, int destinationOffset)64 public void CopyToArray(Array destination, int destinationOffset) 65 { 66 Buffer.BlockCopy(colors, 0, destination, destinationOffset * 4, Palette.Size * 4); 67 } 68 ImmutablePalette(string filename, int[] remap)69 public ImmutablePalette(string filename, int[] remap) 70 { 71 using (var s = File.OpenRead(filename)) 72 LoadFromStream(s, remap); 73 } 74 ImmutablePalette(Stream s, int[] remapShadow)75 public ImmutablePalette(Stream s, int[] remapShadow) 76 { 77 LoadFromStream(s, remapShadow); 78 } 79 LoadFromStream(Stream s, int[] remapShadow)80 void LoadFromStream(Stream s, int[] remapShadow) 81 { 82 using (var reader = new BinaryReader(s)) 83 for (var i = 0; i < Palette.Size; i++) 84 { 85 var r = (byte)(reader.ReadByte() << 2); 86 var g = (byte)(reader.ReadByte() << 2); 87 var b = (byte)(reader.ReadByte() << 2); 88 89 // Replicate high bits into the (currently zero) low bits. 90 r |= (byte)(r >> 6); 91 g |= (byte)(g >> 6); 92 b |= (byte)(b >> 6); 93 94 colors[i] = (uint)((255 << 24) | (r << 16) | (g << 8) | b); 95 } 96 97 colors[0] = 0; // Convert black background to transparency. 98 foreach (var i in remapShadow) 99 colors[i] = 140u << 24; 100 } 101 ImmutablePalette(IPalette p, IPaletteRemap r)102 public ImmutablePalette(IPalette p, IPaletteRemap r) 103 : this(p) 104 { 105 for (var i = 0; i < Palette.Size; i++) 106 colors[i] = (uint)r.GetRemappedColor(this.GetColor(i), i).ToArgb(); 107 } 108 ImmutablePalette(IPalette p)109 public ImmutablePalette(IPalette p) 110 { 111 for (int i = 0; i < Palette.Size; i++) 112 colors[i] = p[i]; 113 } 114 ImmutablePalette(IEnumerable<uint> sourceColors)115 public ImmutablePalette(IEnumerable<uint> sourceColors) 116 { 117 var i = 0; 118 foreach (var sourceColor in sourceColors) 119 colors[i++] = sourceColor; 120 } 121 } 122 123 public class MutablePalette : IPalette 124 { 125 readonly uint[] colors = new uint[Palette.Size]; 126 127 public uint this[int index] 128 { 129 get { return colors[index]; } 130 set { colors[index] = value; } 131 } 132 CopyToArray(Array destination, int destinationOffset)133 public void CopyToArray(Array destination, int destinationOffset) 134 { 135 Buffer.BlockCopy(colors, 0, destination, destinationOffset * 4, Palette.Size * 4); 136 } 137 MutablePalette(IPalette p)138 public MutablePalette(IPalette p) 139 { 140 SetFromPalette(p); 141 } 142 SetColor(int index, Color color)143 public void SetColor(int index, Color color) 144 { 145 colors[index] = (uint)color.ToArgb(); 146 } 147 SetFromPalette(IPalette p)148 public void SetFromPalette(IPalette p) 149 { 150 p.CopyToArray(colors, 0); 151 } 152 ApplyRemap(IPaletteRemap r)153 public void ApplyRemap(IPaletteRemap r) 154 { 155 for (var i = 0; i < Palette.Size; i++) 156 colors[i] = (uint)r.GetRemappedColor(this.GetColor(i), i).ToArgb(); 157 } 158 } 159 } 160