public static Bitmap ReduceColors(Bitmap image, int numberOfColors)
        {
            Bitmap                    _return  = new Bitmap(image.Width, image.Height);
            MyColorComparer           comparer = new MyColorComparer();
            Dictionary <MyColor, int> dict     = new Dictionary <MyColor, int>(comparer);

            for (int i = 0; i < image.Width; ++i)
            {
                for (int j = 0; j < image.Height; ++j)
                {
                    MyColor color = new MyColor(image.GetPixel(i, j));
                    if (dict.ContainsKey(color))
                    {
                        dict[color]++;
                    }
                    else
                    {
                        dict[color] = 0;
                    }
                }
            }
            List <KeyValuePair <MyColor, int> > dictList = dict.ToList();

            dictList.Sort((a, b) => b.Value - a.Value);
            dict = dictList.GetRange(0, numberOfColors <= dictList.Count ? numberOfColors : dictList.Count).ToDictionary(x => x.Key, x => x.Value, comparer);
            for (int i = 0; i < image.Width; ++i)
            {
                for (int j = 0; j < image.Height; ++j)
                {
                    int     minDist      = int.MaxValue;
                    MyColor color        = new MyColor(0, 0, 0);
                    MyColor currentColor = new MyColor(image.GetPixel(i, j));
                    foreach (var elem in dict)
                    {
                        int dist = elem.Key.Distance(currentColor);
                        if (dist < minDist)
                        {
                            minDist = dist;
                            color   = elem.Key;
                        }
                    }
                    _return.SetPixel(i, j, color.ToColor());
                }
            }
            return(_return);
        }
