I have a Graphics object that I've drawn on the screen and I need to save it to a png or bmp file. Graphics doesn't seem to support that directly, but it must be possible somehow.
What are the steps?
Here is the code:
Bitmap bitmap = new Bitmap(Convert.ToInt32(1024), Convert.ToInt32(1024), System.Drawing.Imaging.PixelFormat.Format32bppArgb);
Graphics g = Graphics.FromImage(bitmap);
// Add drawing commands here
g.Clear(Color.Green);
bitmap.Save(#"C:\Users\johndoe\test.png", ImageFormat.Png);
If your Graphics is on a form, you can use this:
private void DrawImagePointF(PaintEventArgs e)
{
... Above code goes here ...
e.Graphics.DrawImage(bitmap, 0, 0);
}
In addition, to save on a web page, you could use this:
MemoryStream memoryStream = new MemoryStream();
bitmap.Save(memoryStream, ImageFormat.Png);
var pngData = memoryStream.ToArray();
<img src="data:image/png;base64,#(Convert.ToBase64String(pngData))"/>
Graphics objects are a GDI+ drawing surface. They must have an attached device context to draw on ie either a form or an image.
Copy it to a Bitmap and then call the bitmap's Save method.
Note that if you're literally drawing to the screen (by grabbing the screen's device context), then the only way to save what you just drew to the screen is to reverse the process by drawing from the screen to a Bitmap. This is possible, but it would obviously be a lot easier to just draw directly to a Bitmap (using the same code you use to draw to the screen).
Try this, works fine for me...
private void SaveControlImage(Control ctr)
{
try
{
var imagePath = #"C:\Image.png";
Image bmp = new Bitmap(ctr.Width, ctr.Height);
var gg = Graphics.FromImage(bmp);
var rect = ctr.RectangleToScreen(ctr.ClientRectangle);
gg.CopyFromScreen(rect.Location, Point.Empty, ctr.Size);
bmp.Save(imagePath);
Process.Start(imagePath);
}
catch (Exception)
{
//
}
}
Graphics graph = CreateGraphics();
Bitmap bmpPicture = new Bitmap("filename.bmp");
graph.DrawImage(bmpPicture, width, height);
You are likely drawing either to an image or on a control. If on image use
Image.Save("myfile.png",ImageFormat.Png)
If drawing on control use Control.DrawToBitmap() and then save the returned image as above.
Thanks for the correction - I wasn't aware you can draw directly to the screen.
Related
I need to create a drawing with a circle and text embeded to it .This drawing is outputted as Image file (Jpeg/Jpg/svg/Png) using c# GDI+ .
Since i dont want to display the UI directly on a form ,how do i get the graphic's object to start drawing.
Thanks in advance.
You can create a new Bitmap passing the size for the image:
using (Bitmap myBitmap = new Bitmap(100, 100)) {
using (Graphics g = Graphics.FromImage(myBitmap)) {
// do your drawing here
}
myBitmap.Save(#"C:\path\for\image.bmp");
}
Optionally you can set the ImageFormat for the image when saving
myBitmap.Save(#"C:\path\for\image.png", ImageFormat.Png);
You create a Bitmap, and get the graphics object from it to draw on:
Bitmap myBitmap = new Bitmap(#"C:\MyImg.bmp");
Graphics g = Graphics.FromImage(myBitmap);
Note that the Bitmap does not need to be created on disk, it can be created in memory too!
I'm drawing some graphics on a control area repeatedly, and each time I want to start fresh with a transparent background. So I use:
Graphics graph = control.CreateGraphics();
graph.Clear(Color.Transparent);
However, the graphics area seems to turn black instead of transparent. Any ideas?
I found an alternate way to achieve what I need. I create a new transparent bitmap with the control's dimensions, draw my stuff on it and then use it as a background image for the control:
Bitmap bitmap = new Bitmap(control.Width, control.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
bitmap.MakeTransparent();
Graphics graph = Graphics.FromImage(bitmap);
// draw stuff here ...
control.BackgroundImage = bitmap;
graph.Dispose();
This works perfectly.
because picturebox has not transparency layer. you could be use transfer bitmap.
try this.
tmp_bmp = new Bitmap(picturebox1.Width, picturebox1.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
Graphics Canvas = Graphics.FromImage(tmp_bmp);
picturebox1.Image = tmp_Type;
Type_Canvas.Clear(Color.Transparent);
This approach worked fine for me:
private void MyCustomControl_Paint(object sender, PaintEventArgs e)
{
// Clear background - also works when backcolor is transparent
InvokePaintBackground(this, e);
I have seen, that the drawing of two images is time consuming, so I want to reduce drawing these images as much as possible. I use pictureedit and have overriden the ondraw event.
Here I added the below part, but it ends up uin a black image. I do want to check, whether I need to draw at all. This check works. Then I draw the background and overlay it by another one and I want to store this as image and put it as background for my control.
If I do not redraw the background I just call:
g.Clear(Color.Transparent);
in my pictureEdit paint event.
Did I something wrong?
Best Regards,
Patrick
//Recalculate the background
if (redrawBackground)
{
g.FillRectangle(Brushes.White, 0, 0, backGroundImage.Width, backGroundImage.Height);
g.Clear(Color.White);
//this is drawn without aspect ration. The matrix is stored, since drawing images is expensive
GenerateTransformation(g, false);
g.DrawImageUnscaled(backGroundImage, new Rectangle(0, 0, backGroundImage.Width, backGroundImage.Height));
lastTransformation = g.Transform;
GenerateTransformation(g, true);
g.DrawImage(foreGroundImage, new Rectangle(0, 0, backGroundImage.Width, backGroundImage.Height));
lastTransformationAspect = g.Transform;
//Save bitmap as background
Bitmap bmp = new Bitmap(backGroundImage.Width, backGroundImage.Height, e.Graphics);
//Trick the background by a new image
pictureEdit.Image = bmp;
}
Your code (new Bitmap(backGroundImage.Width, backGroundImage.Height, e.Graphics);
) does not copy the image to the Bitmap; it only associates the Graphics object with the bitmap.
Try this:
Bitmap bmp = new Bitmap(width, height);
Graphics g = Graphics.FromImage(bmp);
g.DrawSomething(); // This draws to the bitmap
In a windows forms application, I have as input a Drawing.Bitmap and a DrawingImage. I need to overlay them and put there output in a Controls.Image. How can I do this?
It doesn't matter if you use Image object or Bitmap object, The Drawing.Image is abstract class and Drawing.Bitmap inherited from it. to
draw image over image, get the graphics object from the base image and then use Graphics.DrawImage which accept parameter of type Image.
So you have two images here, one should be printed "overlay" over the other image:
System.Drawing.Image primaryImage = Image.FromFile(#"Your file path");//or resource..
using (Graphics graphics = Graphics.FromImage(primaryImage))//get the underlying graphics object from the image.
{
using (Bitmap overlayImage = new Bitmap(primaryImage.Width, primaryImage.Hieght,
System.Drawing.Imaging.PixelFormat.Format32bppArgb)//or your overlay image from file or resource...
{
graphics.DrawImage(overlayImage, new Point(0, 0));//this will draw the overlay image over the base image at (0, 0) coordination.
}
}
Control.Image = primaryImage;
Not that if the overlay image doesn't have some transparent, and its size is equals or larger than the base image, it will overlap the other image completely, so you the overlay image must have some opacity.
I realize it has been awhile, but the answers here weren't quite working for me. A little tweaking, though made them work fine. For what it is worth, here is my final version.
SCENARIO:
background image is RGB 24
overlay image is ARGB 32 with alpha channel already set properly.
images created from a memory stream
PROBLEM:
Creating the overlay image from the memory stream assumed I meant: Format32bppRgb
But what is needed is Format32bppArgb since the transparency is already in place..
SOLUTION:
pictureBox1.Image = MergeImages( backgroundImage, overlayImage);
using System.Drawing;
using System.Drawing.Imaging;
// ...
private Image MergeImages(Image backgroundImage,
Image overlayImage)
{
Image theResult = backgroundImage;
if (null != overlayImage)
{
Image theOverlay = overlayImage;
if (PixelFormat.Format32bppArgb != overlayImage.PixelFormat)
{
theOverlay = new Bitmap(overlayImage.Width,
overlayImage.Height,
PixelFormat.Format32bppArgb);
using (Graphics graphics = Graphics.FromImage(theOverlay))
{
graphics.DrawImage(overlayImage,
new Rectangle(0, 0, theOverlay.Width, theOverlay.Height),
new Rectangle(0, 0, overlayImage.Width, overlayImage.Height),
GraphicsUnit.Pixel);
}
((Bitmap)theOverlay).MakeTransparent();
}
using (Graphics graphics = Graphics.FromImage(theResult))
{
graphics.DrawImage(theOverlay,
new Rectangle(0, 0, theResult.Width, theResult.Height),
new Rectangle(0, 0, theOverlay.Width, theOverlay.Height),
GraphicsUnit.Pixel);
}
}
return theResult;
}
I can't seem to get the text I've written to show up on my image Here's the code I'm using
//Creates a bitmap with the path to the current image
Bitmap LabelImage = new Bitmap(dtImages.Rows[intCurrentImage]["ImageURL"].ToString());
Graphics graphic = Graphics.FromImage(LabelImage);
graphic.DrawString("Hello", new Font("Tahoma",40), Brushes.Azure, new System.Drawing.Point(0,0));
//put Image that I just created and put the text on into an Infragistics UltraPicureBox
picImage.Image = LabelImage
You did not update your original image (LabelImage), so why should the text you added to the Graphics object show up?.
From MSDN, Graphics.FromImage:
Creates a new Graphics from the specified Image.
(emphasis mine)
After you have added the text, you need to save the changes:
graphic.Save();
Unrelated to your question, you should really put the creation of the Graphics object in a using statement, to ensure proper disposal:
using(Graphics graphic = Graphics.FromImage(LabelImage))
{
// use graphic here
}
I just tried this
Bitmap bitmap = new Bitmap("C:\\Untitled.png");
Graphics g = Graphics.FromImage(bitmap);
g.DrawString("Hello", new Font("Tahoma", 40), Brushes.Azure, new System.Drawing.Point(0, 0));
pictureBox1.Image = bitmap;
and it works fine for me. Just try to pick a contrasting brush.