Archive Browser
Download PhotoshopColorSwatchLoader.zip version 1.0.0.0, last updated 22/01/2014 (24.13 KB)
Download- md5: ea73aa398ec190b0794416866e79de48
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Text;
using System.Windows.Forms;
// Reading PhotoShop Color Swatch (aco) files using C#
// http://cyotek.com/blog/reading-photoshop-color-swatch-aco-files-using-csharp
namespace PhotoShopColorSwatchLoader
{
internal sealed partial class MainForm : Form
{
#region Enums
private enum ColorSpace
{
Rgb = 0,
Hsb = 1,
Cmyk = 2,
Lab = 7,
Grayscale = 8
}
private enum FileVersion
{
Version1 = 1,
Version2
}
#endregion
#region Constants
private const int DefaultX = 6;
private const int DefaultY = 6;
private const int Spacing = 6;
private const int CellSize = 24;
#endregion
#region Instance Fields
private List<Color> _loadedPalette;
#endregion
#region Public Constructors
public MainForm()
{
InitializeComponent();
}
#endregion
#region Overridden Methods
/// <summary>
/// Raises the <see cref="E:System.Windows.Forms.Form.Load"/> event.
/// </summary>
/// <param name="e">An <see cref="T:System.EventArgs"/> that contains the event data. </param>
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
this.AddFiles("aco");
}
#endregion
#region Private Members
private void AddFiles(string extension)
{
string path;
path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "data");
foreach (string fileName in Directory.GetFiles(path, "*." + extension))
filesListBox.Items.Add(new FileInfo(fileName));
}
/// <summary>
/// Reads a 16bit unsigned integer in big-endian format.
/// </summary>
/// <param name="stream">The stream to read the data from.</param>
/// <returns>The unsigned 16bit integer cast to an <c>Int32</c>.</returns>
private int ReadInt16(Stream stream)
{
return (stream.ReadByte() << 8) | (stream.ReadByte() << 0);
}
/// <summary>
/// Reads a 32bit unsigned integer in big-endian format.
/// </summary>
/// <param name="stream">The stream to read the data from.</param>
/// <returns>The unsigned 32bit integer cast to an <c>Int32</c>.</returns>
private int ReadInt32(Stream stream)
{
return ((byte)stream.ReadByte() << 24) | ((byte)stream.ReadByte() << 16) | ((byte)stream.ReadByte() << 8) | ((byte)stream.ReadByte() << 0);
}
private List<Color> ReadPhotoShopSwatchFile(string fileName)
{
List<Color> colorPalette;
using (Stream stream = File.OpenRead(fileName))
{
FileVersion version;
// read the version, which occupies two bytes
version = (FileVersion)this.ReadInt16(stream);
if (version != FileVersion.Version1 && version != FileVersion.Version2)
throw new InvalidDataException("Invalid version information.");
// the specification states that a version2 palette follows a version1
// the only difference between version1 and version2 is the inclusion
// of a name property. Perhaps there's addtional color spaces as well
// but we can't support them all anyway
// I noticed some files no longer include a version 1 palette
colorPalette = this.ReadSwatches(stream, version);
if (version == FileVersion.Version1)
{
version = (FileVersion)this.ReadInt16(stream);
if (version == FileVersion.Version2)
colorPalette = this.ReadSwatches(stream, version);
}
}
return colorPalette;
}
/// <summary>
/// Reads a unicode string of the specified length.
/// </summary>
/// <param name="stream">The stream to read the data from.</param>
/// <param name="length">The number of characters in the string.</param>
/// <returns>The string read from the stream.</returns>
private string ReadString(Stream stream, int length)
{
byte[] buffer;
buffer = new byte[length * 2];
stream.Read(buffer, 0, buffer.Length);
return Encoding.BigEndianUnicode.GetString(buffer);
}
private List<Color> ReadSwatches(Stream stream, FileVersion version)
{
int colorCount;
List<Color> results;
results = new List<Color>();
// read the number of colors, which also occupies two bytes
colorCount = this.ReadInt16(stream);
for (int i = 0; i < colorCount; i++)
{
ColorSpace colorSpace;
int value1;
int value2;
int value3;
int value4;
// again, two bytes for the color space
colorSpace = (ColorSpace)(this.ReadInt16(stream));
value1 = this.ReadInt16(stream);
value2 = this.ReadInt16(stream);
value3 = this.ReadInt16(stream);
value4 = this.ReadInt16(stream);
if (version == FileVersion.Version2)
{
int length;
// need to read the name even though currently our colour collection doesn't support names
length = ReadInt32(stream);
this.ReadString(stream, length);
}
switch (colorSpace)
{
case ColorSpace.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; // 0-255
green = value2 / 256; // 0-255
blue = value3 / 256; // 0-255
results.Add(Color.FromArgb(red, green, blue));
break;
case ColorSpace.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; // 0-359
saturation = value2 / 655.35; // 0-100
brightness = value3 / 655.35; // 0-100
throw new InvalidDataException(string.Format("Color space '{0}' not supported.", colorSpace));
case ColorSpace.Grayscale:
int gray;
// Grayscale.
// The first value in the color data is the gray value, from 0...10000.
gray = (int)(value1 / 39.0625); // 0-255
results.Add(Color.FromArgb(gray, gray, gray));
break;
default:
throw new InvalidDataException(string.Format("Color space '{0}' not supported.", colorSpace));
}
}
return results;
}
#endregion
#region Event Handlers
private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
{
using (Form dialog = new AboutDialog())
dialog.ShowDialog(this);
}
private void exitToolStripMenuItem_Click(object sender, EventArgs e)
{
this.Close();
}
private void filesListBox_SelectedIndexChanged(object sender, EventArgs e)
{
FileInfo selectedFile;
selectedFile = filesListBox.SelectedItem as FileInfo;
if (selectedFile != null)
{
_loadedPalette = this.ReadPhotoShopSwatchFile(selectedFile.FullPath);
this.Text = string.Format("{0} - {1}", Path.GetFileName(selectedFile.FullPath), Application.ProductName);
}
else
{
_loadedPalette = null;
this.Text = Application.ProductName;
}
palettePanel.Invalidate();
}
private void palettePanel_Paint(object sender, PaintEventArgs e)
{
if (_loadedPalette != null)
{
int x;
int y;
x = DefaultX;
y = DefaultY;
e.Graphics.Clear(palettePanel.BackColor);
foreach (Color color in _loadedPalette)
{
Rectangle bounds;
if (x > palettePanel.Width - (CellSize + DefaultX))
{
x = DefaultX;
y += DefaultY + CellSize + Spacing;
}
bounds = new Rectangle(x, y, CellSize, CellSize);
using (Brush brush = new SolidBrush(color))
e.Graphics.FillRectangle(brush, bounds);
e.Graphics.DrawRectangle(Pens.Black, bounds);
x += (CellSize + Spacing);
}
}
}
#endregion
}
}
Donate
This software may be used free of charge, but as with all free software there are costs involved to develop and maintain.
If this site or its services have saved you time, please consider a donation to help with running costs and timely updates.
Donate