Override a transparent picturebox in C# windows application form? - c#

I want to put in a background image, and above the background image I want to superimpose a transparent picturebox and tried to put the second picturebox like so:
pictureBox2.BackColor = Color.Transparent;
But it did not work. Basically, I would like to do this:

Transparency in Windows Forms isn't implemented as one would expect. Having a transparent background actually means that a control uses the background of its parent. This means that you need to make your overlay control a child of the original picture box:
PictureBox overlay = new PictureBox();
overlay.Dock = DockStyle.Fill;
overlay.BackColor = Color.FromArgb(128, Color.Blue);
pictureBox2.Controls.Add(overlay);
If you want the overlay picture box to contain a transparent image you need to actually change the image:
PictureBox overlay = new PictureBox();
overlay.Dock = DockStyle.Fill;
overlay.BackColor = Color.Transparent;
Bitmap transparentImage = new Bitmap(overlayImage.Width, overlayImage.Height);
using (Graphics graphics = Graphics.FromImage(transparentImage))
{
ColorMatrix matrix = new ColorMatrix();
matrix.Matrix33 = 0.5f;
ImageAttributes attributes = new ImageAttributes();
attributes.SetColorMatrix(matrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap);
graphics.DrawImage(overlayImage, new Rectangle(0, 0, transparentImage.Width, transparentImage.Height), 0, 0, overlayImage.Width, overlayImage.Height, GraphicsUnit.Pixel, attributes);
}
overlay.Image = transparentImage;
pictureBox2.Controls.Add(overlay);

Related

Image and text gets distorted/blurred on form background

