Vivian Lobo
Vivian Lobo

Reputation: 623

Blur the selected part of the image

I am trying to create an application in C# (WinForms), something similar to this iOS Question

I managed to get part of it working, I can blur an image using this algorithm

Also I am able to draw a selection rectangle, I do not know if I am going wrong with the blurring or passing the rectangle. I have attached the file as shown below. Blurring Effect

As seen, the blurring is outside the selection box.

I have pasted the code below:

// Start Rectangle
        private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
        {
            // Determine the initial rectangle coordinates...
            RectStartPoint = e.Location;
            Invalidate();
        }

        private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
        {
            if (e.Button != MouseButtons.Left)
                return;
            Point tempEndPoint = e.Location;
            Rect.Location = new Point(
                Math.Min(RectStartPoint.X, tempEndPoint.X),
                Math.Min(RectStartPoint.Y, tempEndPoint.Y));
            Rect.Size = new Size(
                Math.Abs(RectStartPoint.X - tempEndPoint.X),
                Math.Abs(RectStartPoint.Y - tempEndPoint.Y));
            pictureBox1.Invalidate();
        }



        // Draw Area
        private void pictureBox1_Paint(object sender, PaintEventArgs e)
        {
            // Draw the rectangle...
            if (pictureBox1.Image != null)
            {
                if (Rect != null && Rect.Width > 0 && Rect.Height > 0)
                {                        
                    e.Graphics.DrawRectangle(selectionPen, Rect);
                }
            }
        }


        private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
        {
            //Right now I am using right click as a call to blur
            if (e.Button == MouseButtons.Right)
            {
                if (Rect.Contains(e.Location))
                {                        
                    pictureBox1.Image = Blur(pictureBox1.Image, Rect, 5);
                    pictureBox1.Refresh();
                }
            }
        }

        private void blurPageToolStripMenuItem_Click(object sender, EventArgs e)
        {            
            FullRect = new Rectangle(0, 0, pictureBox1.Image.Width, pictureBox1.Image.Height);
            pictureBox1.Image = Blur(pictureBox1.Image, FullRect, 5);
        }

        private System.Drawing.Image Blur(System.Drawing.Image image, Rectangle rectangle, Int32 blurSize)
        {
           Bitmap blurred = new Bitmap(image);   //image.Width, image.Height);
            using (Graphics graphics = Graphics.FromImage(blurred))
            {
                // look at every pixel in the blur rectangle
                for (Int32 xx = rectangle.Left; xx < rectangle.Right; xx += blurSize)
                {
                    for (Int32 yy = rectangle.Top; yy < rectangle.Bottom; yy += blurSize)
                    {
                        Int32 avgR = 0, avgG = 0, avgB = 0;
                        Int32 blurPixelCount = 0;
                        Rectangle currentRect = new Rectangle(xx, yy, blurSize, blurSize);

                        // average the color of the red, green and blue for each pixel in the
                        // blur size while making sure you don't go outside the image bounds
                        for (Int32 x = currentRect.Left; (x < currentRect.Right && x < image.Width); x++)
                        {
                            for (Int32 y = currentRect.Top; (y < currentRect.Bottom && y < image.Height); y++)
                            {
                                Color pixel = blurred.GetPixel(x, y);

                                avgR += pixel.R;
                                avgG += pixel.G;
                                avgB += pixel.B;

                                blurPixelCount++;
                            }
                        }

                        avgR = avgR / blurPixelCount;
                        avgG = avgG / blurPixelCount;
                        avgB = avgB / blurPixelCount;

                        // now that we know the average for the blur size, set each pixel to that color
                        graphics.FillRectangle(new SolidBrush(Color.FromArgb(avgR, avgG, avgB)), currentRect);                            
                    }
                }
                graphics.Flush();
            }
            return blurred;
        }       

Another problem I am facing is, when the form is loaded initially, it starts in minimised mode, now if I use the selection (red rectangle), and then if I maximise the application the selected part of the picture is different.

Thank you for the help/suggestion in advance. If any links to a tool similar is around, please do share as I might have missed it. Thanks

Upvotes: 3

Views: 5167

Answers (1)

endofzero
endofzero

Reputation: 1818

You may be experiencing this issue because your image is stretched in the PictureBox. You can verify this is the issue by setting the SizeMode property of the PictureBox to Normal.

This is the sequence of events:

  1. The selection rectangle is drawn.
  2. The point/rectangle for the selection is determined.
  3. The unstretched image is retrieved from the PictureBox, and is passed to the Blur method, with the calculated rectangle.
  4. The unstretched image is blurred over the area described by the rectangle.
  5. The unstretched image, now blurred, is assigned to the PictureBox.
  6. The PictureBox stretches the image out to according to its SizeMode setting.

This makes the image appear to have blurred in a different location than what you selected.

The code you have looks at the selection rectangle, and uses those points to operate on the original image, not the stretched version of the image. If you want to blur the stretched image, you will need to get the stretched image first, then apply the blur to the rectangle selected on that image. Here is an example:

    private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
    {
        //Right now I am using right click as a call to blur
        if (e.Button == MouseButtons.Right)
        {
            if (Rect.Contains(e.Location))
            {
                pictureBox1.Image = Blur(getPictureBoxImage(), Rect, 5);
                pictureBox1.Refresh();
            }
        }
    }

    private Bitmap getPictureBoxImage()
    {
        Bitmap bmp = new Bitmap(pictureBox1.Width, pictureBox1.Height);
        using (Graphics g = Graphics.FromImage(bmp))
        {
            g.DrawImage(pictureBox1.Image,
                new Rectangle(0, 0, bmp.Width, bmp.Height));
        }
        return bmp;
    }

Code for retrieving the stretched image is derived from this answer: https://stackoverflow.com/a/8702405/935052

Upvotes: 1

Related Questions