Paradox Game Engine  v1.0.0 beta06
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros Pages
Palette.cs
Go to the documentation of this file.
1 using System;
2 using System.Collections.Generic;
3 using System.Text;
4 using System.Drawing;
5 using System.IO;
6 using FreeImageAPI.Metadata;
7 using System.Runtime.InteropServices;
8 using System.Diagnostics;
9 
10 namespace FreeImageAPI
11 {
12  /// <summary>
13  /// Provides methods for working with the standard bitmap palette.
14  /// </summary>
15  public sealed class Palette : MemoryArray<RGBQUAD>
16  {
17  [DebuggerBrowsable(DebuggerBrowsableState.Never)]
18  private GCHandle paletteHandle;
19 
20  [DebuggerBrowsable(DebuggerBrowsableState.Never)]
21  private RGBQUAD[] array;
22 
23  /// <summary>
24  /// Initializes a new instance for the given FreeImage bitmap.
25  /// </summary>
26  /// <param name="dib">Handle to a FreeImage bitmap.</param>
27  /// <exception cref="ArgumentNullException"><paramref name="dib"/> is null.</exception>
28  /// <exception cref="ArgumentException"><paramref name="dib"/> is not
29  /// <see cref="FREE_IMAGE_TYPE.FIT_BITMAP"/><para/>-or-<para/>
30  /// <paramref name="dib"/> has more than 8bpp.</exception>
31  public Palette(FIBITMAP dib)
32  : base(FreeImage.GetPalette(dib), (int)FreeImage.GetColorsUsed(dib))
33  {
34  if (dib.IsNull)
35  {
36  throw new ArgumentNullException("dib");
37  }
38  if (FreeImage.GetImageType(dib) != FREE_IMAGE_TYPE.FIT_BITMAP)
39  {
40  throw new ArgumentException("dib");
41  }
42  if (FreeImage.GetBPP(dib) > 8u)
43  {
44  throw new ArgumentException("dib");
45  }
46  }
47 
48  /// <summary>
49  /// Initializes a new instance for the given FITAG that contains
50  /// a palette.
51  /// </summary>
52  /// <param name="tag">The tag containing the palette.</param>
53  /// <exception cref="ArgumentNullException"><paramref name="tag"/> is null.</exception>
54  /// <exception cref="ArgumentException"><paramref name="tag"/> is not
55  /// <see cref="FREE_IMAGE_MDTYPE.FIDT_PALETTE"/>.</exception>
56  public Palette(FITAG tag)
57  : base(FreeImage.GetTagValue(tag), (int)FreeImage.GetTagCount(tag))
58  {
59  if (FreeImage.GetTagType(tag) != FREE_IMAGE_MDTYPE.FIDT_PALETTE)
60  {
61  throw new ArgumentException("tag");
62  }
63  }
64 
65  /// <summary>
66  /// Initializes a new instance for the given MetadataTag that contains
67  /// a palette.
68  /// </summary>
69  /// <param name="tag">The tag containing the palette.</param>
70  /// <exception cref="ArgumentNullException"><paramref name="dib"/> is null.</exception>
71  /// <exception cref="ArgumentException"><paramref name="tag"/> is not
72  /// <see cref="FREE_IMAGE_MDTYPE.FIDT_PALETTE"/>.</exception>
73  public Palette(MetadataTag tag)
74  : base(FreeImage.GetTagValue(tag.tag), (int)tag.Count)
75  {
76  if (FreeImage.GetTagType(tag) != FREE_IMAGE_MDTYPE.FIDT_PALETTE)
77  {
78  throw new ArgumentException("tag");
79  }
80  }
81 
82  /// <summary>
83  /// Initializes a new instance for the given array of <see cref="RGBQUAD"/> that contains
84  /// a palette.
85  /// </summary>
86  /// <param name="palette">A RGBQUAD array containing the palette data to initialize this instance.</param>
87  public Palette(RGBQUAD[] palette)
88  {
89  unsafe
90  {
91  this.array = (RGBQUAD[])palette.Clone();
92  this.paletteHandle = GCHandle.Alloc(array, GCHandleType.Pinned);
93 
94  base.baseAddress = (byte*)this.paletteHandle.AddrOfPinnedObject();
95  base.length = (int)this.array.Length;
96 
97  // Create an array containing a single element.
98  // Due to the fact, that it's not possible to create pointers
99  // of generic types, an array is used to obtain the memory
100  // address of an element of T.
101  base.buffer = new RGBQUAD[1];
102  // The array is pinned immediately to prevent the GC from
103  // moving it to a different position in memory.
104  base.handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
105  // The array and its content have beed pinned, so that its address
106  // can be safely requested and stored for the whole lifetime
107  // of the instace.
108  base.ptr = (byte*)base.handle.AddrOfPinnedObject();
109  }
110  }
111 
112  /// <summary>
113  /// Initializes a new instance for the given array of <see cref="Color"/> that contains
114  /// a palette.
115  /// </summary>
116  /// <param name="palette">A Color array containing the palette data to initialize this instance.</param>
117  public Palette(Color[] palette)
118  : this(RGBQUAD.ToRGBQUAD(palette))
119  {
120  }
121 
122  /// <summary>
123  /// Initializes a new instance with the specified size.
124  /// </summary>
125  /// <param name="size">The size of the palette.</param>
126  public Palette(int size)
127  : this(new RGBQUAD[size])
128  {
129  }
130 
131  /// <summary>
132  /// Gets or sets the palette through an array of <see cref="RGBQUAD"/>.
133  /// </summary>
134  public RGBQUAD[] AsArray
135  {
136  get
137  {
138  return Data;
139  }
140  set
141  {
142  Data = value;
143  }
144  }
145 
146  /// <summary>
147  /// Get an array of <see cref="System.Drawing.Color"/> that the block of memory represents.
148  /// This property is used for internal palette operations.
149  /// </summary>
150  internal unsafe Color[] ColorData
151  {
152  get
153  {
155  Color[] data = new Color[length];
156  for (int i = 0; i < length; i++)
157  {
158  data[i] = Color.FromArgb((int)(((uint*)baseAddress)[i] | 0xFF000000));
159  }
160  return data;
161  }
162  }
163 
164  /// <summary>
165  /// Returns the palette as an array of <see cref="RGBQUAD"/>.
166  /// </summary>
167  /// <returns>The palette as an array of <see cref="RGBQUAD"/>.</returns>
168  public RGBQUAD[] ToArray()
169  {
170  return Data;
171  }
172 
173  /// <summary>
174  /// Creates a linear palette based on the provided <paramref name="color"/>.
175  /// </summary>
176  /// <param name="color">The <see cref="System.Drawing.Color"/> used to colorize the palette.</param>
177  /// <remarks>
178  /// Only call this method on linear palettes.
179  /// </remarks>
180  public void Colorize(Color color)
181  {
182  Colorize(color, 0.5d);
183  }
184 
185  /// <summary>
186  /// Creates a linear palette based on the provided <paramref name="color"/>.
187  /// </summary>
188  /// <param name="color">The <see cref="System.Drawing.Color"/> used to colorize the palette.</param>
189  /// <param name="splitSize">The position of the color within the new palette.
190  /// 0 &lt; <paramref name="splitSize"/> &lt; 1.</param>
191  /// <remarks>
192  /// Only call this method on linear palettes.
193  /// </remarks>
194  public void Colorize(Color color, double splitSize)
195  {
196  Colorize(color, (int)(length * splitSize));
197  }
198 
199  /// <summary>
200  /// Creates a linear palette based on the provided <paramref name="color"/>.
201  /// </summary>
202  /// <param name="color">The <see cref="System.Drawing.Color"/> used to colorize the palette.</param>
203  /// <param name="splitSize">The position of the color within the new palette.
204  /// 0 &lt; <paramref name="splitSize"/> &lt; <see cref="MemoryArray&lt;T&gt;.Length"/>.</param>
205  /// <remarks>
206  /// Only call this method on linear palettes.
207  /// </remarks>
208  public void Colorize(Color color, int splitSize)
209  {
211  if (splitSize < 1 || splitSize >= length)
212  {
213  throw new ArgumentOutOfRangeException("splitSize");
214  }
215 
216  RGBQUAD[] pal = new RGBQUAD[length];
217 
218  double red = color.R;
219  double green = color.G;
220  double blue = color.B;
221 
222  int i = 0;
223  double r, g, b;
224 
225  r = red / splitSize;
226  g = green / splitSize;
227  b = blue / splitSize;
228 
229  for (; i <= splitSize; i++)
230  {
231  pal[i].rgbRed = (byte)(i * r);
232  pal[i].rgbGreen = (byte)(i * g);
233  pal[i].rgbBlue = (byte)(i * b);
234  }
235 
236  r = (255 - red) / (length - splitSize);
237  g = (255 - green) / (length - splitSize);
238  b = (255 - blue) / (length - splitSize);
239 
240  for (; i < length; i++)
241  {
242  pal[i].rgbRed = (byte)(red + ((i - splitSize) * r));
243  pal[i].rgbGreen = (byte)(green + ((i - splitSize) * g));
244  pal[i].rgbBlue = (byte)(blue + ((i - splitSize) * b));
245  }
246 
247  Data = pal;
248  }
249 
250  /// <summary>
251  /// Creates a linear grayscale palette.
252  /// </summary>
254  {
255  Colorize(Color.White, length - 1);
256  }
257 
258  /// <summary>
259  /// Creates a linear grayscale palette.
260  /// </summary>
261  /// <param name="inverse"><b>true</b> to create an inverse grayscale palette.</param>
262  public void CreateGrayscalePalette(bool inverse)
263  {
264  Colorize(Color.White, inverse ? 0 : length - 1);
265  }
266 
267  /// <summary>
268  /// Creates a linear palette with the specified <see cref="Color"/>.
269  /// </summary>
270  /// <remarks>
271  /// A linear grayscale palette contains all shades of colors from
272  /// black to white. This method creates a similar palette with the white
273  /// color being replaced by the specified color.
274  /// </remarks>
275  /// <param name="color">The <see cref="Color"/> used to create the palette.</param>
276  /// <param name="inverse"><b>true</b> to create an inverse palette.</param>
277  public void CreateGrayscalePalette(Color color, bool inverse)
278  {
279  Colorize(color, inverse ? 0 : length - 1);
280  }
281 
282  /// <summary>
283  /// Reverses the palette.
284  /// </summary>
285  public void Reverse()
286  {
288  if (array != null)
289  {
290  Array.Reverse(array);
291  }
292  else
293  {
294  RGBQUAD[] localArray = Data;
295  Array.Reverse(localArray);
296  Data = localArray;
297  }
298  }
299 
300  /// <summary>
301  /// Copies the values from the specified <see cref="Palette"/> to this instance.
302  /// </summary>
303  /// <param name="palette">The palette to copy from.</param>
304  /// <exception cref="ArgumentNullException">
305  /// <paramref name="palette"/> is a null reference.</exception>
306  public void CopyFrom(Palette palette)
307  {
309  if (palette == null)
310  {
311  throw new ArgumentNullException("palette");
312  }
313  CopyFrom(palette.Data, 0, 0, Math.Min(palette.Length, this.Length));
314  }
315 
316  /// <summary>
317  /// Copies the values from the specified <see cref="Palette"/> to this instance,
318  /// starting at the specified <paramref name="offset"/>.
319  /// </summary>
320  /// <param name="palette">The palette to copy from.</param>
321  /// <param name="offset">The position in this instance where the values
322  /// will be copied to.</param>
323  /// <exception cref="ArgumentNullException">
324  /// <paramref name="palette"/> is a null reference.</exception>
325  /// <exception cref="ArgumentOutOfRangeException">
326  /// <paramref name="offset"/> is outside the range of valid indexes.</exception>
327  public void CopyFrom(Palette palette, int offset)
328  {
330  CopyFrom(palette.Data, 0, offset, Math.Min(palette.Length, this.Length - offset));
331  }
332 
333  /// <summary>
334  /// Saves this <see cref="Palette"/> to the specified file.
335  /// </summary>
336  /// <param name="filename">
337  /// A string that contains the name of the file to which to save this <see cref="Palette"/>.
338  /// </param>
339  public void Save(string filename)
340  {
341  using (Stream stream = new FileStream(filename, FileMode.Create, FileAccess.Write))
342  {
343  Save(stream);
344  }
345  }
346 
347  /// <summary>
348  /// Saves this <see cref="Palette"/> to the specified stream.
349  /// </summary>
350  /// <param name="stream">
351  /// The <see cref="Stream"/> where the image will be saved.
352  /// </param>
353  public void Save(Stream stream)
354  {
355  Save(new BinaryWriter(stream));
356  }
357 
358  /// <summary>
359  /// Saves this <see cref="Palette"/> using the specified writer.
360  /// </summary>
361  /// <param name="writer">
362  /// The <see cref="BinaryWriter"/> used to save the image.
363  /// </param>
364  public void Save(BinaryWriter writer)
365  {
367  writer.Write(ToByteArray());
368  }
369 
370  /// <summary>
371  /// Loads a palette from the specified file.
372  /// </summary>
373  /// <param name="filename">The name of the palette file.</param>
374  public void Load(string filename)
375  {
376  using (Stream stream = new FileStream(filename, FileMode.Open, FileAccess.Read))
377  {
378  Load(stream);
379  }
380  }
381 
382  /// <summary>
383  /// Loads a palette from the specified stream.
384  /// </summary>
385  /// <param name="stream">The stream to load the palette from.</param>
386  public void Load(Stream stream)
387  {
388  Load(new BinaryReader(stream));
389  }
390 
391  /// <summary>
392  /// Loads a palette from the reader.
393  /// </summary>
394  /// <param name="reader">The reader to load the palette from.</param>
395  public void Load(BinaryReader reader)
396  {
398  unsafe
399  {
400  int size = length * sizeof(RGBQUAD);
401  byte[] data = reader.ReadBytes(size);
402  fixed (byte* src = data)
403  {
404  CopyMemory(baseAddress, src, data.Length);
405  }
406  }
407  }
408 
409  /// <summary>
410  /// Releases allocated handles associated with this instance.
411  /// </summary>
412  /// <param name="disposing"><b>true</b> to release managed resources.</param>
413  protected override void Dispose(bool disposing)
414  {
415  if (paletteHandle.IsAllocated)
416  paletteHandle.Free();
417  array = null;
418 
419  base.Dispose(disposing);
420  }
421  }
422 }
void Load(string filename)
Loads a palette from the specified file.
Definition: Palette.cs:374
function b
override void Dispose(bool disposing)
Releases allocated handles associated with this instance.
Definition: Palette.cs:413
The FIBITMAP structure is a handle to a FreeImage bimtap.
Definition: FIBITMAP.cs:50
T[] buffer
Array of T containing a single element. The array is used as a workaround, because there are no point...
Definition: MemoryArray.cs:44
Palette(Color[] palette)
Initializes a new instance for the given array of Color that contains a palette.
Definition: Palette.cs:117
System.IO.FileMode FileMode
Definition: ScriptSync.cs:33
Palette(RGBQUAD[] palette)
Initializes a new instance for the given array of RGBQUAD that contains a palette.
Definition: Palette.cs:87
RGBQUAD[] AsArray
Gets or sets the palette through an array of RGBQUAD.
Definition: Palette.cs:134
static unsafe void CopyMemory(byte *dest, byte *src, int len)
Copies a block of memory from one location to another.
Definition: MemoryArray.cs:751
void Load(Stream stream)
Loads a palette from the specified stream.
Definition: Palette.cs:386
void Load(BinaryReader reader)
Loads a palette from the reader.
Definition: Palette.cs:395
void Colorize(Color color)
Creates a linear palette based on the provided color .
Definition: Palette.cs:180
Palette(int size)
Initializes a new instance with the specified size.
Definition: Palette.cs:126
Palette(FIBITMAP dib)
Initializes a new instance for the given FreeImage bitmap.
Definition: Palette.cs:31
Provides methods for working with the standard bitmap palette.
Definition: Palette.cs:15
The RGBQUAD structure describes a color consisting of relative intensities of red, green, blue and alpha value. Each single color component consumes 8 bits and so, takes values in the range from 0 to 255.
Definition: RGBQUAD.cs:97
virtual void EnsureNotDisposed()
Throws an ObjectDisposedException if this instance is disposed.
Definition: MemoryArray.cs:701
RGBQUAD[] ToArray()
Returns the palette as an array of RGBQUAD.
Definition: Palette.cs:168
Manages metadata objects and operations.
Definition: MetadataTag.cs:47
SiliconStudio.Core.Mathematics.Color Color
Definition: ColorPicker.cs:14
void Save(Stream stream)
Saves this Palette to the specified stream.
Definition: Palette.cs:353
byte * baseAddress
Baseaddress of the wrapped memory.
Definition: MemoryArray.cs:25
void CreateGrayscalePalette(bool inverse)
Creates a linear grayscale palette.
Definition: Palette.cs:262
void Save(string filename)
Saves this Palette to the specified file.
Definition: Palette.cs:339
void CopyFrom(Palette palette)
Copies the values from the specified Palette to this instance.
Definition: Palette.cs:306
int length
Number of elements being wrapped.
Definition: MemoryArray.cs:31
void CreateGrayscalePalette()
Creates a linear grayscale palette.
Definition: Palette.cs:253
Palette(MetadataTag tag)
Initializes a new instance for the given MetadataTag that contains a palette.
Definition: Palette.cs:73
The FITAG structure is a handle to a FreeImage metadata tag.
Definition: FITAG.cs:45
void Save(BinaryWriter writer)
Saves this Palette using the specified writer.
Definition: Palette.cs:364
void CopyFrom(Palette palette, int offset)
Copies the values from the specified Palette to this instance, starting at the specified offset ...
Definition: Palette.cs:327
void Colorize(Color color, double splitSize)
Creates a linear palette based on the provided color .
Definition: Palette.cs:194
void Colorize(Color color, int splitSize)
Creates a linear palette based on the provided color .
Definition: Palette.cs:208
Palette(FITAG tag)
Initializes a new instance for the given FITAG that contains a palette.
Definition: Palette.cs:56
int Count
Gets a 32-bit integer that represents the total number of elements in the MemoryArray<T>.
Definition: MemoryArray.cs:612
void CreateGrayscalePalette(Color color, bool inverse)
Creates a linear palette with the specified Color.
Definition: Palette.cs:277
byte[] ToByteArray()
Returns the represented block of memory as an array of Byte.
Definition: MemoryArray.cs:506
bool IsNull
Gets whether the handle is a null or not.
Definition: FIBITMAP.cs:91
T[] Data
Gets or sets the values of the unmanaged array.
Definition: MemoryArray.cs:554
void Reverse()
Reverses the palette.
Definition: Palette.cs:285