C# :: Aufgabe #180
                         
        3 Lösungen
         
         
        
      
                
        
     
        
      Farben/Pixel sortieren
        Fortgeschrittener - C#
        von KawaiiShox
         - 29.06.2017 um 11:39 Uhr
      
       
      
        Es soll ein Programm erstellt werden, welches zufällig erstellte Pixel nach der Farbe sortieren kann.
Das Programm soll dabei ungefähr so aussehen, wie auf Bild1.
Im ersten Teil der Aufgabe soll es , durch das Drücken eines Buttons, möglich sein ein Panel mit Pixeln, die alle eine zufällig generierte Farbe besitzen, zu füllen. (Bild2)
Als nächstes sollen dann alle Pixel des Panels sortiert werden(Bild3). In diesem Beispiel habe ich die Pixel nach ihrem "HUE" sortiert. Spannend wäre aber auch zu wissen, wie es aussieht, wenn man die Pixel nach einem anderem Kriterium sortiert.
Wer möchte, kann aber auch die Pixel eines bestimmten Bildes sortieren.
         
     
   Das Programm soll dabei ungefähr so aussehen, wie auf Bild1.
Im ersten Teil der Aufgabe soll es , durch das Drücken eines Buttons, möglich sein ein Panel mit Pixeln, die alle eine zufällig generierte Farbe besitzen, zu füllen. (Bild2)
Als nächstes sollen dann alle Pixel des Panels sortiert werden(Bild3). In diesem Beispiel habe ich die Pixel nach ihrem "HUE" sortiert. Spannend wäre aber auch zu wissen, wie es aussieht, wenn man die Pixel nach einem anderem Kriterium sortiert.
Wer möchte, kann aber auch die Pixel eines bestimmten Bildes sortieren.
Lösungen:
 C#-Code
 C#-Code
using System;
using System.Collections.Generic;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
namespace aufgabe_180_form  {
    public partial class Form1 : Form    {
        Random rand = new Random();
        public Form1()  { InitializeComponent(); comboBox1.SelectedIndex = 0; }
        private void button1_Click(object sender, EventArgs e)        {
            Bitmap bm = new Bitmap(this.pictureBox1.Width, this.pictureBox1.Height);
            for(var i = 0; i < bm.Height; i++)
                for(var j = 0; j < bm.Width; j++)   {
                    Color c = Color.FromArgb(rand.Next(255), rand.Next(255), rand.Next(255));
                    bm.SetPixel(j, i, c);
                }
            pictureBox1.Image = bm;
        }
        private void button2_Click(object sender, EventArgs e)        {
            Bitmap bm = new Bitmap(pictureBox1.Image), bm_sorted = new Bitmap(bm);
            for(var h = 0; h < bm.Height; h++)  {
                Dictionary<int, double> d = new Dictionary<int, double>();
                for (int x = 0; x < bm.Width; x++)
                    switch (comboBox1.SelectedIndex) {
                        case 0: d.Add(x, bm.GetPixel(x, h).GetHue()); break;
                        case 1: d.Add(x, bm.GetPixel(x, h).GetBrightness()); break;
                        case 2: d.Add(x, bm.GetPixel(x, h).R); break;
                        case 3: d.Add(x, bm.GetPixel(x, h).G); break;
                        case 4: d.Add(x, bm.GetPixel(x, h).B); break;
                    }
                var items = from pair in d
                            orderby pair.Value ascending
                            select pair;
                int counter = 0;
                foreach (KeyValuePair<int, double> index_x in items)   {
                    bm_sorted.SetPixel(counter, h, bm.GetPixel(index_x.Key, h));
                    counter++;
                }
                pictureBox1.Image = bm_sorted;
            }
        }
        private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
        {
            this.pictureBox1.Focus();
        }
    }
}
        Hier noch ein Lösungsvorschlag in WPF, wo es ja bekanntlich (leider) keine PictureBox mehr gibt, 
deshalb muss man sich mit WPF schon ganz schön winden.
 C#-Code
 C#-Code
 C#-Code
 C#-Code
          
      
     
    deshalb muss man sich mit WPF schon ganz schön winden.
 C#-Code
 C#-Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Drawing;
