/// <summary> /// Converts the colour into a L*a*b* representation. /// </summary> /// <returns>The L*a*b* representation of the colour.</returns> public LabColor ToLab() { var lab = new LabColor(0, 0, 0); lab.L = 116.0 * Fxyz(Y / D65.Y) - 16; lab.A = 500.0 * (Fxyz(X / D65.X) - Fxyz(Y / D65.Y)); lab.B = 200.0 * (Fxyz(Y / D65.Y) - Fxyz(Z / D65.Z)); return(lab); }
/// <summary> /// Creates a palette from a Photoshop color book file. /// </summary> /// <param name="file">The file to convert from.</param> public AcbPalette(byte[] file) : this() { using (var ms = new MemoryStream(file)) { using (var sr = new BinaryReader(ms)) { if (new string(sr.ReadChars(4)) != magic) { throw new PaletteException("Not a valid color book."); } var version = sr.ReadUInt16BE(); ID = sr.ReadUInt16BE(); Name = UnescapeString(GetValue(sr.ReadStringBE(false))); Prefix = GetValue(sr.ReadStringBE(false)); Postfix = GetValue(sr.ReadStringBE(false)); Description = UnescapeString(GetValue(sr.ReadStringBE(false))); var count = sr.ReadUInt16BE(); BucketSize = sr.ReadUInt16BE(); DefaultSelection = sr.ReadUInt16BE(); ColorSpace = (AdobeColorSpaceAcbSubset)sr.ReadUInt16BE(); for (int i = 0; i < count; i++) { var name = sr.ReadStringBE(true); // TODO: this needs to be associated with the PaletteColor var cid = new string(sr.ReadChars(6)); #if DEBUG System.Diagnostics.Debug.WriteLine("{0}{1}{2}:{3}", Prefix, name, Postfix, cid); #endif IColor color; switch (ColorSpace) { case AdobeColorSpaceAcbSubset.Rgb: color = new RgbColor(sr.ReadByte(), sr.ReadByte(), sr.ReadByte()); break; // For lab and cmyk, should we add 0.5? // (seems to be not a good idea) case AdobeColorSpaceAcbSubset.Lab: var l = sr.ReadByte() / 2.55d; var a = sr.ReadByte() - 128; var b = sr.ReadByte() - 128; color = new LabColor(l, a, b); break; case AdobeColorSpaceAcbSubset.Cmyk: var c = 1 - sr.ReadByte() / 255d; var m = 1 - sr.ReadByte() / 255d; var y = 1 - sr.ReadByte() / 255d; var k = 1 - sr.ReadByte() / 255d; color = new CmykColor(c, m, y, k); break; default: throw new PaletteException(string.Format( "Invalid colorspace. {0}", ColorSpace)); } Colors.Add(new PaletteColor(color, name, cid)); } if (ms.Length > ms.Position) { var purpose = new string(sr.ReadChars(8)); switch (purpose) { case spot: Purpose = AcbPurpose.Spot; break; case proc: Purpose = AcbPurpose.Process; break; default: Purpose = AcbPurpose.Unknown; break; } } } } }
/// <summary> /// Creates a palette from an Adobe Swatch Exchange file. /// </summary> /// <param name="file">The file, as an array of bytes.</param> /// <returns>The converted palette.</returns> public AsePalette(byte[] file) : this() { using (var ms = new MemoryStream(file)) { using (var sr = new BinaryReader(ms)) { if (new string(sr.ReadChars(4)) != "ASEF") { throw new PaletteException("Not an ASE file."); } // major, minor var version = new Version(sr.ReadUInt16BE(), sr.ReadUInt16BE()); // should we bomb if it's not a version we accept? if (version > new Version(1, 0)) { throw new PaletteException("The version is unsupported."); } var count = sr.ReadUInt32BE(); for (int i = 0; i < count; i++) { var type = sr.ReadUInt16BE(); var length = sr.ReadUInt32BE(); if (type == 1) // color entry { var nameLen = sr.ReadUInt16BE(); var name = sr.ReadStringBE(nameLen, true); var colorSpace = new string(sr.ReadChars(4)); IColor color; switch (colorSpace) { case "RGB ": var r = sr.ReadSingleBE(); var g = sr.ReadSingleBE(); // HACK: we can't use same named variable // declarations in a switch/case block, due // to C behaviour leftovers var blue = sr.ReadSingleBE(); var rr = Convert.ToUInt16(Math.Round(r * 65535)); var gr = Convert.ToUInt16(Math.Round(g * 65535)); var br = Convert.ToUInt16(Math.Round(blue * 65535)); color = new RgbColor(rr, gr, br); break; case "LAB ": var l = sr.ReadSingleBE() * 100; var a = sr.ReadSingleBE(); var b = sr.ReadSingleBE(); color = new LabColor(l, a, b); break; default: throw new PaletteException( string.Format("The colorspace ({0}) is unsupported.", colorSpace)); } Colors.Add(new PaletteColor(color, name)); var colorType = sr.ReadUInt16BE(); } else { // skip ahead sr.ReadBytes(Convert.ToInt32(length)); } } } } }