| | 1 | | using System; |
| | 2 | | using System.Collections.Generic; |
| | 3 | | using System.Drawing; |
| | 4 | | using System.Linq; |
| | 5 | | using System.Runtime.InteropServices; |
| | 6 | | using static SDL2.SDL_pixels; |
| | 7 | | using static Imagini.ErrorHandler; |
| | 8 | |
|
| | 9 | | namespace Imagini.Drawing |
| | 10 | | { |
| | 11 | | /// <summary> |
| | 12 | | /// Contains palette information. |
| | 13 | | /// </summary> |
| | 14 | | public sealed class Palette : Resource, IDisposable |
| | 15 | | { |
| | 16 | | /// <summary> |
| | 17 | | /// Defines maximum color count in a palette. |
| | 18 | | /// </summary> |
| | 19 | | public const int MaximumColors = 256; |
| | 20 | | internal IntPtr Handle; |
| | 21 | | private Color[] _colors; |
| | 22 | | public Color[] Colors |
| | 23 | | { |
| | 24 | | get |
| | 25 | | { |
| 3 | 26 | | CheckIfNotDisposed(); |
| 3 | 27 | | return _colors; |
| | 28 | | } |
| | 29 | | set |
| | 30 | | { |
| 5 | 31 | | var count = value.Length; |
| 5 | 32 | | if (count < 1 || count > MaximumColors) |
| 2 | 33 | | throw new ArgumentOutOfRangeException("Invalid color count - maximum of 256 is supported"); |
| 3 | 34 | | var sdlColors = new SDL_Color[count]; |
| 1038 | 35 | | for (int i = 0; i < count; i++) |
| 516 | 36 | | sdlColors[i] = value[i].ToSDLColor(); |
| | 37 | | unsafe |
| | 38 | | { |
| 3 | 39 | | var colorPtr = (SDL_Color*)Marshal.AllocHGlobal(sizeof(SDL_Color) * sdlColors.Length); |
| 1038 | 40 | | for (int i = 0; i < count; i++) |
| 516 | 41 | | *(colorPtr + i) = value[i].ToSDLColor(); |
| 0 | 42 | | Try(() => |
| 3 | 43 | | SDL_SetPaletteColors(Handle, (IntPtr)colorPtr, 0, count), |
| 3 | 44 | | "SDL_SetPaletteColors"); |
| | 45 | | } |
| 3 | 46 | | _colors = value; |
| 3 | 47 | | } |
| | 48 | | } |
| | 49 | |
|
| 1 | 50 | | internal Palette(IntPtr handle) |
| | 51 | | { |
| 1 | 52 | | Handle = handle; |
| 1 | 53 | | var palette = Marshal.PtrToStructure<SDL_Palette>(Handle); |
| 1 | 54 | | var p = palette.colors; |
| 1 | 55 | | var colors = new Color[palette.ncolors]; |
| 514 | 56 | | for (int i = 0; i < palette.ncolors; i++) |
| | 57 | | { |
| | 58 | | unsafe |
| | 59 | | { |
| 256 | 60 | | var ptr = (IntPtr)(p + i * 4); |
| 256 | 61 | | var color = Marshal.PtrToStructure<SDL_Color>(ptr); |
| 256 | 62 | | colors[i] = color.FromSDLColor(); |
| | 63 | | } |
| | 64 | | } |
| 1 | 65 | | Colors = colors; |
| 1 | 66 | | } |
| | 67 | |
|
| | 68 | | /// <summary> |
| | 69 | | /// Creates a new palette from the specified colors. |
| | 70 | | /// </summary> |
| 4 | 71 | | public Palette(params Color[] colors) |
| | 72 | | { |
| 4 | 73 | | Handle = SDL_AllocPalette(colors.Length); |
| 4 | 74 | | Colors = colors; |
| 2 | 75 | | } |
| | 76 | |
|
| | 77 | | /// <summary> |
| | 78 | | /// Creates a new palette from the specified colors. |
| | 79 | | /// </summary> |
| 3 | 80 | | public Palette(IEnumerable<Color> colors) : this(colors.ToArray()) { } |
| | 81 | |
|
| | 82 | | /// <summary> |
| | 83 | | /// Disposes the object. |
| | 84 | | /// </summary> |
| 1 | 85 | | public void Dispose() => Destroy(); |
| | 86 | |
|
| | 87 | | internal override void Destroy() |
| | 88 | | { |
| 2 | 89 | | if (IsDisposed) return; |
| 2 | 90 | | base.Destroy(); |
| 2 | 91 | | SDL_FreePalette(Handle); |
| 2 | 92 | | } |
| | 93 | |
|
| 1 | 94 | | static Palette() => Lifecycle.TryInitialize(); |
| | 95 | | } |
| | 96 | |
|
| | 97 | | internal static class ColorExtensions |
| | 98 | | { |
| | 99 | | public static Color FromSDLColor(this SDL_Color color) => |
| | 100 | | Color.FromArgb(color.a, color.r, color.g, color.b); |
| | 101 | |
|
| | 102 | | public static SDL_Color ToSDLColor(this Color color) => |
| | 103 | | new SDL_Color() |
| | 104 | | { |
| | 105 | | a = color.A, |
| | 106 | | r = color.R, |
| | 107 | | g = color.G, |
| | 108 | | b = color.B |
| | 109 | | }; |
| | 110 | |
|
| | 111 | | public static uint AsUint(this Color color, PixelFormatInfo format) => |
| | 112 | | SDL_MapRGBA(format.Handle, color.R, color.G, color.B, color.A); |
| | 113 | |
|
| | 114 | | public static Color FromUint(uint value, PixelFormatInfo format) |
| | 115 | | { |
| | 116 | | byte r = 0; byte g = 0; byte b = 0; byte a = 0; |
| | 117 | | SDL_GetRGBA(value, format.Handle, ref r, ref g, ref b, ref a); |
| | 118 | | return Color.FromArgb(a, r, g, b); |
| | 119 | | } |
| | 120 | | } |
| | 121 | | } |