Пример #2
0
        public static Bitmap ReduceColors(Bitmap image, FilterMatrix filterMatrix, int numberOfColors, bool blackAndWhite)
        {
            double[,] filter = new double[1, 1];
            switch (filterMatrix)
            {
            case FilterMatrix.FloydAndSteinberg:
                filter = new double[3, 3];
                for (int i = 0; i < 3; ++i)
                {
                    for (int j = 0; j < 3; ++j)
                    {
                        filter[i, j] = 0;
                    }
                }
                filter[2, 1] = 7.0 / 16;
                filter[0, 2] = 3.0 / 16;
                filter[1, 2] = 5.0 / 16;
                filter[2, 2] = 1.0 / 16;
                break;

            case FilterMatrix.Burkes:
                filter = new double[5, 3];
                for (int i = 0; i < 5; ++i)
                {
                    for (int j = 0; j < 3; ++j)
                    {
                        filter[i, j] = 0;
                    }
                }
                filter[3, 1] = 8.0 / 32;
                filter[4, 1] = 4.0 / 32;
                filter[0, 2] = 2.0 / 32;
                filter[1, 2] = 4.0 / 32;
                filter[2, 2] = 8.0 / 32;
                filter[3, 2] = 4.0 / 32;
                filter[4, 2] = 2.0 / 32;
                break;

            case FilterMatrix.Stucky:
                filter = new double[5, 5];
                for (int i = 0; i < 5; ++i)
                {
                    for (int j = 0; j < 5; ++j)
                    {
                        filter[i, j] = 0;
                    }
                }
                filter[3, 2] = 8.0 / 42;
                filter[4, 2] = 4.0 / 42;
                filter[0, 3] = 2.0 / 42;
                filter[1, 3] = 4.0 / 42;
                filter[2, 3] = 8.0 / 42;
                filter[3, 3] = 4.0 / 42;
                filter[4, 3] = 2.0 / 42;
                filter[0, 4] = 1.0 / 42;
                filter[1, 4] = 2.0 / 42;
                filter[2, 4] = 4.0 / 42;
                filter[3, 4] = 2.0 / 42;
                filter[4, 4] = 1.0 / 42;
                break;

            default:
                break;
            }

            Bitmap _return = new Bitmap(image.Width, image.Height);

            MyColor[,] table = new MyColor[image.Width, image.Height];
            for (int x = 0; x < image.Width; ++x)
            {
                for (int y = 0; y < image.Height; ++y)
                {
                    table[x, y] = new MyColor(image.GetPixel(x, y));
                }
            }
            int diffX = filter.GetLength(0) / 2;
            int diffY = filter.GetLength(1) / 2;

            for (int y = 0; y < image.Height; ++y)
            {
                for (int x = 0; x < image.Width; ++x)
                {
                    MyColor oldPixel = table[x, y];
                    MyColor K        = Approximate(table[x, y].ToColor(), numberOfColors, blackAndWhite);
                    table[x, y] = K;
                    MyColor error = oldPixel - table[x, y];
                    for (int i = 0; i < filter.GetLength(0); ++i)
                    {
                        for (int j = 0; j < filter.GetLength(1); ++j)
                        {
                            if (x + i - diffX >= 0 && y + j - diffY >= 0 && x + i - diffX < table.GetLength(0) && y + j - diffY < table.GetLength(1))
                            {
                                table[x + i - diffX, y + j - diffY] = table[x + i - diffX, y + j - diffY] + (error * filter[i, j]);
                            }
                        }
                    }
                }
            }
            for (int x = 0; x < image.Width; ++x)
            {
                for (int y = 0; y < image.Height; ++y)
                {
                    _return.SetPixel(x, y, table[x, y].ToColor());
                }
            }
            return(_return);
        }
        public static Bitmap ReduceColors(Bitmap image, int numberOfColors)
        {
            Bitmap _return = new Bitmap(image.Width, image.Height);

            List <MyColor>[] centroids1 = new List <MyColor> [numberOfColors];
            List <MyColor>[] centroids2 = new List <MyColor> [numberOfColors];
            for (int i = 0; i < numberOfColors; ++i)
            {
                centroids1[i] = new List <MyColor>();
                centroids2[i] = new List <MyColor>();
                centroids1[i].Add(new MyColor(rand.Next(256), rand.Next(256), rand.Next(256), rand.Next(256)));
            }
            List <MyColor>[] centroids = centroids1;
            List <MyColor>[] last      = centroids2;
            bool             flag      = true;

            while (flag)
            {
                for (int x = 0; x < image.Width; ++x)
                {
                    for (int y = 0; y < image.Height; ++y)
                    {
                        int     minDist    = int.MaxValue;
                        int     ind        = -1;
                        MyColor pixelColor = new MyColor(image.GetPixel(x, y));
                        for (int i = 0; i < numberOfColors; ++i)
                        {
                            int dist = pixelColor.Distance(centroids[i].First());
                            if (dist < minDist)
                            {
                                minDist = dist;
                                ind     = i;
                            }
                        }
                        centroids[ind].Add(pixelColor);
                    }
                }
                if (last[0].Count == 0)
                {
                    last      = centroids1;
                    centroids = centroids2;
                }
                else
                {
                    flag = false;
                    for (int i = 0; i < numberOfColors; ++i)
                    {
                        if (centroids[i].Count != last[i].Count)
                        {
                            flag = true;
                            break;
                        }
                        for (int j = 1; j < centroids[i].Count; ++j)
                        {
                            if (centroids[i][j] != last[i][j])
                            {
                                flag = true;
                                break;
                            }
                        }
                        if (flag)
                        {
                            break;
                        }
                    }
                    if (flag)
                    {
                        if (centroids == centroids1)
                        {
                            centroids2 = new List <MyColor> [numberOfColors];
                            centroids  = centroids2;
                            last       = centroids1;
                        }
                        else
                        {
                            centroids1 = new List <MyColor> [numberOfColors];
                            centroids  = centroids1;
                            last       = centroids2;
                        }
                    }
                }
                if (flag)
                {
                    for (int i = 0; i < numberOfColors; ++i)
                    {
                        MyColor avg = new MyColor(0, 0, 0, 0);
                        for (int j = 1; j < last[i].Count; ++j)
                        {
                            avg = avg + last[i][j];
                        }
                        avg          = avg / (last[i].Count < 2 ? 1 : last[i].Count - 1);
                        centroids[i] = new List <MyColor>();
                        centroids[i].Add(avg);
                    }
                }
            }
            for (int x = 0; x < image.Width; ++x)
            {
                for (int y = 0; y < image.Height; ++y)
                {
                    int     minDist    = int.MaxValue;
                    int     ind        = -1;
                    MyColor pixelColor = new MyColor(image.GetPixel(x, y));
                    for (int i = 0; i < numberOfColors; ++i)
                    {
                        int dist = pixelColor.Distance(centroids[i].First());
                        if (dist < minDist)
                        {
                            minDist = dist;
                            ind     = i;
                        }
                    }
                    _return.SetPixel(x, y, centroids[ind].First().ToColor());
                }
            }
            return(_return);
        }
Пример #4
0
 public int Distance(MyColor color)
 {
     return(((int)A - (int)color.A) * ((int)A - (int)color.A) + ((int)R - (int)color.R) * ((int)R - (int)color.R) + ((int)G - (int)color.G) * ((int)G - (int)color.G) + ((int)B - (int)color.B) * ((int)B - (int)color.B));
 }