0

I am trying to create a program that accepts an image, recursively goes through each pixel, normalizes the pixel and re-creates a NEW image that looks the same as the original, but has normalized pixels instead.

    public void parseJpeg(String jpegPath)
    {
        var normalizedRed = 0.0;
        var normalizedGreen = 0.0;
        var normalizedBlue = 0.0;
        Bitmap normalizedImage = null;

        var image = new Bitmap(jpegPath);
        normalizedImage = new Bitmap(image.Width, image.Height);
        for (int x = 0; x < image.Width; ++x)
        {
            for (int y = 0; y < image.Height; ++y)
            {
                Color color = image.GetPixel(x, y);

                double exponent = 2;
                double redDouble = Convert.ToDouble(color.R);
                double blueDouble = Convert.ToDouble(color.B);
                double greenDouble = Convert.ToDouble(color.G);

                double redResult = Math.Pow(redDouble, exponent);
                double blueResult = Math.Pow(blueDouble, exponent);
                double greenResult = Math.Pow(greenDouble, exponent);

                double totalResult = redResult + blueResult + greenResult;                    

                normalizedRed = Convert.ToDouble(color.R) / Math.Sqrt(totalResult);
                normalizedGreen = Convert.ToDouble(color.G) / Math.Sqrt(totalResult);
                normalizedBlue = Convert.ToDouble(color.B) / Math.Sqrt(totalResult);


                Color newCol = Color.FromArgb(Convert.ToInt32(normalizedRed), Convert.ToInt32(normalizedGreen), Convert.ToInt32(normalizedBlue));

                normalizedImage.SetPixel(x, y, newCol);                                                                
            }                
        }

        normalizedImage.Save("C:\\Users\\username\\Desktop\\test1.jpeg"); 
        resultsViewBox.AppendText("Process completed.\n");
    }

Using the above code produces all black pixels and I do not understand why. When it normalizes it sets RGB = 1. After normalization, how do I set pixels with the NEW normalized value?

When I perform the below code, I get a black and blue image in my preview, but when I open the file it's blank. This is better than what I was getting before, which was ALL black pixels. This only works on one image though. So I am not sure how much of a step forward it is.

public void parseJpeg(String jpegPath)
    {
        Bitmap normalizedImage = null;           

        var image = new Bitmap(jpegPath);
        normalizedImage = new Bitmap(image.Width, image.Height);
        for (int x = 0; x < image.Width; ++x)
        {
            for (int y = 0; y < image.Height; ++y)
            {
                Color color = image.GetPixel(x, y);

                float norm = (float)System.Math.Sqrt(color.R * color.R + color.B * color.B + color.G * color.G);

                Color newCol = Color.FromArgb(Convert.ToInt32(norm));

                normalizedImage.SetPixel(x, y, newCol);
            }
        }

        normalizedImage.Save("C:\\Users\\username\\Desktop\\test1.jpeg");
        resultsViewBox.AppendText("Process completed.\n");
    }

I found the code for what I was trying to do: http://www.lukehorvat.com/blog/normalizing-image-brightness-in-csharp/

    public void parseJpeg(String jpegPath)
    {
        var image = new Bitmap(jpegPath);
        normalizedImage = new Bitmap(image.Width, image.Height);


        for (int x = 0; x < image.Width; ++x)
        {
            for (int y = 0; y < image.Height; ++y)
            {
                float pixelBrightness = image.GetPixel(x, y).GetBrightness();
                minBrightness = Math.Min(minBrightness, pixelBrightness);
                maxBrightness = Math.Max(maxBrightness, pixelBrightness);
            }
        }

        for (int x = 0; x < image.Width; x++)
        {
            for (int y = 0; y < image.Height; y++)
            {
                Color pixelColor = image.GetPixel(x, y);
                float normalizedPixelBrightness = (pixelColor.GetBrightness() - minBrightness) / (maxBrightness - minBrightness);
                Color normalizedPixelColor = ColorConverter.ColorFromAhsb(pixelColor.A, pixelColor.GetHue(), pixelColor.GetSaturation(), normalizedPixelBrightness);

                normalizedImage.SetPixel(x, y, normalizedPixelColor);
            }
        }

        normalizedImage.Save("C:\\Users\\username\\Desktop\\test1.jpeg");
        resultsViewBox.AppendText("Process completed.\n");
    }
user2216791
  • 49
  • 2
  • 11
  • 1
    I haven't read through all of the code, but you don't need to do all of these gymnastics with string parsing. `GetPixel` returns a `Color` object, which has `R`, `G`, and `B` properties. – Adam Robinson Oct 23 '13 at 14:50
  • I don't know from where you got your code but the use of strings just messes with my brain cells. If you want pixel manipulation you should convert your data into an array of byte/int, depending on the resolution. Have a look at [this](http://stackoverflow.com/questions/3801275/how-to-convert-image-in-byte-array/) and [this](http://stackoverflow.com/questions/17352061/fastest-way-to-convert-image-to-byte-array). – Andrei V Oct 23 '13 at 14:51
  • Yes please use the ``R``, ``G``, ``B`` properties but more importantly do you really mean to rewrite the same image ``test1.jpeg`` (with only one pixel set) for every pixel in the original file? Think about it, if the input is 800x600, you will rewrite ``test1.jpeg`` 480,000 times. – acfrancis Oct 23 '13 at 14:55
  • @acfrancis: Let's hope he's not using an SSD! – Adam Robinson Oct 23 '13 at 15:18

3 Answers3

0

You are creating a new Bitmap and saving over the file for every pixel in your image. Move the

normalizedImage = new Bitmap(image.Width, image.Height);

line to before your loops, and the

normalizedImage.Save("C:\\Users\\username\\Desktop\\test1.jpeg");

line to after your loops.

Your normalization algorithm does not appear to be correct. Let's say your original color was red (255,0,0) Then your totalResult will be 65025, and your normalizedRed will be 255/sqrt(65025), which is 1, giving you a new normalized color of (1,0,0), which is essentially black.

Golden Dragon
  • 511
  • 5
  • 13
  • @user2216791 **Please do not edit other people's answers.** If you think the answers is not correct, please write as a comment under the answer. They'll fix it. – Win Oct 23 '13 at 15:05
  • 1
    @Win: Edits that don't change the substance of the answer are fine. This one only corrected the path to be what was written in the question above. That's why the edit button is there for everyone. – Adam Robinson Oct 23 '13 at 15:20
  • I know the normalization algorithm isn't right, but I do not know what to make it. Any suggestions? – user2216791 Oct 24 '13 at 14:20
0

Just as a note, your code will run a bit faster if you define all the doubles once outside the look and then assign them within the loop rather than defining and deleting each of the 8 doubles each iteration

Jonathan
  • 21
  • 3
0

Instead of messing with the colors you should use the brightness or luminosity factor to achieve normalization. Here is a link to the already answered question that can help you. you can convert each RGB pixel to HSL and minupulate L factor:

How do I normalize an image?

The code that you shared is actually a trim down version of HSL manipulation.

Community
  • 1
  • 1