using System.IO;
namespace aufgabe_180_WPF   {
    public partial class MainWindow : Window    {
        Random rand = new Random();
        public int[] random_pixel;
        int Empty_BitMapImage_h = 400, Empty_BitMapImage_w = 400;
        public static BitmapImage Create_Empty_BitMapImage(int width, int height)
        {            
            Bitmap bitmap = new Bitmap(width, height);
            BitmapImage image = new BitmapImage();
            using (MemoryStream memory = new MemoryStream())
            {
                bitmap.Save(memory, System.Drawing.Imaging.ImageFormat.Bmp);
                memory.Position = 0;
                image.BeginInit();
                image.StreamSource = memory;
                image.CacheOption = BitmapCacheOption.OnLoad;
                image.EndInit();
            }
            return image;
        }
        public MainWindow()        { InitializeComponent(); }        
        public void bt_1_Click(object sender, RoutedEventArgs e)
        {
            BitmapImage EmptyImage = Create_Empty_BitMapImage(Empty_BitMapImage_w, Empty_BitMapImage_h);
            BitmapSource bitmapSource = new FormatConvertedBitmap(EmptyImage, PixelFormats.Default, null, 0);
            WriteableBitmap RandomImage = new WriteableBitmap(bitmapSource);
            int h = RandomImage.PixelHeight;
            int w = RandomImage.PixelWidth;
            int[] pixelData = new int[w * h];
            int widthInByte = 4 * w;
            this.random_pixel = new int[w * h];
            for (var i = 0; i < random_pixel.Length; i++)
                random_pixel[i] = rand.Next(int.MinValue, int.MaxValue);
            RandomImage.WritePixels(new Int32Rect(0, 0, w, h), random_pixel, widthInByte, 0);
           
            image_org.Source = RandomImage;
        }
        private void bt_2_Click(object sender, RoutedEventArgs e)
        {
            BitmapImage EmptyImage = Create_Empty_BitMapImage(Empty_BitMapImage_w, Empty_BitMapImage_h);
            BitmapSource bitmapSource = new FormatConvertedBitmap(EmptyImage, PixelFormats.Default, null, 0);
            WriteableBitmap modifiedImage = new WriteableBitmap(bitmapSource);            
            int h = modifiedImage.PixelHeight;
            int w = modifiedImage.PixelWidth;
            int[] new_pixelData = new int[w * h];
            int widthInByte = 4 * w;
            int counter1 = 0, counter2 = 0;
            for (var y = 0; y < w; y++) {
                Dictionary<int, double> dict = new Dictionary<int, double>();
                for (int x = 0; x < h; x++) {
                    System.Drawing.Color c = System.Drawing.Color.FromArgb(random_pixel[counter1]);
                    dict.Add(counter1, c.GetHue());
                    counter1++;
                }
                var items = from pair in dict
                            orderby pair.Value ascending
                            select pair;
                               
                foreach (KeyValuePair<int, double> index_x in items)    {
                    new_pixelData[counter2] = random_pixel[index_x.Key];
                    counter2++;
                }
            }
            modifiedImage.WritePixels(new Int32Rect(0, 0, w, h), new_pixelData, widthInByte, 0);
            image_sorted.Source = modifiedImage;
            BmpBitmapEncoder bmpEncoder = new BmpBitmapEncoder();
            bmpEncoder.Frames.Add(BitmapFrame.Create(modifiedImage));
            using (System.IO.FileStream file = System.IO.File.OpenWrite("test.bmp"))    {
                bmpEncoder.Save(file);
            }
        }
    }
}
 C#-Code
 C#-Code
<Window x:Class="aufgabe_180_WPF.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:aufgabe_180_WPF"
        mc:Ignorable="d"
        Title="colour sorting WPF" Height="350" Width="525">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="1*"/>
            <ColumnDefinition Width="1*"/>
            <ColumnDefinition Width="1*"/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="45"/>
            <RowDefinition/>
            <RowDefinition Height="1*"/>
        </Grid.RowDefinitions>
        <Button x:Name="bt_1" Content=" random colours " HorizontalAlignment="Center" Margin="5" VerticalAlignment="Center" Click="bt_1_Click" Grid.ColumnSpan="2"/>
        <Button x:Name="bt_2" Content=" sort colours " Grid.Column="2" HorizontalAlignment="Center" Margin="5" VerticalAlignment="Center" Click="bt_2_Click" Grid.ColumnSpan="2"/>
        <Image x:Name="image_org" Grid.ColumnSpan="2" Margin="10,0,10,10" Grid.Row="1" Grid.RowSpan="2" />
        <Image x:Name="image_sorted" Grid.ColumnSpan="2" Margin="10,0,10,10" Grid.Row="1" Grid.Column="2" Grid.RowSpan="2"/>
    </Grid>
