0

I am creating an image format called DIF (Dictionary Image Format), in which the image specifies the color palette (dictionary) within the image, or can choose to load an external one.

I am trying to create a color dictionary for all the possible values in the RGB spectrum. I have found how to iterate through the RGB spectrum, but am at a loss on how to iterate through all the possible dictionary keys.

Each dictionary key will be made of of a string of upper or lower case letters (like aAaAB) that is five letters long. This provides for 380204032 possible combinations, enough to encode the 16.7 million colors in RGB.

How would this work, and how would I integrate it with my existing RGB code, which is below:

Dictionary<string,Color> rgb = new Dictionary<string,Color>();

for(int r = 0; r <= 255; r++)
{
   for(int g = 0; g <= 255; g++)
   {
        for(int b = 0; b <= 255; b++)
        {
            //Add colors to dictionary here
        }
   }
}
Igor
  • 548
  • 3
  • 7
  • 24
  • 3
    How does `aAaAB` translate into a colour? It sounds like you're trying to reinvent hex colours – Sayse Jul 23 '14 at 12:16
  • 2
    What is the value for `b` in first and second for loop? – Jesuraja Jul 23 '14 at 12:19
  • 1
    @Jesuraja probably a copy/paste fail from the inner `for` loop – Trevor Pilley Jul 23 '14 at 12:22
  • 1
    as above sounds like weird thing to do...but the first thing you need to specify to answer your problem is the int to char conversion? 0 = a, 1 = b, 2 = A, 3 = B or something. Alternatively you need to specify how your five character string increases when you add one to the previous value, is it a, aa, aaa or a, ab, abc or a, A, b? – cjb110 Jul 23 '14 at 12:25
  • @Jesuraja as Trevor said, I screwed up. I'll fix it – Igor Jul 23 '14 at 12:37
  • 1
    I don't understand what you're trying to do? Why convert colors to a 5-character string? Why not use 6-character hex-codes that are universally recognized? If you're trying to make the colors more compact to save memory or something, why not just use the 3 byte-values as key? And why do you need a dictionary at all? The values generated is easy enough to convert to/from hex/bytes/Color without a dictionary lookup. – TheQ Jul 23 '14 at 12:39
  • This comes quite close to Base64, which uses 4 characters in the range `A-Z, a-z, 0-9, +, /` to encode 3 bytes. – C.Evenhuis Jul 23 '14 at 12:58
  • @TheQ I think I will not use a dictionary file for the RGB lookup, as you have stated. However, the dictionary method would work good for things like black and white, 256 shades of gray, etc. – Igor Jul 23 '14 at 13:15

1 Answers1

1

I would suggest that you don't need a dictionary at all.

Instead, you can convert each colour to and from a base 52 (a-zA-Z) notation on demand.

Here's an example. It uses some base conversion code from here: Quickest way to convert a base 10 number to any base in .NET?

using System;
using System.Drawing;

namespace Demo
{
    internal class Program
    {
        private void run()
        {
            // As an example, iterate through all known colours and demonstrate
            // that we can convert each colour to a 5 character string and back.

            var colors = Enum.GetValues(typeof(KnownColor));

            foreach (KnownColor knowColor in colors)
            {
                Color colour = Color.FromKnownColor(knowColor);
                string colourString = ColourToBase52(colour);
                Color decodedColour = ColourFromBase52(colourString);

                if (colour.ToArgb() != decodedColour.ToArgb())
                    Console.WriteLine("ERROR with colour " + colour); // Expect this to complain about TRANSPARENT.
                else
                    Console.WriteLine("{0,-30} is represented by {1}", colour, colourString);
            }
        }

        public static string ColourToBase52(Color colour)
        {
            int value = colour.ToArgb() & 0x00FFFFFF; // Mask off the alpha channel.
            return ToBase52(value);
        }

        public static Color ColourFromBase52(string colour)
        {
            int value = FromBase52(colour);
            return Color.FromArgb(unchecked((int)(0xFF000000 | value)));
        }

        public static string ToBase52(int value)
        {
            char[] baseChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".ToCharArray();
            int targetBase = baseChars.Length;

            int i = 32;
            char[] buffer = new char[i];

            do
            {
                buffer[--i] = baseChars[value % targetBase];
                value = value / targetBase;
            }
            while (value > 0);

            char[] result = new char[32 - i];
            Array.Copy(buffer, i, result, 0, 32 - i);

            return new string(result).PadLeft(5, 'a');
        }

        public static int FromBase52(string value)
        {
            char[] baseChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".ToCharArray();
            int targetbase = baseChars.Length;

            int multiplier = 1;
            int result = 0;

            for (int i = value.Length-1; i >= 0; --i)
            {
                int digit = Array.IndexOf(baseChars, value[i]);
                result += digit*multiplier;
                multiplier *= targetbase;
            }

            return result;
        }

        public static void Main()
        {
            new Program().run();
        }
    }
}
Community
  • 1
  • 1
Matthew Watson
  • 104,400
  • 10
  • 158
  • 276
  • Would it be possible to have the alpha channel be converted to another color than black? If not that's alright. – Igor Jul 23 '14 at 13:58
  • @Igor The alpha channel is effectively being ignored, and the colours are always assumed to be completely solid. `ColourToBase52()` is ignoring the alpha value, and `ColourFromBase52()` is setting it to 0xff (solid) where it does `0xFF000000 | value`. – Matthew Watson Jul 23 '14 at 14:13