using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace WindowsFormsApplication2 { public partial class Form1 : Form { public struct triple { public int r; public int g; public int b; }; public int distance(triple a, triple b) { return (a.r - b.r) * (a.r - b.r) + (a.g - b.g) * (a.g - b.g) + (a.b - b.b) * (a.b - b.b); } public Form1() { InitializeComponent(); } Bitmap pic1; private void button1_Click(object sender, EventArgs e) { OpenFileDialog open_dialog = new OpenFileDialog(); open_dialog.Title = "Open Picture"; open_dialog.Filter = "Bitmap Files (*.bmp)|*.bmp"; if (open_dialog.ShowDialog() == DialogResult.OK) { pic1 = new Bitmap(open_dialog.FileName); pictureBox1.Image = pic1; } open_dialog.Dispose(); } private void button2_Click(object sender, EventArgs e) { this.Cursor = Cursors.WaitCursor; //int[,] par = new int[pic1.Width, pic1.Height]; int num_colors = Convert.ToInt32(textBox1.Text); List colors = new List(); Bitmap pic2 = new Bitmap(pic1); for (int i = 0; i < pic1.Width; i++) for (int j = 0; j < pic1.Height; j++) { Color color1 = pic1.GetPixel(i, j); triple cur; cur.r = color1.R; cur.g = color1.G; cur.b = color1.B; colors.Add(cur); } colors = colors.Distinct().ToList(); if( colors.Count() <= num_colors ) { pictureBox2.Image = pic2; this.Cursor = Cursors.Default; return; } triple[] means = new triple[num_colors]; bool[] used = new bool[colors.Count()]; Random r = new Random(); for (int i = 0; i < num_colors; i++) { int random_index; while( true ) { random_index = r.Next(0,colors.Count()); if( used[random_index] == true ) continue; break; } means[i] = colors[random_index]; } int[] par = new int[colors.Count()]; for (int i = 0; i < colors.Count(); i++) { int cur_dis = distance(colors[i], means[0]); par[i] = 0; for (int k = 1; k < num_colors; k++) { int temp = distance(colors[i], means[k]); if (temp < cur_dis) { cur_dis = temp; par[i] = k; } } } bool change = true; int sepid = 10; triple[] sum = new triple[num_colors]; int[] cnt = new int[num_colors]; while( change && (--sepid != 0) ) { change = false; //creating new means for( int i = 0; i < num_colors; i++ ) sum[i].r = sum[i].g = sum[i].b = cnt[i] = 0; for (int i = 0; i < colors.Count(); i++) { sum[par[i]].r += colors[i].r; sum[par[i]].g += colors[i].g; sum[par[i]].b += colors[i].b; cnt[par[i]]++; } for (int i = 0; i < num_colors; i++) { if (cnt[i] == 0) { int someoneelse = r.Next(0, colors.Count()); means[i].r = colors[someoneelse].r; means[i].g = colors[someoneelse].g; means[i].b = colors[someoneelse].b; continue; } means[i].r = sum[i].r / cnt[i]; means[i].g = sum[i].g / cnt[i]; means[i].b = sum[i].b / cnt[i]; } //recalculating the clusters for (int i = 0; i < colors.Count(); i++) { int cur_dis = distance(colors[i], means[0]); for (int k = 1; k < num_colors; k++) { int temp = distance(colors[i], means[k]); if (temp < cur_dis) { cur_dis = temp; if (par[i] != k) { par[i] = k; change = true; } } } } } Dictionary convert = new Dictionary(); for (int i = 0; i < colors.Count(); i++) { try { convert.Add(colors[i], means[par[i]]); } catch { }; } for( int i = 0; i < pic2.Width; i++ ) for (int j = 0; j < pic2.Height; j++) { Color color1 = pic1.GetPixel(i, j); triple cur; cur.r = color1.R; cur.g = color1.G; cur.b = color1.B; cur = convert[cur]; color1 = Color.FromArgb(cur.r, cur.g, cur.b); pic2.SetPixel(i, j, color1); } pictureBox2.Image = pic2; this.Cursor = Cursors.Default; } } }