Entwickler-Ecke

WinForms - TrackBar ValueChanged/Helligkeit,Kontrast Probleme


Delete - Mi 29.06.11 20:15
Titel: TrackBar ValueChanged/Helligkeit,Kontrast Probleme
Hallo Leute,

habe folgendes Problem, wollte wenn sich der Wert von einer TrackBar verändert den Kontrast eines Bildes verändern, das funktioniert auch gut aber wenn den Schieberegler z.b. mal von 0 bis 100 verschoben wird, versucht das Programm bei jeder Zahl den Kontrast Wert zu verändern und das wikrt sich natürlich ziemlich auf den Speicher aus, hatte es dann versucht mit dem Event MouseUp, das hat dann auch gut funktioniert, nur leider nur wenn ich mit der Maus etwas mache, bei Keys müsste ich noch ein KeyUp Event machen aber der Schieberegler kann ja auch mit dem Mausrad bewegt werden, und dann bringen mir die vorigen Events garnichts mehr, gibts es da einen Weg ValueChanged so zu modifizieren das das Event erst ausgelöst wird wenn der Schieberegler sich nicht mehr bewegt/losgelassen wird ?

Liebe Grüße BleachRukia


Ralf Jansen - Mi 29.06.11 20:55

Eine Methode die sicher funktioniert unabhängig von der Art wie der Value der Trackbar verändert wird wäre im ValueChanged einen Timer zustarten(restarten) in dessen Timermethode der eigentlich auszuführende Code zur Kontrastanpassung steckt. Dann wird der Kontrast nur geeändert wenn über die Länge des Timerintervalls keiner an der Trackbar rumgeschraubt hat.

Also in etwa so


C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
private Timer timer = new Timer();

// irgendwo initialisieren z.b. in Form_Load
timer.Interval = 300;  // passenden Wert noch ermitteln
timer.Tick += timer_Tick;

private void DeineTrackBar_ValueChanged(object sender, EventArgs e)
{
    timer.Stop();
    timer.Start();
}

private void timer_Tick(object sender, EventArgs e)
{
    timer.Stop();
// dein Code zum Kontrast ändern von hier aufrufen
}


Delete - Mi 29.06.11 21:21

Hallo,

vielen vielen dank für deine Antwort, dein Code funktioniert eigentlich auch ganz gut nur leider nicht ganz perfekt, habe deinen Code mal mit diesem Beispiel ausprobiert:


C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
        private Timer timer = new Timer();
        public Form1()
        {
            InitializeComponent();
            // irgendwo initialisieren z.b. in Form_Load
            timer.Interval = 300;  // passenden Wert noch ermitteln
            timer.Tick += timer_Tick;
        }

        private void trackBar1_ValueChanged(object sender, EventArgs e)
        {
            timer.Stop();
            timer.Start();
        }

        private void timer_Tick(object sender, EventArgs e)
        {
            timer.Stop();
            this.Text = "";
        }


