<commit_before>﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Colours
{
    /// <summary>
    /// Converts to and from <see cref="Palette"/> and Photoshop tables.
    /// (ACT files)
    /// </summary>
    /// <remarks>
    /// See Adobe's documentation: 
    /// http://www.adobe.com/devnet-apps/photoshop/fileformatashtml/#50577411_pgfId-1070626
    /// </remarks>
    public static class ActConverter
    {
        /// <summary>
        /// Creates a palette from a colour table.
        /// </summary>
        /// <param name="file">The file as a bytestream.</param>
        /// <returns>A palette from the table</returns>
        /// <remarks>
        /// Note that the resulting color can be truncated by a directive
        /// after the first 768 bytes.
        /// </remarks>
        public static Palette FromTable(byte[] file)
        {
            var p = new Palette() { Name = "Imported from Photoshop" };

            if (file.Length > 772 || file.Length < 768)
                throw new InvalidDataException("Not a valid colour table length.");

            var metadata = file.Length == 772;
            using (var s = new MemoryStream(file))
            {
                using (var sr = new BinaryReader(s))
                {
                    for (int i = 0; i < 256; i++)
                        p.Colors.Add(
                            new PaletteColor(
                                new RgbColor(sr.ReadByte(), sr.ReadByte(), sr.ReadByte())
                                )
                                );

                    if (metadata)
                    {
                        var truncateRaw = sr.ReadBytes(2);
                        // Photoshop values are BE
                        if (BitConverter.IsLittleEndian)
                            truncateRaw = truncateRaw.Reverse().ToArray();
                        var truncateTo = BitConverter.ToUInt16(truncateRaw, 0);

                        p.Colors = p.Colors.Take(truncateTo).ToList();

                        // we don't support transparency indices
                    }
                }
            }

            return p;
        }

        public static byte[] ToTable(Palette p)
        {
            using (var s = new MemoryStream())
            {
                using (var sw = new BinaryWriter(s))
                {
                    var l = p.Colors.Take(256).Select(x => x.Color).ToArray();

                    const byte defaultChannel = 0xFF;
                    for (int i = 0; i < 256; i++)
                    {
                        if (l.Length <= i)
                        {
                            // when in doubt, white?
                            sw.Write(defaultChannel);
                            sw.Write(defaultChannel);
                            sw.Write(defaultChannel);
                        }
                        else
                        {
                            sw.Write(l[i].R);
                            sw.Write(l[i].G);
                            sw.Write(l[i].B);<commit_msg>document ToTable<commit_after>﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Colours
{
    /// <summary>
    /// Converts to and from <see cref="Palette"/> and Photoshop tables.
    /// (ACT files)
    /// </summary>
    /// <remarks>
    /// See Adobe's documentation: 
    /// http://www.adobe.com/devnet-apps/photoshop/fileformatashtml/#50577411_pgfId-1070626
    /// </remarks>
    public static class ActConverter
    {
        /// <summary>
        /// Creates a palette from a colour table.
        /// </summary>
        /// <param name="file">The file as a bytestream.</param>
        /// <returns>A palette from the table</returns>
        /// <remarks>
        /// Note that the resulting color can be truncated by a directive
        /// after the first 768 bytes.
        /// </remarks>
        public static Palette FromTable(byte[] file)
        {
            var p = new Palette() { Name = "Imported from Photoshop" };

            if (file.Length > 772 || file.Length < 768)
                throw new InvalidDataException("Not a valid colour table length.");

            var metadata = file.Length == 772;
            using (var s = new MemoryStream(file))
            {
                using (var sr = new BinaryReader(s))
                {
                    for (int i = 0; i < 256; i++)
                        p.Colors.Add(
                            new PaletteColor(
                                new RgbColor(sr.ReadByte(), sr.ReadByte(), sr.ReadByte())
                                )
                                );

                    if (metadata)
                    {
                        var truncateRaw = sr.ReadBytes(2);
                        // Photoshop values are BE
                        if (BitConverter.IsLittleEndian)
                            truncateRaw = truncateRaw.Reverse().ToArray();
                        var truncateTo = BitConverter.ToUInt16(truncateRaw, 0);

                        p.Colors = p.Colors.Take(truncateTo).ToList();

                        // we don't support transparency indices
                    }
                }
            }

            return p;
        }

        /// <summary>
        /// Creates a colour table from a palette.
        /// </summary>
        /// <param name="p">The palette to convert.</param>
        /// <returns>The colour table, as a byte stream.</returns>
        /// <remarks>
        /// If the length of the palette is exactly 256, then no metadata will
        /// be appended.
        /// </remarks>
        public static byte[] ToTable(Palette p)
        {
            using (var s = new MemoryStream())
            {
                using (var sw = new BinaryWriter(s))
                {
                    var l = p.Colors.Take(256).Select(x => x.Color).ToArray();

                    const byte defaultChannel = 0xFF;
                    for (int i = 0; i < 256; i++)
                    {
                        if (l.Length <= i)
                        {
                            // when in doubt, white?
                            sw.Write(defaultChannel);
                            sw.Write(defaultChannel);
                            sw.Write(defaultChannel);
                        }
                        else
                        {
                            sw.Write(l[i].R);
                            sw.Write(l[i].G);
                            sw.Write(l[i].B);
{'fraction_non_alphanumeric': 0.10873146622734761, 'fraction_numerical': 0.013329339523738206, 'mean_word_length': 1.0611111111111111, 'pattern_counts': {'":': 0, '<': 45, '<?xml version=': 0, '>': 41, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5813721', 'n_tokens_mistral': 1779, 'n_tokens_neox': 1603, 'n_words': 436}