protected virtual ColorCollection ReadPalette(Stream stream, AdobePhotoshopColorSwatchFileVersion version) { int colorCount; ColorCollection results; results = new ColorCollection(); // read the number of colors, which also occupies two bytes colorCount = this.ReadInt16(stream); for (int i = 0; i < colorCount; i++) { AdobePhotoshopColorSwatchColorSpace colorSpace; int value1; int value2; int value3; string name; // again, two bytes for the color space colorSpace = (AdobePhotoshopColorSwatchColorSpace)(this.ReadInt16(stream)); value1 = this.ReadInt16(stream); value2 = this.ReadInt16(stream); value3 = this.ReadInt16(stream); this.ReadInt16(stream); // only CMYK supports this field. As we can't handle CMYK colors, we read the value to advance the stream but don't do anything with it if (version == AdobePhotoshopColorSwatchFileVersion.Version2) { int length; // need to read the name even though currently our colour collection doesn't support names length = ReadInt32(stream); name = this.ReadString(stream, length); } else { name = string.Empty; } switch (colorSpace) { case AdobePhotoshopColorSwatchColorSpace.Rgb: int red; int green; int blue; // RGB. // The first three values in the color data are red , green , and blue . They are full unsigned // 16-bit values as in Apple's RGBColor data structure. Pure red = 65535, 0, 0. red = value1 / 256; green = value2 / 256; blue = value3 / 256; results.Add(Color.FromArgb(red, green, blue)); break; case AdobePhotoshopColorSwatchColorSpace.Hsb: double hue; double saturation; double brightness; // HSB. // The first three values in the color data are hue , saturation , and brightness . They are full // unsigned 16-bit values as in Apple's HSVColor data structure. Pure red = 0,65535, 65535. hue = value1 / 182.04; saturation = value2 / 655.35; brightness = value3 / 655.35; results.Add(new HslColor(hue, saturation, brightness).ToRgbColor()); break; case AdobePhotoshopColorSwatchColorSpace.Grayscale: int gray; // Grayscale. // The first value in the color data is the gray value, from 0...10000. gray = (int)(value1 / 39.0625); results.Add(Color.FromArgb(gray, gray, gray)); break; default: throw new InvalidDataException(string.Format("Color space '{0}' not supported.", colorSpace)); } #if USENAMEHACK results.SetName(i, name); #endif } return(results); }
/// <summary> /// Deserializes the <see cref="ColorCollection" /> contained by the specified <see cref="Stream" />. /// </summary> /// <param name="stream">The <see cref="Stream" /> that contains the palette to deserialize.</param> /// <returns>The <see cref="ColorCollection" /> being deserialized.</returns> public override ColorCollection Deserialize(Stream stream) { ColorCollection results; if (stream == null) { throw new ArgumentNullException("stream"); } results = new ColorCollection(); using (StreamReader reader = new StreamReader(stream)) { string header; int swatchIndex; bool readingPalette; readingPalette = false; // check signature header = reader.ReadLine(); if (header != "GIMP Palette") { throw new InvalidDataException("Invalid palette file"); } // read the swatches swatchIndex = 0; while (!reader.EndOfStream) { string data; data = reader.ReadLine(); if (!string.IsNullOrEmpty(data)) { if (data[0] == '#') { // comment readingPalette = true; } else if (!readingPalette) { // custom attribute } else if (readingPalette) { int r; int g; int b; string[] parts; string name; // TODO: Optimize this a touch. Microoptimization? Maybe. parts = !string.IsNullOrEmpty(data) ? data.Split(new[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries) : new string[0]; name = parts.Length > 3 ? string.Join(" ", parts, 3, parts.Length - 3) : null; if (!int.TryParse(parts[0], out r) || !int.TryParse(parts[1], out g) || !int.TryParse(parts[2], out b)) { throw new InvalidDataException(string.Format("Invalid palette contents found with data '{0}'", data)); } results.Add(Color.FromArgb(r, g, b)); #if USENAMEHACK results.SetName(swatchIndex, name); #endif swatchIndex++; } } } } return(results); }