Wenn ich den Schiebregler bewege passiert garnichts, so soll es ja auch sein aber wenn ich den Schieberegler dann nicht mehr bewege aber noch gedrückt halte löst das Programm leider das Event aus :(

Aber mal eine ganz andere Frage, habe bei Photoshop gesehen das wenn ich den Contrast meines Bildes verändere er bei jeder Zahl der Trackbar ohne zu ruckeln den Contrast verändert (Vorschau), wie haben die Macher von Photoshop das geschafft ?

Habe zum Thema Bildbearbeitung nur das im Netz gefunden, das auch wirklich am schnellsten funktioniert hat: http://www.codeproject.com/KB/GDI-plus/csharpgraphicfilters11.aspx

Aus deisem Projekt benutze ich den CorlorFilter, der sieht bei Contrats so aus:


C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
        public static bool Contrast(Bitmap b, sbyte nContrast)
        {
            if (nContrast < -100return false;
            if (nContrast > 100return false;

            double pixel = 0, contrast = (100.0 + nContrast) / 100.0;

            contrast *= contrast;

            int red, green, blue;

            // GDI+ still lies to us - the return format is BGR, NOT RGB.
            BitmapData bmData = b.LockBits(new Rectangle(00, b.Width, b.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);

            int stride = bmData.Stride;
            System.IntPtr Scan0 = bmData.Scan0;

            unsafe
            {
                byte* p = (byte*)(void*)Scan0;

                int nOffset = stride - b.Width * 3;

                for (int y = 0; y < b.Height; ++y)
                {
                    for (int x = 0; x < b.Width; ++x)
                    {
                        blue = p[0];
                        green = p[1];
                        red = p[2];

                        pixel = red / 255.0;
                        pixel -= 0.5;
                        pixel *= contrast;
                        pixel += 0.5;
                        pixel *= 255;
                        if (pixel < 0) pixel = 0;
                        if (pixel > 255) pixel = 255;
                        p[2] = (byte)pixel;

                        pixel = green / 255.0;
                        pixel -= 0.5;
                        pixel *= contrast;
                        pixel += 0.5;
                        pixel *= 255;
                        if (pixel < 0) pixel = 0;
                        if (pixel > 255) pixel = 255;
                        p[1] = (byte)pixel;

                        pixel = blue / 255.0;
                        pixel -= 0.5;
                        pixel *= contrast;
                        pixel += 0.5;
                        pixel *= 255;
                        if (pixel < 0) pixel = 0;
                        if (pixel > 255) pixel = 255;
                        p[0] = (byte)pixel;

                        p += 3;
                    }
                    p += nOffset;
                }
            }

            b.UnlockBits(bmData);

            return true;
        }


Gibt es da nicht eine Lösung dafür das wenn ich das Bild bearbeite, das das Programm nicht ruckelt wenn ich das Bild mit Vorschau verändern will ?

Liebe Grüße BleachRukia


Ralf Jansen - Mi 29.06.11 21:55

Zitat:
Wenn ich den Schiebregler bewege passiert garnichts, so soll es ja auch sein aber wenn ich den Schieberegler dann nicht mehr bewege aber noch gedrückt halte löst das Programm leider das Event aus


Ich würde das als wünschenswertes bezeichnen und nicht als Problem. Wenn jemand den Regler sehr langsam verschiebt bekommt er so zwischendurch auch eine Aktualisierung. Um sich zu orientieren ob man den gewünschten Kontrast erreicht hat hilfreich. Oder habe ich dein Problem mit dem Verhalten nicht verstanden?

Zitat:
Aber mal eine ganz andere Frage, habe bei Photoshop gesehen das wenn ich den Contrast meines Bildes verändere er bei jeder Zahl der Trackbar ohne zu ruckeln den Contrast verändert (Vorschau), wie haben die Macher von Photoshop das geschafft ?


Weil die vermutlich nachgedacht und optimierten eigenen Code erstellt haben und nicht einfach irgendeinen (im schlimmsten Fall auch noch unverstandenen) Code ergoggelt haben? Spekulativ könnten die das z.B. ebenfalls mit einem Timer gemacht haben dabei aber einfach nur mit einem kurzen Timerintervall der dir nicht auffällt. Aber abgestimmt ist auf deren Geschwindigkeit der Kontrastanpassung. Das angepasste Bild wird in einem nebenläufigen Thread während der Timer läuft vorbereitet und wenn der Timer tatsächlich abläuft ist das Bild bereits fertig und muss nur ausgetauscht werden.


Delete - Do 30.06.11 02:35

Hallo,

hatte noch einmal im Nezt ein bisschen gesucht gehabt und bin auf ColorMatrix gestoßen, nachdem ich mir ein paar Erklärungen durchgelesen habe und auch ein paar Beispiele ausprobiert habe kann ich einfach nur sagen WOW, die Geschwindigkeit in der Bilder bearbeitet werden ist einfach unglaublich, solbald ich alle bearbeitungs Sachen die ich brauche ausprobiert habe, werde ich die fertigen Codes hier in den Beitrag + Erklärunglinks posten damit andere Leuten nicht auch so lange suchen müssen wie ich :D

Liebe Grüße BleachRukia


Delete - Do 30.06.11 23:42

Hallo Leute,

bevor ich jetzt den ganzen Code reinposte habe ich noch ein riesiges Problem bei dem ich Hilfe brauche:

Mit diesem Code hier:


C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{    
    public partial class Form1 : Form
    {
        Bitmap NewImage;
        public Form1()
        {
            InitializeComponent();
            NewImage = new Bitmap(pictureBox1.Image);
        }

        private void trackBar1_ValueChanged(object sender, EventArgs e)
        {
            pictureBox1.Image = EditBrightness(NewImage, (float)trackBar1.Value / 100);
        }

        public static Bitmap EditBrightness(Bitmap InputImage, float Brightness)
        {
            //Create a blank bitmap the same size as original
            Bitmap EditImage = new Bitmap(InputImage.Width, InputImage.Height);

            //Get a graphics object from the new image
            Graphics Graphics = Graphics.FromImage(EditImage);

            //Create the ImageEdit ColorMatrix
            ColorMatrix colorMatrix = new ColorMatrix(
               new float[][]
      {
         new float[] {10000},
         new float[] {01000},
         new float[] {00100},
         new float[] {00010},
         new float[] {Brightness, Brightness, Brightness, 01}
      });

            //Create some image attributes
            ImageAttributes ImageAttributes = new ImageAttributes();

            //Set the color matrix attribute
            ImageAttributes.SetColorMatrix(colorMatrix);

            //Draw the original image on the new image
            //Using the ImageEdit ColorMatrix
            Graphics.DrawImage(InputImage, new Rectangle(00, InputImage.Width, InputImage.Height),
               00, InputImage.Width, InputImage.Height, GraphicsUnit.Pixel, ImageAttributes);

            //Dispose the Graphics object
            Graphics.Dispose();
            return EditImage;
        }
    }
}


kann ich wunderbar und super schnell den Helligkeits Wert eines Bildes verändern nur wenn ich zu oft auf der Trackbar rauf und runter fahre bekomme ich jedes mal eine OutOfMemoryException also das nicht genügend Arbeitsspeicher frei wäre, wie kann ich dieses Problem vorbeugen, dachte eigentlich mit Graphics.Dispose(); wäre das schon passiert ?

Liebe Grüße BleachRukia


Ralf Jansen - Fr 01.07.11 00:02

Zitat:
dachte eigentlich mit Graphics.Dispose(); wäre das schon passiert ?


Für das Graphics Object ja. Nicht aber z.B. für das alte Bitmap in deiner Picturebox das du in trackBar1_ValueChanged ersetzt.


Delete - Fr 01.07.11 00:10

Hallo,

tausend Dank, mit pictureBox1.Image.Dispose(); funktioniert es jetzt :D

Liebe Grüße BleachRukia


Delete - Fr 01.07.11 03:57

Hallo Leute,

bin endlich fertig mit meinen kleinen Mini Projekt und hier ist der Code + Erklärung:

Als erstes habe ich 3 Buttons erstellt (Invert, Grayscale, Reset) danach 2 Trackbars (Helligkeit, Kontrast) und zu guter letzt 2 Bitmpas, damit die bearbeitungen untereinander kombiniert werden können, die Bildbearbeitungen Berechnung habe ich in eine extra Klasse namens ColorEdit geschrieben :)

Bei der Helligkeits Trackbar ist der MinWert = -100 und der MaxWert +100, die TickFrequency = 10, Value = 0,
bei der Kontrast Trackbar ist der Minwert = 0 und der MaxWert = 200, die TickFrequency = 10, Value = 100.

Das Grundgerüst für die ColorMatrix habe ich auf dieser Webseite gefunden, auf dieser Seite werden 3 super Möglichkeiten vorgestellt wie man Farbe eines Bildes bearbeiten kann: http://www.switchonthecode.com/tutorials/csharp-tutorial-convert-a-color-image-to-grayscale

Aber die Möglichkeiten der ColorMatrix habe ich auf dieser Webseite in super Beispielen gefunden: http://rainmeter.net/RainCMS/?q=TipsAndTricksColorMatrixUnleashed

FormCode:


C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{    
    public partial class Form1 : Form
    {
        Bitmap NewImage, EditImage;
        public Form1()
        {
            InitializeComponent();
            NewImage = new Bitmap(pictureBox1.Image);
            EditImage = new Bitmap(pictureBox1.Image);
        }
        
        private void GrayscaleButton_Click(object sender, EventArgs e)
        {
            EditImage.Dispose();
            this.pictureBox1.Image = ColorEdit.Grayscale((Bitmap)this.pictureBox1.Image);
            EditImage = new Bitmap(pictureBox1.Image);
        }

        private void InvertButton_Click(object sender, EventArgs e)
        {
            EditImage.Dispose();
            this.pictureBox1.Image = ColorEdit.Invert((Bitmap)this.pictureBox1.Image);
            EditImage = new Bitmap(pictureBox1.Image);
        }

        private void ResetButton_Click(object sender, EventArgs e)
        {
            this.BrightnessTrackBar.Value = 0;
            this.ContrastTrackBar.Value = 100;
        }

        private void BrightnessTrackBar_ValueChanged(object sender, EventArgs e)
        {
            this.pictureBox1.Image.Dispose();
            NewImage = new Bitmap(EditImage);
            this.pictureBox1.Image = ColorEdit.Brightness(NewImage, (float)this.BrightnessTrackBar.Value / 100);
            NewImage = new Bitmap(pictureBox1.Image);
            this.pictureBox1.Image = ColorEdit.Contrast(NewImage, (float)this.ContrastTrackBar.Value / 100);
            NewImage.Dispose();
        }

        private void ContrastTrackBar_ValueChanged(object sender, EventArgs e)
        {
            this.pictureBox1.Image.Dispose();
            NewImage = new Bitmap(EditImage);
            this.pictureBox1.Image = ColorEdit.Brightness(NewImage, (float)this.BrightnessTrackBar.Value / 100);
            NewImage = new Bitmap(pictureBox1.Image);
            this.pictureBox1.Image = ColorEdit.Contrast(NewImage, (float)this.ContrastTrackBar.Value / 100);
            NewImage.Dispose();
        }
    }
}


ColorEditCode:


C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:
132:
133:
134:
135:
136:
137:
138:
139:
140:
141:
142:
143:
144:
145:
146:
147:
148:
149:
150:
151:
152:
153:
154:
155:
156:
157:
158:
159:
160:
161:
162:
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.Text;

namespace WindowsFormsApplication1
{
    class ColorEdit
    {
        public static Bitmap Invert(Bitmap InputImage)
        {
            //Create a blank bitmap the same size as original.
            Bitmap EditImage = new Bitmap(InputImage.Width, InputImage.Height);

            //Get a graphics object from the new image.
            Graphics Graphics = Graphics.FromImage(EditImage);

            //Create the ImageEdit ColorMatrix.
            ColorMatrix colorMatrix = new ColorMatrix(
               new float[][]
      {
         new float[] {-10000},
         new float[] {0, -1000},
         new float[] {00, -100},
         new float[] {00010},
         new float[] {11101}
      });

            //Create some image attributes.
            ImageAttributes ImageAttributes = new ImageAttributes();

            //Set the color matrix attribute.
            ImageAttributes.SetColorMatrix(colorMatrix);

            //Draw the original image on the new image.
            //Using the ImageEdit ColorMatrix
            Graphics.DrawImage(InputImage, new Rectangle(00, InputImage.Width, InputImage.Height),
               00, InputImage.Width, InputImage.Height, GraphicsUnit.Pixel, ImageAttributes);

            //Dispose the Graphics objects.
            InputImage.Dispose();
            Graphics.Dispose();

            return EditImage;
        }
        
        public static Bitmap Grayscale(Bitmap InputImage)
        {
            //Create a blank bitmap the same size as original.
            Bitmap EditImage = new Bitmap(InputImage.Width, InputImage.Height);

            //Get a graphics object from the new image.
            Graphics Graphics = Graphics.FromImage(EditImage);

            //Create the ImageEdit ColorMatrix.
            ColorMatrix colorMatrix = new ColorMatrix(
               new float[][]
      {
         new float[] {0.3f0.3f0.3f00},
         new float[] {0.59f0.59f0.59f00},
         new float[] {0.11f0.11f0.11f00},
         new float[] {00010},
         new float[] {00001}
      });

            //Create some image attributes.
            ImageAttributes ImageAttributes = new ImageAttributes();

            //Set the color matrix attribute.
            ImageAttributes.SetColorMatrix(colorMatrix);

            //Draw the original image on the new image.
            //Using the ImageEdit ColorMatrix
            Graphics.DrawImage(InputImage, new Rectangle(00, InputImage.Width, InputImage.Height),
               00, InputImage.Width, InputImage.Height, GraphicsUnit.Pixel, ImageAttributes);

            //Dispose the Graphics objects.
            InputImage.Dispose();
            Graphics.Dispose();

            return EditImage;
        }

        public static Bitmap Brightness(Bitmap InputImage, float Brightness)
        {
            //Create a blank bitmap the same size as original.
            Bitmap EditImage = new Bitmap(InputImage.Width, InputImage.Height);

            //Get a graphics object from the new image.
            Graphics Graphics = Graphics.FromImage(EditImage);

            //Create the ImageEdit ColorMatrix.
            ColorMatrix colorMatrix = new ColorMatrix(
               new float[][]
      {
         new float[] {10000},
         new float[] {01000},
         new float[] {00100},
         new float[] {00010},
         new float[] {Brightness, Brightness, Brightness, 01}
      });

            //Create some image attributes.
            ImageAttributes ImageAttributes = new ImageAttributes();

            //Set the color matrix attribute.
            ImageAttributes.SetColorMatrix(colorMatrix);

            //Draw the original image on the new image.
            //Using the ImageEdit ColorMatrix
            Graphics.DrawImage(InputImage, new Rectangle(00, InputImage.Width, InputImage.Height),
               00, InputImage.Width, InputImage.Height, GraphicsUnit.Pixel, ImageAttributes);

            //Dispose the Graphics objects.
            InputImage.Dispose();
            Graphics.Dispose();

            return EditImage;
        }
        
        public static Bitmap Contrast(Bitmap InputImage, float Contrast)
        {
            //Create a blank bitmap the same size as original.
            Bitmap EditImage = new Bitmap(InputImage.Width, InputImage.Height);

            //Get a graphics object from the new image.
            Graphics Graphics = Graphics.FromImage(EditImage);

            float T = (1.0f - Contrast) / 2.0f;

            //Create the ImageEdit ColorMatrix.
            ColorMatrix colorMatrix = new ColorMatrix(
               new float[][]
      {
         new float[] {Contrast, 0000},
         new float[] {0, Contrast, 000},
         new float[] {00, Contrast, 00},
         new float[] {00010},
         new float[] {T, T, T, 01}
      });

            //Create some image attributes.
            ImageAttributes ImageAttributes = new ImageAttributes();

            //Set the color matrix attribute.
            ImageAttributes.SetColorMatrix(colorMatrix);

            //Draw the original image on the new image.
            //Using the ImageEdit ColorMatrix
            Graphics.DrawImage(InputImage, new Rectangle(00, InputImage.Width, InputImage.Height),
               00, InputImage.Width, InputImage.Height, GraphicsUnit.Pixel, ImageAttributes);

            //Dispose the Graphics objects.
            InputImage.Dispose();
            Graphics.Dispose();

            return EditImage;
        }
    }
}


Ich hoffe das die Leuten die die selben Probleme mit Bildbearbeitung hatten wie ich jetzt keine mehr haben werden :D

Liebe Grüße BleachRukia