2
\$\begingroup\$

I'm drawing rectangular ROI region by darkening the area outside of it as in this image:

enter image description here

But image.MakeTransparent takes too much time. What is the best way to increase drawing speed?

void DrawRoi(Bitmap Image, RectangleF rect)
{
        Rectangle roi = new Rectangle();

        roi.X = (int)((float)Image.Width * rect.X);
        roi.Y = (int)((float)Image.Height * rect.Y);
        roi.Width = (int)((float)Image.Width * rect.Width);
        roi.Height = (int)((float)Image.Height * rect.Height);

        Stopwatch timer = new Stopwatch();
        timer.Start();
        // graphics manipulation takes about 240ms on 1080p image
        using (Bitmap roiMaskImage = CreateRoiMaskImage(ImageWithRoi.Width, ImageWithRoi.Height, roi))
        {
                using (Graphics g = Graphics.FromImage(ImageWithRoi))
                {                                
                        g.DrawImage(Image, 0, 0);
                        g.DrawImage(roiMaskImage, 0, 0);
                        Pen borderPen = CreateRoiBorderPen(ImageWithRoi);
                        g.DrawRectangle(borderPen, roi);
                }
        }
        Debug.WriteLine("roi graphics: {0}ms", timer.ElapsedMilliseconds);
        this.imagePictureBox.Image = ImageWithRoi;
}

Bitmap CreateRoiMaskImage(int width, int height, Rectangle roi)
{
        Bitmap image = new Bitmap(width, height, PixelFormat.Format32bppArgb);
        using (Graphics g = Graphics.FromImage(image))
        {
                SolidBrush dimBrush = new SolidBrush(Color.FromArgb(64, 0, 0, 0));
                g.FillRectangle(dimBrush, 0, 0, width, height);
                SolidBrush roiBrush = new SolidBrush(Color.Red);
                g.FillRectangle(roiBrush, roi);
                image.MakeTransparent(Color.Red);
                return image;
        }                
}

Pen CreateRoiBorderPen(Bitmap image)
{
        float width = ((float)(image.Width + image.Height) * 2.5f) / (float)(640 + 480);
        if (width < 1.0f)
                width = 1.0f;
        Pen pen = new Pen(Color.FromArgb(255, 0, 255, 0), width);
        return pen;
}
\$\endgroup\$
2
\$\begingroup\$

Well, you could try literally darkening the outside of the image by 25%, not by creating a 25%-opaque black area but just by calculating the pixel color values of the same color 25% darker, without the need to create a new 32bbp bitmap.

This might help: Formula to determine brightness of RGB color (StackOverflow). Based on this, let's say you choose Y = 0.2126 R + 0.7152 G + 0.0722 B as your luminance formula and 0.75 and the new brightness of the outside part of the image -- each pixel should be changed to:

Y = 0.75 * (0.2126 * R + 0.7152 * G + 0.0722 * B)
(R, G, B)' = (R - Y * 0.2126, G - Y * 0.7152, B - Y * 0.0722)

(Twice I realized that the formula I put here was quite wrong... this time I'm more confident, but it might be that this makes no sense when painted, I haven't tested it.)

This would require iterating through each individual pixel outside the central square, so not sure if it will be faster in the end... But as will all things performance, only measurements will tell!

\$\endgroup\$
  • \$\begingroup\$ thank you very much for intresting suggestion, I will try the approach \$\endgroup\$ – Chesnokov Yuriy Sep 5 '11 at 11:44
  • \$\begingroup\$ Could this be done with a ColorMatrix? \$\endgroup\$ – JoeGeeky Dec 17 '11 at 22:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.