I tried this code, it print distorted image and text on black background of a desktop.
I am using a Form with a transparent background. I want to print image on the background.
this.TransparencyKey = BackColor;
Bitmap original = null;
original = new Bitmap(imagePath);
Bitmap newImage = new Bitmap(width, height + rect.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
var newGrp = Graphics.FromImage(newImage);
newGrp.Clear(Color.Transparent);
newGrp.InterpolationMode = InterpolationMode.HighQualityBilinear;
newGrp.SmoothingMode = SmoothingMode.HighQuality;
newGrp.TextRenderingHint = TextRenderingHint.AntiAlias;
newGrp.CompositingQuality = CompositingQuality.HighQuality;
newGrp.DrawImage(original, 0, rect.Height, width, height);
newGrp.DrawString(text, font, color, textStartPosition, 0);
this.BackgroundImage = (Image)newImage;
Original is bitmap from image file and color of text is gray.The form is transparent. The new image is painted as background of form. Depend on background color of desktop(dynamic color), I want to print image on form, But my concerns about text is not clear.
I expect clear image and text on black background.

is it possible to achieve bevelled text and drop shadows using GDI in c#?

I'm looking to expand my 'simple' photography events system to add the ability to add custom text to images we've shot. I technically have this aspect working using the existing picturebox control to display the image and a text box in which text can be entered and this will be added to the image being displayed.
However, being a photographer, I'd like the text to look a little nicer and as such am looking to emulate what I can do in Photoshop, i.e. bevel/emboss, add inner glows and drop shadows to this text but I'm struggling to find any references to this.
I may be simply limited by the fact I'm using winforms and this may have been achievable via WPF, but WPF wasn't about when I stopped being a programmer for a profession and as such stuck to technology I knew... I'm also far too far down the line in the system to re-write it all in WPF, so if its a limitation I'll just look at adding in pre-determined overlays rather than custom text which I know I can achieve.
The code I have so far is as follows and any tips on how to expand this to perform the bevel/emboss, glows etc would be much appreciated.
public static Bitmap addTexttoImage(string imagename, string textnya)
{
float fontSize = 80;
string imagepath = imagename;
Image image = Image.FromStream(new MemoryStream(File.ReadAllBytes(imagepath)));
//read the image we pass
Bitmap bmp = (Bitmap)Image.FromFile(imagepath);
Graphics g = Graphics.FromImage(bmp);
//this will centre align our text at the bottom of the image
StringFormat sf = new StringFormat();
sf.Alignment = StringAlignment.Center;
sf.LineAlignment = StringAlignment.Far;
//define a font to use.
Font f = new Font("Impact", fontSize, FontStyle.Bold, GraphicsUnit.Pixel);
//pen for outline - set width parameter
Pen p = new Pen(ColorTranslator.FromHtml("#77090C"), 8);
p.LineJoin = LineJoin.Round; //prevent "spikes" at the path
//this makes the gradient repeat for each text line
Rectangle fr = new Rectangle(0, bmp.Height - f.Height, bmp.Width, f.Height);
LinearGradientBrush b = new LinearGradientBrush(fr,
ColorTranslator.FromHtml("#FF6493"),
ColorTranslator.FromHtml("#D00F14"),
90);
//this will be the rectangle used to draw and auto-wrap the text.
//basically = image size
Rectangle r = new Rectangle(0, 0, bmp.Width, bmp.Height);
GraphicsPath gp = new GraphicsPath();
gp.AddString(textnya, f.FontFamily, (int)FontStyle.Bold, fontSize, r, sf);
g.SmoothingMode = SmoothingMode.AntiAlias;
g.PixelOffsetMode = PixelOffsetMode.HighQuality;
g.DrawPath(p, gp);
g.FillPath(b, gp);
//cleanup
gp.Dispose();
b.Dispose();
b.Dispose();
f.Dispose();
sf.Dispose();
g.Dispose();
return bmp;
}

Apply the opacity of a LinearGradientBrush to an image in winforms

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.
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.
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 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;

Graphics.DrawString doesn't work

I want to draw a text over a PictureBox in a foreach loop. This is the code that is responsible for rendering(GG is a PictureBox that is currently in the loop)
if (GG != null)
{
((PictureBox)GG).Image = (Image)obj;
using (Graphics g = ((PictureBox)GG).CreateGraphics()) {
g.DrawString(i["amount"].ToString(), kryptonRichTextBox1.Font,
new SolidBrush(Color.Gold), new Point(16, 18));
}
}
But sadly, the text is not rendered. If I comment out the
//((PictureBox)GG).Image = (Image)obj;
line, it does work! I have no idea how to get it to work.
I wanted to use the TextRenderer, but I don't know how to get an IDeviceContext of a control(and all examples I see on the internet use PaintEventArgs.Graphics in Paint event).
Also, if this is relevant, the GG PictureBox is a child of another picturebox, and has a transparent background.
I tried to refresh the box after invalidating, the working code:
if (GG != null)
{
((PictureBox)GG).Image = (Image)obj;
((PictureBox)GG).Invalidate();
((PictureBox)GG).Refresh();
using (Graphics g = ((PictureBox)GG).CreateGraphics()) {
g.DrawString(i["amount"].ToString(), kryptonRichTextBox1.Font,
new SolidBrush(Color.Gold), new Point(16, 18));
}
}
You modified the image content but the PictureBox is completely unaware of that. You didn't reassign its Image property. You will need to tell it that it needs to redraw the image as displayed on the screen. Add this line of code:
GG.Invalidate();
Just draw on a Bitmap and show it in the PictureBox:
// A new bitmap with the same size as the PictureBox
var bitmap = new Bitmap(pictureBox.Width, pictureBox.Height);
//Get the graphics objectm which we can use to draw
var graphics = Graphics.FromImage(bitmap);
//Draw stuff
graphics.DrawString(i["amount"].ToString(), kryptonRichTextBox1.Font,
new SolidBrush(Color.Gold), new Point(16, 18));
//Show the bitmap with graphics image in the PictureBox
pictureBox.Image = bitmap;
Image digidashboard = new Bitmap(Properties.Resources.digidashboard);
//using (Graphics g = ((PictureBox)pictureBoxDashboard).CreateGraphics())
//{
// g.DrawString("80.00", this.Font, new SolidBrush(Color.Red), 3, 6);
// pictureBoxUnlock.Image = digidashboard;
// pictureBoxDashboard.Invalidate();
//}
Graphics g = Graphics.FromImage(digidashboard);
g.DrawString("80.00", this.Font, new SolidBrush(Color.Red), 3, 6);
pictureBoxDashboard.Image = digidashboard;
According to StevenHouben's answer, I paste my C# version. It works fine. Thanks #StevenHouben.

Save non-transparent image from a PictureBox with transparent images

I have a PictureBox with lots of transparent png's drawn into...
Now I'd like to save the content of this PictureBox to a file, but without the transparency.
How can I do this?
I have already tried to remove transparency from the Image like this, but it didn't work, I still got a transparent image after the save.
...
removeTransparency(pictureBox.Image).Save(saveFileDialog.FileName);
private Bitmap removeTransparency(Image transparentImage)
{
Bitmap src = new Bitmap(transparentImage);
Bitmap newImage = new Bitmap(src.Size.Width, src.Size.Height);
Graphics g = Graphics.FromImage(newImage);
g.DrawRectangle(new Pen(new SolidBrush(Color.White)), 0, 0, newImage.Width, newImage.Height);
g.DrawImage(src, 0, 0);
return newImage;
}
You may cycle through all pixel (please not using GetPixel/SetPixel) to change the color or you may create another bitmap with the same size, create a graphics context from the image, clear the image with your favorite background color and then draw your image on it (so transparent pixels simply will be replaced by the background color).
Example
Did you do something like this?
public static Bitmap Repaint(Bitmap source, Color backgroundColor)
{
Bitmap result = new Bitmap(source.Width, source.Height, PixelFormat.Format32bppArgb);
using (Graphics g = Graphics.FromImage(result))
{
g.Clear(backgroundColor);
g.DrawImage(source, new Rectangle(0, 0, source.Width, source.Height));
}
return result;
}

Categories

Resources