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



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 &lt; 1.0f)
                width = 1.0f;
        Pen pen = new Pen(Color.FromArgb(255, 0, 255, 0), width);
        return pen;
}
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!