How to change the colors in an image?

Answered How to change the colors in an image?

  • Thursday, May 17, 2012 10:45 AM
     
     

    Can anybody guide me to some articles or tutorials on how to change the colors in an image? for example i want to change the color of a car from red to blue,That is only the body. How do i change the red pixels to blue so that it looks real? any suggestions or guidelines will help a lot. Thanks in advance.


    Thanks and Regards, Prashanth MP.

All Replies

  • Thursday, May 17, 2012 11:54 AM
     
     

    you can using of image processing :

    example : http://www.codeproject.com/Articles/9727/Image-Processing-Lab-in-C

  • Thursday, May 17, 2012 5:12 PM
     
     

    Hi,

    you either need to extract the portion of the image you want to change and then change the color, or you could change a range of colors in the original image if possible (and the impact on the rest of the image isnt too big...).

    I usually do things like that (changing colors of parts of images) by trying to change the colors first (usually changing the hue for a given range), if that works, its ok, if not, use a lasso-like tool to get an image that contains only the parts to change, then change the color and draw the modified over the original (maybe not only drawing, but "merging" with the original...).

    There are other possibilites like floodfilling with a mode that calculates the inserted color by the difference of the original color to the value of the original color at the start point etc...

    Regards,

      Thorsten

  • Monday, May 21, 2012 5:13 AM
     
      Has Code
    maziyar and thorsten,Thank you guys,it helped me. However when i change the hue the whole image's color is being changed. here is the sample that i have. 
     Int32 h = 252;
    Bitmap bt =(Bitmap) pictureBox1.Image;
                // create Hue modifier Filter
                AForge.Imaging.Filters.HueModifier filter =
                    new AForge.Imaging.Filters.HueModifier(h);
                // apply the filter
                System.Drawing.Bitmap newImage = filter.Apply(bt);
    
    
    
                 //create Saturation filter
                AForge.Imaging.Filters.SaturationCorrection filter1 =
                    new AForge.Imaging.Filters.SaturationCorrection(0.2);
                // apply the filter
                System.Drawing.Bitmap newImage1 = filter1.Apply(newImage);
              
    
                pictureBox2.Image = newImage1;
    Can you guys provide me some sample.

    Thanks and Regards, Prashanth MP.

  • Monday, May 21, 2012 7:01 AM
     
     Answered

    Hi,

    as I mentioned, you probably need to change a Hue-Range (for instance from 330 to 30 for the main red part).

    You could test if you get what you need with this here: It's a test-program, so there possibly could be some runtime errors... (and UI-Text is in german)

    https://skydrive.live.com/redir.aspx?cid=d5e5bd21dbf5e4e9&resid=D5E5BD21DBF5E4E9!1851&parid=D5E5BD21DBF5E4E9!1450&authkey=!

    Regards,

      Thorsten


  • Tuesday, May 22, 2012 11:25 AM
     
     

    Hi,I got your sample and its awesome,Thanks for the sample. it was really helpful. But can you tell me if there is anyway that i can get the hue range of the colors in the image dynamically?


    Thanks and Regards, Prashanth MP.

  • Tuesday, May 22, 2012 11:34 AM
     
     

    But can you tell me if there is anyway that i can get the hue range of the colors in the image dynamically?

    Hi,

    of what colors? Of all colors present in the image? Or maybe in a rectagular part of the image?

    If so you could loop over all pixels and get the hue-values for each and examine the results for max min etc.

    Regards,

      Thorsten

  • Wednesday, May 23, 2012 5:01 AM
     
     
    Hi,for example The image of this car, i have to get the min and max hue range in this pic.

    Thanks and Regards, Prashanth MP.

  • Wednesday, May 23, 2012 12:35 PM
     
     Answered Has Code

    Hi,

    as I mentioned you can loop over the pixels (here with GetPixel, in a realworld scenario I'd use a faster way like unsafe code) and get the hue for each pixel:

    [If you want to get the hue for a color-range you'll need to implement some logic for that. The same is for getting the hue for a spatial range.] [For instance you could exclude very dark pixels and very bright that have a hue of 0. In your picture, you probably want to exclude the hue around 40 too (the turn-signal-lamp (indicator))]

        public partial class Form1 : Form
        {
            //usually added by designer
            private System.Windows.Forms.PictureBox pictureBox1;
            private System.Windows.Forms.Button button1;
            private System.Windows.Forms.DataGridView dataGridView1;
            private System.Windows.Forms.Button button2;
            private System.Windows.Forms.OpenFileDialog openFileDialog1;
    
            private Dictionary<double, long> _hue = new Dictionary<double, long>();
            public Form1()
            {
                InitializeComponent();
                //usually done by designer
                Init();
            }
    
            private void button1_Click(object sender, EventArgs e)
            {
                if (this.openFileDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK)
                {
                    Bitmap bmp = null;
                    using (Image img = Image.FromFile(this.openFileDialog1.FileName))
                        bmp = new Bitmap(img);
    
                    Image iOld = this.pictureBox1.Image;
                    this.pictureBox1.Image = bmp;
    
                    if (iOld != null)
                        iOld.Dispose();
                }
            }
    
            private void button2_Click(object sender, EventArgs e)
            {
                if (this.pictureBox1.Image != null)
                {
                    Bitmap bmp = (Bitmap)this.pictureBox1.Image;
                    for (int y = 0; y < bmp.Height; y++)
                    {
                        for (int x = 0; x < bmp.Width; x++)
                        {
                            double h = bmp.GetPixel(x, y).GetHue();
                            //precision 1/10
                            double hf = Math.Round(h, 1);
    
                            if (!_hue.ContainsKey(hf))
                                _hue.Add(hf, 1);
                            else
                                _hue[hf]++;
                        }
                    }
    
                    //sort
                    _hue = _hue.OrderBy(a => a.Key).ToDictionary(b => b.Key, b => b.Value);
    
                    //get a datasource
                    DataTable dt = CreateTableFromDictionary(_hue);
                    this.dataGridView1.DataSource = dt.DefaultView;
    
                    this.Text = _hue.Min(a => a.Key).ToString() + "; " + _hue.Max(b => b.Key).ToString(); 
                }
            }
    
            private DataTable CreateTableFromDictionary(Dictionary<double, long> hue)
            {
                DataTable dt = new DataTable();
                dt.Columns.Add("Hue");
                dt.Columns.Add("Amount");
    
                for (int i = 0; i < hue.Count; i++)
                {
                    DataRow dr = dt.NewRow();
                    dr[0] = hue.Keys.ElementAt(i);
                    dr[1] = hue.Values.ElementAt(i);
                    dt.Rows.Add(dr);
                }
    
                return dt;
            }
    
            private void Form1_FormClosing(object sender, FormClosingEventArgs e)
            {
                if (this.pictureBox1.Image != null)
                    this.pictureBox1.Image.Dispose();
            }
    
            private void Init()
            {
                this.pictureBox1 = new System.Windows.Forms.PictureBox();
                this.button1 = new System.Windows.Forms.Button();
                this.dataGridView1 = new System.Windows.Forms.DataGridView();
                this.button2 = new System.Windows.Forms.Button();
                this.openFileDialog1 = new System.Windows.Forms.OpenFileDialog();
                // 
                // pictureBox1
                // 
                this.pictureBox1.Location = new System.Drawing.Point(325, 12);
                this.pictureBox1.Name = "pictureBox1";
                this.pictureBox1.Size = new System.Drawing.Size(449, 394);
                this.pictureBox1.TabIndex = 0;
                this.pictureBox1.TabStop = false;
                // 
                // button1
                // 
                this.button1.Location = new System.Drawing.Point(699, 422);
                this.button1.Name = "button1";
                this.button1.Size = new System.Drawing.Size(75, 23);
                this.button1.TabIndex = 1;
                this.button1.Text = "Open";
                this.button1.UseVisualStyleBackColor = true;
                this.button1.Click += new System.EventHandler(this.button1_Click);
                // 
                // dataGridView1
                // 
                this.dataGridView1.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
                this.dataGridView1.Location = new System.Drawing.Point(12, 12);
                this.dataGridView1.Name = "dataGridView1";
                this.dataGridView1.Size = new System.Drawing.Size(297, 394);
                this.dataGridView1.TabIndex = 2;
                // 
                // button2
                // 
                this.button2.Location = new System.Drawing.Point(234, 422);
                this.button2.Name = "button2";
                this.button2.Size = new System.Drawing.Size(75, 23);
                this.button2.TabIndex = 3;
                this.button2.Text = "Scan";
                this.button2.UseVisualStyleBackColor = true;
                this.button2.Click += new System.EventHandler(this.button2_Click);
                // 
                // openFileDialog1
                // 
                this.openFileDialog1.FileName = "Pic1";
                this.openFileDialog1.Filter = "Images (*.bmp;*.jpg;*.png)|*.bmp;*.jpg;*.png";
                // 
                // Form1
                // 
                this.ClientSize = new System.Drawing.Size(798, 457);
                this.Controls.Add(this.button2);
                this.Controls.Add(this.dataGridView1);
                this.Controls.Add(this.button1);
                this.Controls.Add(this.pictureBox1);
                this.Name = "Form1";
                this.Text = "Form1";
                this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.Form1_FormClosing);
            }
        }

    Regards,

      Thorsten



  • Friday, June 01, 2012 5:09 AM
     
      Has Code

    Thanks for the code.I really appreciate your help.But I'm a little confused,After scanning an image for  the " hue Value- 0" the "Amount" produced is huge like 167811. do i have to convert it or something? And One more thing is i tried to convert your HSLbereich project from vb to c#, i have few errors in them. one of the errors are in this block.

     Private Sub textBox2_Validating(ByVal sender As System.Object, ByVal e As System.ComponentModel.CancelEventArgs) Handles textBox2.Validating, textBox3.Validating
            Dim tb As TextBox = CType(sender, TextBox)
            If Not IsNumeric(tb.Text) Then
                tb.Text = "0"
            End If
            If Int32.Parse(tb.Text) > 100 Then
                tb.Text = "100"
            End If
            If Int32.Parse(tb.Text) < -100 Then
                tb.Text = "-100"
            End If
        End Sub

    After converting to c# i got this

    private void textBox2_Validating(System.Object sender, System.ComponentModel.CancelEventArgs e)
    {
    	TextBox tb = (TextBox)sender;
    	if (!Information.IsNumeric(tb.Text)) {
    		tb.Text = "0";
    	}
    	if (Int32.Parse(tb.Text) > 100) {
    		tb.Text = "100";
    	}
    	if (Int32.Parse(tb.Text) < -100) {
    		tb.Text = "-100";
    	}
    }
    
    Here i was gettin an error "The name 'information' does not exist,so i added Microsoft.Visualbasic to the reference and it got fixed, The project has got compiled but i'm getting a lot of messages in the form frmHSLBereich. The type System.Windows.Forms.Form has no property named ComboBox1,I'm getting this message for all the controls on the form. Here is the link to the converted project if you want to have a look. Download(SkyDrive).


    Thanks and Regards, Prashanth MP.

  • Friday, June 01, 2012 5:36 AM
     
     Answered Has Code

    Hi, here's how I use it in c#:

            private bool IsNumeric(string t)
            {
                char[] cf = t.ToCharArray();
    
                foreach (char c in cf)
                    if (char.IsNumber(c) == false)
                        return false;
    
                return true;
            }
    
            private void textBox2_Validating(System.Object sender, System.ComponentModel.CancelEventArgs e)
            {
                TextBox tb = (TextBox)sender;
                if (!IsNumeric(tb.Text))
                {
                    tb.Text = "0";
                }
                if (Int32.Parse(tb.Text) > 100)
                {
                    tb.Text = "100";
                }
                if (Int32.Parse(tb.Text) < -100)
                {
                    tb.Text = "-100";
                }
            }

    Regards,

      Thorsten

    • Marked As Answer by JohnnyWalker9 Friday, June 01, 2012 9:01 AM
    •  
  • Friday, June 01, 2012 5:47 AM
     
     Answered

    Hi,

    the amount is the amount of pixels that have that hue... that might be a big number, especially for hue-values of 0.

    Here's a quick c#-version of the HSL-Range:

    https://skydrive.live.com/redir.aspx?cid=d5e5bd21dbf5e4e9&resid=D5E5BD21DBF5E4E9!2330&parid=D5E5BD21DBF5E4E9!1901&authkey=!

    Regards,

      Thorsten

    • Marked As Answer by JohnnyWalker9 Friday, June 01, 2012 9:01 AM
    •  
  • Friday, June 01, 2012 9:01 AM
     
     
    Thanks a lot for your help.

    Thanks and Regards, Prashanth MP.

  • Monday, June 04, 2012 12:51 PM
     
     
    Hi,Can your code be converted to wpf? I'm trying to convert this to wpf,lot of methods and directives are missing in wpf,is adding reference to the win forms dlls in wpf a good idea?

    Thanks and Regards, Prashanth MP.

  • Monday, June 04, 2012 1:15 PM
     
     

    Hi,

    if I needed a WPF version, I would rewrite the whole thing. Basically you would have to create the UI in WPF and change the algorithms to work with a WriteableBitmap (so the basic algorithm could stay the same, you only would need to replace the BitmapData stuff with the BackBuffer of the WriteableBitmap...)

    This could be done in a short period of time, I think. The most problematic thing will be the UI, IMHO.

    I havent got the time to do this, but I will be around here quite often, if you have questions.

    Regards,

      Thorsten

  • Tuesday, June 05, 2012 4:18 AM
     
     
    Actually i don't need a UI,I just need to fetch an image and pass the hue value to change the color. When the image has no background then the hue range 0-360 works for almost all the images so i'm thinkin of restricting the user from uploading images which has some background colors.(that is show a warning and ask him/her to select an image with white background only).

    Thanks and Regards, Prashanth MP.


  • Tuesday, June 05, 2012 4:47 AM
     
     

    Ok, so you have two options.

    Either port the processing-methods to WPF, or convert the System.Controls.Image or whatever you use in WPF to a System.Drawing.Bitmap temporarily and back after processing.

    Btw: The last post was completely written from my view... There are a lot of people thinking that doing UI in WPF is easaier than in WinForms... So the statement that the UI may be the bigger problem is just my point of view because I have generally more problems in creating an UI than writing the working stuff... (I'm not patient enough - so the WinForms-Design-Model is best for me:

    <hobbyist's view>Just drag some Controls to the form, doubleclick them and implement the handlers and you have a running application. Everything else, like making the UI nicer can be done later - or not at all (just like the documentation :-) </hobbyist's view>))

    Regards,

      Thorsten






  • Tuesday, June 05, 2012 9:15 AM
     
      Has Code

    I'm not able to find an alternative for BitmapData, for Bitmap i'm using 

    WriteableBitmap _bitmap = new WriteableBitmap(100, 100, 96, 96, PixelFormats.Pbgra32, null);

    Is this right? And What are the alternatives for GraphicsUnit and RectangleF? 

    You have a method LockBitmap(), Instead of that can i use, WritableBitmap.Lock() and UnLock()?


    Thanks and Regards, Prashanth MP.

  • Tuesday, June 05, 2012 10:24 AM
     
      Has Code

    the pattern is somewhat like: [Compare that to the gdi+ BitmapData-versions of the algorithms]

            private unsafe BitmapSource DoSomething(BitmapSource bIn)
            {
                WriteableBitmap bSrcF = null;
    
                try
                {
                    bSrcF = new WriteableBitmap(bIn);
    
                    bSrcF.Lock();
    
                    IntPtr Scan0 = bSrcF.BackBuffer;
    
                    int strideSrc = bSrcF.BackBufferStride;
    
                    int nWidth = bIn.PixelWidth;
                    int nHeight = bIn.PixelHeight;
    
                    for (int y = 0; y < nHeight; y++)
                    {
                        //I get the pointer here (inside the outer loop, 
                        //because of posssible parallelizing of that loop, so the pointer is threadlocal)
                        byte* p = (byte*)Scan0;
                        //maybe get the pointer at the current row-adress here
    
                        for (int x = 0; x < nWidth; x++)
                        {
                            //do whatever is needed
    
                            //maybe increment the pointer by 4 (one pixel) here or compute the complete address offset from scan0
                        }
                    }
    
                    bSrcF.Unlock();
                }
                catch
                {
                    try
                    {
                        bSrcF.Unlock();
                    }
                    catch
                    {
    
                    }
                }
    
                return bSrcF;
            }

    Regards,

      Thorsten




  • Wednesday, June 06, 2012 9:23 AM
     
      Has Code
    How can i paint the image with the updated hue? here you are using LinearGradient brush,and using that brush to fill the rectangle,But Can you tell me why you are using the rectangle?And also g.fillRectangle(). Can you explain what you are doing here?
    LinearGradientBrush b = new LinearGradientBrush(new RectangleF(0, 0, bmp.Width, (float)bmp.Height / 6F), color1, color2, LinearGradientMode.Vertical);
    g.FillRectangle(b, new Rectangle(0, 0, bmp.Width, Convert.ToInt32((double)bmp.Height / 6.0)));



    Thanks and Regards, Prashanth MP.


  • Wednesday, June 06, 2012 9:48 AM
     
     

    Hi,

    I'm filling rectangles with gradients that build up the image thats displayed. I use more than one GradientBrush but you could also use one with a ColorBlend that takes all the Gradientstops...

    (I use FilleRectangle to fill a Rectangle in the picture... Just comment out one or two of these lines and see the difference...)

    I maybe can translate the thing to WPF in a couple of days (if I then have more time to do this). I will begin with the processing methods.

    Regards,

      Thorsten

  • Wednesday, June 06, 2012 9:55 AM
     
     

    Ok i thought so,i have almost converted it,except this painting part,trying to find a soultion for that,hopefully i will. Will share you the code once its done. 


    Thanks and Regards, Prashanth MP.

  • Wednesday, June 06, 2012 10:00 AM
     
     
    Like you said i tried commenting the whole LinearGradient brush and g.fillRectangle() ,you are using that to draw the color range image on the label. the color still changes when the slider is moved.

    Thanks and Regards, Prashanth MP.

  • Wednesday, June 06, 2012 10:18 AM
     
     
    Like you said i tried commenting the whole LinearGradient brush and g.fillRectangle() ,you are using that to draw the color range image on the label. the color still changes when the slider is moved.

    Thanks and Regards, Prashanth MP.

    Which color changes? The color in the working image should change then (by the TrackBars ValueChanged event), the colors in the color-blend-image then will not change.
  • Wednesday, June 06, 2012 10:39 AM
     
     
    The color in the image that we upload changes by the trackbar value changed event. 

    Thanks and Regards, Prashanth MP.

  • Wednesday, June 13, 2012 6:45 AM
     
     

    Hi,

    I'm filling rectangles with gradients that build up the image thats displayed. I use more than one GradientBrush but you could also use one with a ColorBlend that takes all the Gradientstops...

    (I use FilleRectangle to fill a Rectangle in the picture... Just comment out one or two of these lines and see the difference...)

    I maybe can translate the thing to WPF in a couple of days (if I then have more time to do this). I will begin with the processing methods.

    Regards,

      Thorsten

    Hi Thorsten, i tried to do something like this to convert your app to WPF,but the pixel hue doesn't change, here is the link to the project

    Download, can u have a look and tell me what could be done?


    Thanks and Regards, Prashanth MP.


  • Wednesday, June 13, 2012 5:26 PM
     
      Has Code

    Hi,

    you use the wrong dimensions in the loops in Bereich. First get the dimensions by calling the lockbitmap-method then use the returned dimensions: (the head of the function: [I use a normal loop to debug and switch to parallel when all works])

                LockBitmap();  
    
                int w = (int)dimensions.Width;
                int h = (int)dimensions.Height;
    
                for (int y = 0; y < h; y++)
                //Parallel.For(0, h, y =>
                {
                    for (int x = 0; x < w; x++)
                    {

    The second thing is, you need to pass valid values for saturation and luminance too (and set the addLuminance and AddStauration correctly). And as far as I see you modify the pixel-array but you do not copy it back to the bitmap in your UpdatePixels-Method.

    Regards,

      Thorsten


  • Wednesday, June 13, 2012 5:59 PM
     
      Has Code

    ... so add in your Bereich-method two times the update of the array

                                  PixelData nPixel = HSLtoRGB(p.Hue, p.Saturation, p.Luminance);
    
                                    pPixel.Red = nPixel.red;
                                    pPixel.Green = nPixel.green;
                                    pPixel.Blue = nPixel.blue;
                                    //update the array
                                    pixelColors[x, y] = pPixel;

    and pass correct values for luminance etc.
  • Wednesday, June 13, 2012 6:04 PM
     
      Has Code

    Ok, here's the updated methods that gives a working example:

    in PixelColor:

            public static BitmapSource UpdatePixels(this BitmapSource source, PixelColor[,] pixels, int stride, int offset)
            {
                WriteableBitmap w = new WriteableBitmap(source);
                var height = source.PixelHeight;
                var width = source.PixelWidth;
                var pixelBytes = new byte[height * width * 4];
                //source.CopyPixels(pixelBytes, stride, 0);
                int y0 = offset / width;
                int x0 = offset - width * y0;
                for (int y = 0; y < height; y++)
                {
                    for (int x = 0; x < width; x++)
                    {
                        PixelColor pixel = pixels[x + x0, y + y0];
                        pixelBytes[(y * width + x) * 4 + 0] = pixel.Blue;
                        pixelBytes[(y * width + x) * 4 + 1] = pixel.Green;
                        pixelBytes[(y * width + x) * 4 + 2] = pixel.Red;
                        pixelBytes[(y * width + x) * 4 + 3] = pixel.Alpha;
                    }
                }
    
                w.WritePixels(new System.Windows.Int32Rect(0, 0, width, height), pixelBytes, width * 4, 0);
    
                return w;
            }

    in fipbmp;

            public void Bereich(float HueMin, float HueMax, float Hue, float Saturation, float Luminance, bool AddSaturation, bool AddLuminance,
                float SaturationMin, float SaturationMax, float LuminanceMin, float LuminanceMax)
            {
                LockBitmap();  
    
                int w = (int)dimensions.Width;
                int h = (int)dimensions.Height;
    
                //for (int y = 0; y < h; y++)
                Parallel.For(0, h, y =>
                {
                    for (int x = 0; x < w; x++)
                    {
                        PixelColor pPixel = (PixelColor)pixelColors[x, y];//.GetValue(new int[] { x, y });
                        byte red = pPixel.Red;
    
                        byte green = pPixel.Green;
    
                        byte blue = pPixel.Blue;
    
                        HSLData p = RGBtoHSL(red, green, blue);
    
                        HSLRange fSat = new HSLRange();
                        if (SaturationMin < SaturationMax)
                        {
                            fSat.Range1.Min = SaturationMin;
                            fSat.Range1.Max = SaturationMax;
                            fSat.Range2.Min = 0;
                            fSat.Range2.Max = 0;
                        }
                        else
                        {
                            fSat.Range1.Min = SaturationMax;
                            fSat.Range1.Max = 1.0F;
                            fSat.Range2.Min = 0;
                            fSat.Range2.Max = SaturationMin;
                        }
    
                        HSLRange fLum = new HSLRange();
                        if (LuminanceMin < LuminanceMax)
                        {
                            fLum.Range1.Min = LuminanceMin;
                            fLum.Range1.Max = LuminanceMax;
                            fLum.Range2.Min = 0;
                            fLum.Range2.Max = 0;
                        }
                        else
                        {
                            fLum.Range1.Min = LuminanceMax;
                            fLum.Range1.Max = 1.0F;
                            fLum.Range2.Min = 0;
                            fLum.Range2.Max = LuminanceMin;
                        }
    
                        if (HueMin < HueMax)
                        {
                            if ((p.Hue >= HueMin) && (p.Hue <= HueMax))
                            {
                                if (fSat.Contains(p.Saturation) && fLum.Contains(p.Luminance))
                                {
                                    float val_hue = p.Hue + Hue;
    
                                    if (val_hue > 360)
                                    {
                                        val_hue -= 360;
                                    }
    
                                    p.Hue = val_hue;
    
                                    if (AddSaturation)
                                        p.Saturation += Saturation;
                                    else
                                        p.Saturation = Saturation;
    
                                    if (p.Saturation > 1.0F)
                                        p.Saturation = 1.0F;
    
                                    if (p.Saturation < 0.0F)
                                        p.Saturation = 0.0F;
    
                                    if (AddLuminance)
                                        p.Luminance += Luminance;
                                    else
                                        p.Luminance = Luminance;
    
                                    if (p.Luminance > 1.0F)
                                        p.Luminance = 1.0F;
    
                                    if (p.Luminance < 0.0F)
                                        p.Luminance = 0.0F;
    
                                    PixelData nPixel = HSLtoRGB(p.Hue, p.Saturation, p.Luminance);
    
                                    pPixel.Red = nPixel.red;
                                    pPixel.Green = nPixel.green;
                                    pPixel.Blue = nPixel.blue;
    
                                    pixelColors[x, y] = pPixel;
                                }
                            }
    
                        }
                        else
                        {
                            if ((p.Hue >= HueMin) || (p.Hue <= HueMax))
                            {
                                if (fSat.Contains(p.Saturation) && fLum.Contains(p.Luminance))
                                {
                                    float val_hue = p.Hue + Hue;
    
                                    if (val_hue > 360)
                                    {
                                        val_hue -= 360;
                                    }
    
                                    p.Hue = val_hue;
    
                                    if (AddSaturation)
                                        p.Saturation += Saturation;
                                    else
                                        p.Saturation = Saturation;
    
                                    if (p.Saturation > 1.0F)
                                        p.Saturation = 1.0F;
    
                                    if (p.Saturation < 0.0F)
                                        p.Saturation = 0.0F;
    
                                    if (AddLuminance)
                                        p.Luminance += Luminance;
                                    else
                                        p.Luminance = Luminance;
    
                                    if (p.Luminance > 1.0F)
                                        p.Luminance = 1.0F;
    
                                    if (p.Luminance < 0.0F)
                                        p.Luminance = 0.0F;
    
                                    PixelData nPixel = HSLtoRGB(p.Hue, p.Saturation, p.Luminance);
    
                                    pPixel.Red = nPixel.red;
                                    pPixel.Green = nPixel.green;
                                    pPixel.Blue = nPixel.blue;
    
                                    pixelColors[x, y] = pPixel;
                                }
                            }
                        }                 
                    }
                });
                UnlockBitmap();
            }

    in MainWindow.xaml.cs:

            public void HSLpic(BitmapSource img)
            {
                //string path = pictureBox1.Source.ToString();
                //BitmapImage img = new BitmapImage(new Uri(path));
    
    
                //WriteableBitmap bmp = new WriteableBitmap(img);
                bmpout = img;
                int height = bmpout.PixelHeight;
                int width = bmpout.PixelWidth;
                int nStride = (bmpout.PixelWidth * bmpout.Format.BitsPerPixel + 7) / 8; ;
                BitmapFunctions f = new BitmapFunctions(bmpout);
                //BitmapSourceHelper.CopyPixels(bmpout, PixelColor.GetPixels(bmpout), nStride, 0);
    
                f.Bereich(float.Parse("0.0"), float.Parse("360.0"), this._hue, this._saturation, this._luminance, true, true,
                     float.Parse("0.0"), float.Parse("1.0"), float.Parse("0.0"), float.Parse("1.0"));
    
                BitmapSource b = bmpout.UpdatePixels(f.PixelColors, nStride, 0);
    
                f.Dispose();
                //bmpOut.dispose()
    
                //Window w = new Window();
                //w.Background = new ImageBrush(bmpout);
                //w.Show();
                pictureBox1.Source = b;
    
    
                Color color1 = default(Color);
                Color color2 = default(Color);
                Color color3 = default(Color);
                Color color4 = default(Color);
                Color color5 = default(Color);
                Color color7 = default(Color);
                Color color71 = default(Color);
                if (float.Parse(this.txtHueMax.Text) > float.Parse(this.txtHueMin.Text))
                {
    
                    PixelData p1 = BitmapFunctions.HSLtoRGB(Double.Parse(this.txtHueMin.Text), 0.5f, 0.5f);
                    color1 = Color.FromArgb(p1.alpha, p1.red, p1.green, p1.blue);
    
                    PixelData p2 = BitmapFunctions.HSLtoRGB((Double.Parse(this.txtHueMin.Text) + Double.Parse(this.txtHueMax.Text) - Double.Parse(this.txtHueMin.Text)) / 6.0, 0.5f, 0.5f);
                    color2 = Color.FromArgb(p2.alpha, p2.red, p2.green, p2.blue);
    
                    PixelData p3 = BitmapFunctions.HSLtoRGB((Double.Parse(this.txtHueMin.Text) + Double.Parse(this.txtHueMax.Text) - Double.Parse(this.txtHueMin.Text)) / 3.0, 0.5f, 0.5f);
                    color3 = Color.FromArgb(p3.alpha, p3.red, p3.green, p3.blue);
    
                    PixelData p4 = BitmapFunctions.HSLtoRGB((Double.Parse(this.txtHueMin.Text) + Double.Parse(this.txtHueMax.Text) - Double.Parse(this.txtHueMin.Text)) / 2.0, 0.5f, 0.5f);
                    color4 = Color.FromArgb(p4.alpha, p4.red, p4.green, p4.blue);
    
                    PixelData p5 = BitmapFunctions.HSLtoRGB((Double.Parse(this.txtHueMin.Text) + Double.Parse(this.txtHueMax.Text) - Double.Parse(this.txtHueMin.Text)) * (2.0 / 3.0), 0.5f, 0.5f);
                    color5 = Color.FromArgb(p5.alpha, p5.red, p5.green, p5.blue);
    
                    PixelData p7 = BitmapFunctions.HSLtoRGB((Double.Parse(this.txtHueMin.Text) + Double.Parse(this.txtHueMax.Text) - Double.Parse(this.txtHueMin.Text)) * (5.0 / 6.0), 0.5f, 0.5f);
                    color7 = Color.FromArgb(p7.alpha, p7.red, p7.green, p7.blue);
    
                    PixelData p71 = BitmapFunctions.HSLtoRGB(Double.Parse(this.txtHueMax.Text), 0.5f, 0.5f);
                    color71 = Color.FromArgb(p71.alpha, p71.red, p71.green, p71.blue);
                }
                else
                {
                    PixelData p1 = BitmapFunctions.HSLtoRGB(Double.Parse(this.txtHueMin.Text), 0.5f, 0.5f);
                    color1 = Color.FromArgb(p1.alpha, p1.red, p1.green, p1.blue);
    
                    double z = Double.Parse(this.txtHueMin.Text) + (double)(360f - Double.Parse(this.txtHueMin.Text) + Double.Parse(this.txtHueMax.Text)) / 6.0;
                    if (z > 360f)
                    {
                        z -= 360f;
                    }
                    PixelData p2 = BitmapFunctions.HSLtoRGB(z, 0.5f, 0.5f);
                    color2 = Color.FromArgb(p2.alpha, p2.red, p2.green, p2.blue);
    
                    z = Double.Parse(this.txtHueMin.Text) + (double)(360f - Double.Parse(this.txtHueMin.Text) + Double.Parse(this.txtHueMax.Text)) / 3.0;
                    if (z > 360f)
                    {
                        z -= 360f;
                    }
                    PixelData p3 = BitmapFunctions.HSLtoRGB(z, 0.5f, 0.5f);
                    color3 = Color.FromArgb(p3.alpha, p3.red, p3.green, p3.blue);
    
                    z = Double.Parse(this.txtHueMin.Text) + (double)(360f - Double.Parse(this.txtHueMin.Text) + Double.Parse(this.txtHueMax.Text)) / 2.0;
                    if (z > 360f)
                    {
                        z -= 360f;
                    }
                    PixelData p4 = BitmapFunctions.HSLtoRGB(z, 0.5f, 0.5f);
                    color4 = Color.FromArgb(p4.alpha, p4.red, p4.green, p4.blue);
    
                    z = Double.Parse(this.txtHueMin.Text) + (double)(360f - Double.Parse(this.txtHueMin.Text) + Double.Parse(this.txtHueMax.Text)) * (2.0 / 3.0);
                    if (z > 360f)
                    {
                        z -= 360f;
                    }
                    PixelData p5 = BitmapFunctions.HSLtoRGB(z, 0.5f, 0.5f);
                    color5 = Color.FromArgb(p5.alpha, p5.red, p5.green, p5.blue);
    
                    z = Double.Parse(this.txtHueMin.Text) + (double)(360f - Double.Parse(this.txtHueMin.Text) + Double.Parse(this.txtHueMax.Text)) * (5.0 / 6.0);
                    if (z > 360f)
                    {
                        z -= 360f;
                    }
                    PixelData p7 = BitmapFunctions.HSLtoRGB(z, 0.5f, 0.5f);
                    color7 = Color.FromArgb(p7.alpha, p7.red, p7.green, p7.blue);
    
                    PixelData p71 = BitmapFunctions.HSLtoRGB(Double.Parse(this.txtHueMax.Text), 0.5f, 0.5f);
                    color71 = Color.FromArgb(p71.alpha, p71.red, p71.green, p71.blue);
                }
                this._vals = new HSLValues()
                {
                    HueMin = float.Parse(this.txtHueMin.Text),
                    HueMax = float.Parse(this.txtHueMax.Text),
                    Hue = this._hue,
                    SaturationMin = float.Parse(this.txtSatMin.Text),
                    SaturationMax = float.Parse(this.txtSatMax.Text),
                    Saturation = this._saturation,
                    LuminanceMin = float.Parse(this.txtLumMin.Text),
                    LuminanceMax = float.Parse(this.txtLumMax.Text),
                    Luminance = this._luminance,
                    AddSaturation = true, //(this.ComboBox1.SelectedIndex == 0 ? true : false),
                    AddLuminance = false //(this.ComboBox2.SelectedIndex == 0 ? true : false)
                };
    
    
            }

    Regards,

      Thorsten


  • Thursday, June 14, 2012 4:57 AM
     
     
    Thank u so much. Let me try that.

    Thanks and Regards, Prashanth MP.

  • Thursday, June 14, 2012 11:37 AM
     
      Has Code

    ... so add in your Bereich-method two times the update of the array

                                  PixelData nPixel = HSLtoRGB(p.Hue, p.Saturation, p.Luminance);
    
                                    pPixel.Red = nPixel.red;
                                    pPixel.Green = nPixel.green;
                                    pPixel.Blue = nPixel.blue;
                                    //update the array
                                    pixelColors[x, y] = pPixel;

    and pass correct values for luminance etc.
    Hi Throsten,It works perfectly,Thanks a lot. but there are some small issues, since i'm using  textboxes and not the NumberUpdown controls,when i change the text in the texbox i am getting the "formatException was unhandled {"Input string was not in a correct format."}" Exception, and the saturation and luminosity slider's values are too hight. Here is the Updated code so that u can have a look. Download

    Thanks and Regards, Prashanth MP.

  • Thursday, June 14, 2012 1:02 PM
     
      Has Code
    Hi Throsten,It works perfectly,Thanks a lot. but there are some small issues, since i'm using  textboxes and not the NumberUpdown controls,when i change the text in the texbox i am getting the "formatException was unhandled {"Input string was not in a correct format."}" Exception, and the saturation and luminosity slider's values are too hight. Here is the Updated code so that u can have a look. Download

    Ok, I think getting the correct slider-values you can do yourself by comparing the maxima and minima of your sliders with the ones of my WinForms-project. (check the multipliers too). For the textboxes as numeric-textboxes in WPf you can:

    From http://stackoverflow.com/questions/1268552/how-do-i-get-a-textbox-to-only-accept-numeric-input-in-wpf:

    <quote according to the above link>

    add the event-handlers in xaml for: PreviewTextInput="textBox1_PreviewTextInput" DataObject.Pasting="textBox1_Pasting" and add in code the handlers:

           private void textBox1_PreviewTextInput(object sender, TextCompositionEventArgs e)
            {
                e.Handled = !IsTextAllowed(e.Text);
            }
    
            private static bool IsTextAllowed(string text)
            {
                Regex regex = new Regex("[^0-9.-]+");
                return !regex.IsMatch(text);
            }
    
            private void textBox1_Pasting(object sender, DataObjectPastingEventArgs e)
            {
                if (e.DataObject.GetDataPresent(typeof(String)))
                {
                    String text = (String)e.DataObject.GetData(typeof(String));
                    if (!IsTextAllowed(text))
                    {
                        e.CancelCommand();
                    }
                }
                else
                {
                    e.CancelCommand();
                }
    
            }

    </quote>

    Regards,

      Thorsten

  • Wednesday, June 20, 2012 5:12 AM
     
      Has Code

    Hi Throsten,It works perfectly,Thanks a lot. but there are some small issues, since i'm using  textboxes and not the NumberUpdown controls,when i change the text in the texbox i am getting the "formatException was unhandled {"Input string was not in a correct format."}" Exception, and the saturation and luminosity slider's values are too hight. Here is the Updated code so that u can have a look. Download


    Ok, I think getting the correct slider-values you can do yourself by comparing the maxima and minima of your sliders with the ones of my WinForms-project. (check the multipliers too). For the textboxes as numeric-textboxes in WPf you can:

    From http://stackoverflow.com/questions/1268552/how-do-i-get-a-textbox-to-only-accept-numeric-input-in-wpf:

    <quote according to the above link>

    add the event-handlers in xaml for: PreviewTextInput="textBox1_PreviewTextInput" DataObject.Pasting="textBox1_Pasting" and add in code the handlers:

           private void textBox1_PreviewTextInput(object sender, TextCompositionEventArgs e)
            {
                e.Handled = !IsTextAllowed(e.Text);
            }
    
            private static bool IsTextAllowed(string text)
            {
                Regex regex = new Regex("[^0-9.-]+");
                return !regex.IsMatch(text);
            }
    
            private void textBox1_Pasting(object sender, DataObjectPastingEventArgs e)
            {
                if (e.DataObject.GetDataPresent(typeof(String)))
                {
                    String text = (String)e.DataObject.GetData(typeof(String));
                    if (!IsTextAllowed(text))
                    {
                        e.CancelCommand();
                    }
                }
                else
                {
                    e.CancelCommand();
                }
    
            }

    </quote>

    Regards,

      Thorsten

    Hi i tried this but i'm still getting the exceptions when i clear the values in the textboxes. And i tried setting the same values for the sliders as in your winforms project,the saturation and lightness slider takes max value for the slider value =1.

    Thanks and Regards, Prashanth MP.

  • Wednesday, June 20, 2012 11:28 PM
     
     

    Hi i tried this but i'm still getting the exceptions when i clear the values in the textboxes. And i tried setting the same values for the sliders as in your winforms project,the saturation and lightness slider takes max value for the slider value =1.

    Thanks and Regards, Prashanth MP.

    Hi,

    so add a ValidationRule and an ErrorTemplate to the Style for the numeric Textbox and also check for being empty.

    2nd: You need to set the values, maxima, minima for the sliders and the multipliers for the slider values.

    I will have a look on this at weekend and repost after.

    Regards,

      Thorsten

  • Thursday, June 21, 2012 2:11 PM
     
      Has Code

    Hi i tried this but i'm still getting the exceptions when i clear the values in the textboxes.

    Hi, in the WinForms version you can change the IsNumerci-Method a bit to avoid that exception:

            private bool IsNumeric(string t)
            {
                if (!string.IsNullOrEmpty(t))
                {
                    char[] cf = t.ToCharArray();
    
                    foreach (char c in cf)
                        if (char.IsNumber(c) == false)
                            return false;
    
                    return true;
                }
                return false;
            }

    In WPF, you could use a numericTextBox like the one in here:

    https://skydrive.live.com/redir.aspx?cid=d5e5bd21dbf5e4e9&resid=D5E5BD21DBF5E4E9!2284&parid=D5E5BD21DBF5E4E9!2265&authkey=!

    Regards.

      Thorsten


  • Monday, June 25, 2012 6:48 AM
     
      Has Code

    Hi i tried this but i'm still getting the exceptions when i clear the values in the textboxes.

    Hi, in the WinForms version you can change the IsNumerci-Method a bit to avoid that exception:

            private bool IsNumeric(string t)
            {
                if (!string.IsNullOrEmpty(t))
                {
                    char[] cf = t.ToCharArray();
    
                    foreach (char c in cf)
                        if (char.IsNumber(c) == false)
                            return false;
    
                    return true;
                }
                return false;
            }

    In WPF, you could use a numericTextBox like the one in here:

    https://skydrive.live.com/redir.aspx?cid=d5e5bd21dbf5e4e9&resid=D5E5BD21DBF5E4E9!2284&parid=D5E5BD21DBF5E4E9!2265&authkey=!

    Regards.

      Thorsten


    Thanks thorsten,i'l try that. Can you help on this Please. http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/f4e83a65-d863-4b6c-9d66-17a0897a06ef . 

    Thanks and Regards, Prashanth MP.

  • Monday, October 01, 2012 6:59 AM
     
      Has Code

    Hi Throsten,It works perfectly,Thanks a lot. but there are some small issues, since i'm using  textboxes and not the NumberUpdown controls,when i change the text in the texbox i am getting the "formatException was unhandled {"Input string was not in a correct format."}" Exception, and the saturation and luminosity slider's values are too hight. Here is the Updated code so that u can have a look. Download


    Ok, I think getting the correct slider-values you can do yourself by comparing the maxima and minima of your sliders with the ones of my WinForms-project. (check the multipliers too). For the textboxes as numeric-textboxes in WPf you can:

    From http://stackoverflow.com/questions/1268552/how-do-i-get-a-textbox-to-only-accept-numeric-input-in-wpf:

    <quote according to the above link>

    add the event-handlers in xaml for: PreviewTextInput="textBox1_PreviewTextInput" DataObject.Pasting="textBox1_Pasting" and add in code the handlers:

           private void textBox1_PreviewTextInput(object sender, TextCompositionEventArgs e)
            {
                e.Handled = !IsTextAllowed(e.Text);
            }
    
            private static bool IsTextAllowed(string text)
            {
                Regex regex = new Regex("[^0-9.-]+");
                return !regex.IsMatch(text);
            }
    
            private void textBox1_Pasting(object sender, DataObjectPastingEventArgs e)
            {
                if (e.DataObject.GetDataPresent(typeof(String)))
                {
                    String text = (String)e.DataObject.GetData(typeof(String));
                    if (!IsTextAllowed(text))
                    {
                        e.CancelCommand();
                    }
                }
                else
                {
                    e.CancelCommand();
                }
    
            }

    </quote>

    Regards,

      Thorsten

    Hi thorsten, I'm unable to fix the SatMin and LumMin sliders. When i change the slider a bit the luminosity and saturation levels are going to the maximum and minimum values. can you please help?

    Thanks and Regards, Prashanth MP.

  • Tuesday, October 02, 2012 11:32 AM
     
     

    Hi,

    is the link to skydrive refferring to the actual/current version of the project?

    Regards,

      Thorsten


  • Wednesday, October 03, 2012 5:27 AM
     
     

    Hi,

    is the link to skydrive refferring to the actual/current version of the project?

    Regards,

      Thorsten


    Hi thorsten,This Download is the latest version. 

    Thanks and Regards, Prashanth MP.

  • Thursday, October 04, 2012 11:36 AM
     
      Has Code

    Hi,

    is the link to skydrive refferring to the actual/current version of the project?

    Regards,

      Thorsten


    And can u tell me how i can change the colors of multiple images instead of one?  After making multiselect true and selecting the images i loop through all the selected images. But how do i save the images without using the save file dialog? for saving a single image using save dialog after changing the color i'm using something like this on button click. But i want to select multiple images,change hue and save all of them to a folder,Can u help me on this? 

    Microsoft.Win32.SaveFileDialog dlg = new Microsoft.Win32.SaveFileDialog(); 

    dlg.FileName = "0" + dlg.FileNames.Count(); // Default file name
                    dlg.DefaultExt = ".jpg"; // Default file extension
                    dlg.Filter = "Picture File (*.jpg)|*.jpg|(*.bmp)|*.bmp"; // Filter files by extension

    // Show save file dialog box

    Nullable<bool> result = dlg.ShowDialog(); // Process to save file dialog box results if (result == true) { string name = dlg.SafeFileName; string path = dlg1.SelectedPath; //Save the color changed image var encoder = new JpegBitmapEncoder(); // Or PngBitmapEncoder, or whichever encoder you want encoder.Frames.Add(BitmapFrame.Create(ColorchangedImage)); using (var stream = dlg.OpenFile()) { encoder.Save(stream); } } } catch (Exception) { System.Windows.MessageBox.Show("Please save it to the appropriate file type."); }



    Thanks and Regards, Prashanth MP.

  • Thursday, October 04, 2012 1:01 PM
     
     

    Hi,

    I cannot load your project, since I use VS 2010 (also some toolkit-dlls are missing...). But from the code I can see that you do not divide the Saturation and Luminance values. The Range to pass to the HSL-Method is -1 to 1, so divide the actual values you use by 100F.

    Regards,

      Thorsten

  • Thursday, October 04, 2012 1:05 PM
     
      Has Code

    Hi,

    to change multiple Images, first get a List containing data to retrieve the images - if they are on the disc as files only store FileInfos for these pictures in the list. Then loop over the list and do the change for each image and re-save it to a folder. You can let the user select a folder with a WinForms FolderBrowserDialog and maybe also let the user select the filetype (jpg or bmp or png) to save the images.

    something like (if you want to bind the data of the sourcedir use an ObservableCoolection instead):

            List<System.IO.FileInfo> _files = null;
            System.IO.DirectoryInfo _dir;
            
            public MainWindow()
            {
                InitializeComponent();
                string sourceDir = ""; //add a source foilders path
                _dir = new System.IO.DirectoryInfo(sourceDir);
            }
    
            private void button1_Click(object sender, RoutedEventArgs e)
            {
                System.Windows.Forms.FolderBrowserDialog dlg = new System.Windows.Forms.FolderBrowserDialog();
                dlg.Description = "Select folder to save";
    
                if (dlg.ShowDialog() == System.Windows.Forms.DialogResult.OK)
                {   
                    if (_files == null)
                        _files = new List<System.IO.FileInfo>();
    
                    _files.Clear();
    
                    _files.AddRange(_dir.GetFiles("*.jpg").ToArray());
                    _files.AddRange(_dir.GetFiles("*.png").ToArray());
                    //...
    
                    foreach (System.IO.FileInfo fi in _files)
                    {
                        //load and processImaage
                        //Image img = ...
                        //...
    
                        //save image to new folder which is
                        //dlg.SelectedPath + DirectorySeparator + fi.Name;         
                    }
                }
            }

    Regards,

      Thorsten