C# :: Aufgabe #180

3 Lösungen Lösungen öffentlich

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.

Lösungen:

vote_ok
von hollst (7410 Punkte) - 19.07.2017 um 14:45 Uhr
Quellcode ausblenden 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();
        }
    }
}
vote_ok
von hollst (7410 Punkte) - 21.07.2017 um 14:14 Uhr
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.

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


Quellcode ausblenden 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>
vote_ok
von daniel59 (3090 Punkte) - 24.08.2017 um 15:38 Uhr
MainWindow.xaml.cs
Quellcode ausblenden C#-Code
using 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
Quellcode ausblenden 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>