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); }
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); }
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)); }