1

I want to apply the opacity of a linear gradient to an image, but all I have been able to get is the gradient painted on top of the image.

enter image description here

Following this stackoverflow post, I created a user control that inherits from PictureBox and I overrode the OnPaint method

    protected override void OnPaint(PaintEventArgs e)
    {
        base.OnPaint(e);
        LinearGradientBrush linearGradientBrush = new LinearGradientBrush(
            this.ClientRectangle,
            Color.FromArgb(255, Color.White),
            Color.FromArgb(0, Color.White),
            0f);
        e.Graphics.FillRectangle(linearGradientBrush, this.ClientRectangle);
    }

However, that simply paints the linear gradient on top of the image.

How do I apply the opacity of the linear gradient to the image?

I find examples in XAML (), but not for winforms.

Community
  • 1
  • 1
Davide Andrea
  • 1,357
  • 2
  • 15
  • 39

1 Answers1

3

It is not necessary to use a user control and override the OnPaint event. Just create a graphics object from a blank image and do your image manipulation and assign the image to a PicturePox.

First draw the linearGradientBrush to the background and afterwards draw the image over it. Always take care about the sequence of your image operations.

FileInfo inputImageFile = new FileInfo(@"C:\Temp\TheSimpsons.png");
Bitmap inputImage = (Bitmap)Bitmap.FromFile(inputImageFile.FullName);

// create blank bitmap with same size
Bitmap combinedImage = new Bitmap(inputImage.Width, inputImage.Height);

// create graphics object on new blank bitmap
Graphics g = Graphics.FromImage(combinedImage);

// also use the same size for the gradient brush and for the FillRectangle function
LinearGradientBrush linearGradientBrush = new LinearGradientBrush(
    new Rectangle(0,0,combinedImage.Width, combinedImage.Height),
    Color.FromArgb(255, Color.White), //Color.White,
    Color.FromArgb(0, Color.White), // Color.Transparent,
    0f);
g.FillRectangle(linearGradientBrush, 0, 0, combinedImage.Width, combinedImage.Height);

g.DrawImage(inputImage, 0,0);

previewPictureBox.Image = combinedImage;

result

Result with black as the forms background color and the example image with transparency.

EDIT: I may have misunderstood the intention, and either haven't found an easy way like in WPF, but it is not this much difficult.

FileInfo inputImageFile = new FileInfo(@"C:\Temp\TheSimpsons.png");
Bitmap inputImage = (Bitmap)Bitmap.FromFile(inputImageFile.FullName);

// create blank bitmap
Bitmap adjImage = new Bitmap(inputImage.Width, inputImage.Height);

// create graphics object on new blank bitmap
Graphics g = Graphics.FromImage(adjImage);

LinearGradientBrush linearGradientBrush = new LinearGradientBrush(
    new Rectangle(0, 0, adjImage.Width, adjImage.Height),
    Color.White,
    Color.Transparent,
    0f);

Rectangle rect = new Rectangle(0, 0, adjImage.Width, adjImage.Height);
g.FillRectangle(linearGradientBrush, rect);

int x;
int y;
for (x = 0; x < adjImage.Width; ++x)
{
    for (y = 0; y < adjImage.Height; ++y)
    {
        Color inputPixelColor = inputImage.GetPixel(x, y);
        Color adjPixelColor = adjImage.GetPixel(x, y);
        Color newColor = Color.FromArgb(adjPixelColor.A, inputPixelColor.R, inputPixelColor.G, inputPixelColor.B);
        adjImage.SetPixel(x, y, newColor);
    }
}
previewPictureBox.Image = adjImage;

enter image description here

MarkusEgle
  • 2,795
  • 4
  • 41
  • 61
  • Wow! I thought that, since no one answered this question when I first asked it, no one ever would; I am pleasantly surprised that you found this question so long afterward, and answered it: thank you! So, I see what you're saying: do it one pixel at a time. OK, I'll try that. Thanks, – Davide Andrea Nov 22 '16 at 17:35