</Window>
        MainWindow.xaml.cs
 C#-Code
 C#-Code
MainWindow.xaml
 XML-Code
 XML-Code
                                         
         
         
        
          
        
        
        
        
        
        
        
                                                                        
        
        
        
      
     
     C#-Code
 C#-Codeusing System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Shapes;
namespace WpfFrabenSortieren
{
    /// <summary>
    /// Interaktionslogik für MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private const int width = 200;
        private const int height = 200;
        private static readonly Random rnd = new Random();
        private Dictionary<Point, Color> colorDic;
        public MainWindow()
        {
            InitializeComponent();
        }
        private void CreateRandomPixels()
        {
            colorDic = new Dictionary<Point, Color>();
            canvasPixel.Children.Clear();
            for (int x = 0; x < width; x++)
            {
                for (int y = 0; y < height; y++)
                {
                    Point p = new Point(x, y);
                    Color c = rnd.GetRandomColor();
                    Rectangle rect = new Rectangle() { Height = 1, Width = 1, StrokeThickness = 0, Fill = new SolidColorBrush(c) };
                    Canvas.SetLeft(rect, x);
                    Canvas.SetTop(rect, y);
                    canvasPixel.Children.Add(rect);
                    colorDic.Add(p, c);
                }
            }
        }
        private void SortPixel()
        {
            if (colorDic != null)
            {
                var sort = colorDic.OrderBy(a => a.Value.GetHue());
                var enumerator = sort.GetEnumerator();
                canvasPixel.Children.Clear();
                for (int x = 0; x < width; x++)
                {
                    for (int y = 0; y < height; y++)
                    {
                        Point p = new Point(x, y);
                        enumerator.MoveNext();
                        Color c = enumerator.Current.Value;
                        Rectangle rect = new Rectangle() { Height = 1, Width = 1, StrokeThickness = 0, Fill = new SolidColorBrush(c) };
                        Canvas.SetLeft(rect, x);
                        Canvas.SetTop(rect, y);
                        canvasPixel.Children.Add(rect);
                    }
                }
            }
        }
        private void buttonRandom_Click(object sender, RoutedEventArgs e)
        {
            CreateRandomPixels();
        }
        private void buttonSort_Click(object sender, RoutedEventArgs e)
        {
            SortPixel();
        }
    }
    static class Extensions
    {
        public static Color GetRandomColor(this Random rnd)
        {
            byte r = (byte)rnd.Next(0, 256);
            byte g = (byte)rnd.Next(0, 256);
            byte b = (byte)rnd.Next(0, 256);
            return Color.FromRgb(r, g, b);
        }
        public static double GetHue(this Color color)
        {
            double r = color.R / 255.0;
            double g = color.G / 255.0;
            double b = color.B / 255.0;
            double[] rgb = { r, g, b };
            double max = rgb.Max();
            double min = rgb.Min();
            double hue;
            if (r == max)
            {
                hue = (g - b) / (max - min);
            }
            else if (g == max)
            {
                hue = 2 + ((b - r) / (max - min));
            }
            else if (b == max)
            {
                hue = 4 + ((r - g) / (max - min));
            }
            else
            {
                throw new Exception();
            }
            hue *= 60;
            if (hue < 0)
            { hue += 360; }
            return hue;
        }
    }
}MainWindow.xaml
 XML-Code
 XML-Code<Window x:Class="WpfFrabenSortieren.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfFrabenSortieren"
        mc:Ignorable="d"
        Title="MainWindow" Height="322" Width="236" ResizeMode="CanMinimize" HorizontalAlignment="Left" VerticalAlignment="Top">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="1*"/>
            <RowDefinition Height="220"/>
        </Grid.RowDefinitions>
        <Canvas x:Name="canvasPixel" Width="200" Height="200" Grid.Row="1" Margin="10,10,0,0" Background="Black" HorizontalAlignment="Left" VerticalAlignment="Top"/>
        <Button x:Name="buttonRandom" Content="Zufällige Farben" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" Width="200" Click="buttonRandom_Click"/>
        <Button x:Name="buttonSort" Content="Farben sortieren" HorizontalAlignment="Left" Margin="10,37,0,0" VerticalAlignment="Top" Width="200" Click="buttonSort_Click"/>
    </Grid>
</Window>

 
    
    
     
            
