Below is my code for changing my panel information into a Bitmap.
The Bitmap is first generated by my panel information and then saved to as a image file.
I confirmed that the width, height, and bounds represent the right information given by my panel.
I am currently unsure of why my result bmp/jpeg file is different from the image on my panel.
//bitmap saving function
Bitmap bmp = new Bitmap(panel1.ClientSize.Width, panel1.ClientSize.Height);
Debug.WriteLine("bounds: " + panel1.ClientRectangle);
this.panel1.DrawToBitmap(bmp, panel1.ClientRectangle);
bmp.Save(#"C:\Documents and Settings\Flaw\Desktop\Test.bmp", ImageFormat.Bmp);
//drawing function
System.Drawing.Graphics graphicsObj;
graphicsObj = this.panel1.CreateGraphics();
Pen myPen = new Pen(System.Drawing.Color.Black, 5);
graphicsObj.Clear(Color.White);
//graphicsObj.DrawLine(myPen, 50, 50, 100, 100);
if (bCircle)
{
graphicsObj.DrawEllipse(myPen, x, y, 100, 100);
}
else if (bSquare)
{
graphicsObj.DrawRectangle(myPen, x, y, 100, 100);
}
The result I get by saving the bitmap.
The image that is on my panel1 (cropped from my Window Form)
Your Bounds property is the relationship the panel has to the parent container, so this won't always work:
this.panel1.DrawToBitmap(bmp, panel1.Bounds);
Try this instead:
this.panel1.DrawToBitmap(bmp, panel1.ClientRectangle);
Your bitmap size should also use the ClientSize properties, since the panel's Width and Height properties include any border sizes:
Bitmap bmp = new Bitmap(panel1.ClientSize.Width, panel1.ClientSize.Height);
Per your update, CreateGraphics is a temporary canvas and won't be a part of the panel, so there was nothing to save. Use the panel's paint event instead:
private void panel1_Paint(object sender, PaintEventArgs e) {
using (Pen myPen = new Pen(Color.Black, 5)) {
e.Graphics.Clear(Color.White);
if (bCircle) {
e.Graphics.DrawEllipse(myPen, x, y, 100, 100);
} else if (bSquare) {
e.Graphics.DrawRectangle(myPen, x, y, 100, 100);
}
}
}
To make an update, you just need to invalidate the control:
panel1.Invalidate();
Related
Is it possible to create another Graphics form an existing Graphics with a different coordinate system? For example, let's say that the black rectangle is the ClipRectangle of the Graphics object I got in OnPaint(). If I only want to draw inside the blue rectangle, I would have to constantly calculate the offset. That is, to draw at the logical point (0,0) in the blue rectangle, I would have to add the x and y offsets. That makes drawing code complicated.
Is there a way to create some sort of virtual Graphics using the Graphics above but with a different coordinate system? Something like below
//not actual code
var virtualG = Graphics.FromExistingGraphics(e.Graphics, 200/*x1*/, 200/*y1*/, 1000/*x2*/, 600/*y2*/);
//Doing the same thing as e.Graphics.DrawLine(pen, 200, 200, 400, 400)
virtualG.DrawLine(pen, 0, 0, 200, 200);
//Draws nothing, NOT the same as e.Graphics.DrawLine(pen, 1100, 200, 1200, 400)
//, because its outside of the virtualG's bounds.
virtualG.DrawLine(pen, 900, 0, 1000, 200);
I thought about creating a new Graphics using bitmap, draw there and then copy the bitmap to the specified location of the Graphics from OnPaint, but that could be slow.
If you don't want any scaling, and simply want to move the origin to (200, 200), then use TranslateTransform as suggested previously. If you want to clip any drawings outside that rectangle, then use SetClip.
Here's an example, showing the same set of lines drawn before and after translating and clipping. The black lines are before, while the blue line is after (the second blue line is clipped and therefore not visible). The red rectangle shows the clipping region:
Code:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public class Line
{
public Point ptA;
public Point ptB;
public void Draw(Graphics G, Color color)
{
using (Pen P = new Pen(color))
{
G.DrawLine(P, ptA, ptB);
}
}
}
private List<Line> Lines = new List<Line>();
private void Form1_Load(object sender, EventArgs e)
{
Lines.Add(new Line() { ptA = new Point(0,0), ptB = new Point(200, 200)});
Lines.Add(new Line() { ptA = new Point(900, 0), ptB = new Point(1000, 200) });
}
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
Graphics G = e.Graphics;
G.Clear(Color.DarkGray);
foreach(Line line in Lines)
{
line.Draw(G, Color.Black);
}
Rectangle rc = new Rectangle(new Point(200, 200), new Size(800, 400));
G.DrawRectangle(Pens.Red, rc);
G.SetClip(rc);
G.TranslateTransform(rc.Left, rc.Top); // origin is now at (200, 200)
foreach (Line line in Lines)
{
line.Draw(G, Color.Blue);
}
}
}
I'm trying to draw a part of a .png image but the code i found is not working. this is my code
//define canvas
canvas = pb.CreateGraphics();
sPicture = new Bitmap(pb.Width, pb.Height);
sCanvas = Graphics.FromImage(sPicture);
// Create a Bitmap object from a file.
Image image = Image.FromFile(#"");
// Clone a portion of the Bitmap object.
Rectangle cloneRect = new Rectangle(0, 0, 11, 6);
System.Drawing.Imaging.PixelFormat format =
image.PixelFormat;
Image cloneBitmap = image.Clone(cloneRect, format); //Error: No overload for method 'Clone' takes2 arguments
// Draw the cloned portion of the Bitmap object.
canvas.DrawImage(cloneBitmap, 0, 0);
This is for a sprite sheet and thanks.
You don't need to use Clone(), you can do this directly with Graphics.DrawImage(). It looks like you are trying to do this in WinForms. If, so handle OnPaint for the control you want to draw on. In the example below I'm drawing directly on the form.
private void Form1_Paint(object sender, PaintEventArgs e)
{
Graphics graphics = e.Graphics;
int width = 60;
int height = 60;
// Create a Bitmap object from a file.
Image sourceImage = Image.FromFile(#"C:\Users\Mike\Downloads\logo.png");
// Draw a portion of the source image.
Rectangle sourceRect = new Rectangle(0, 0, width, height);
graphics.DrawImage(sourceImage, 0, 0, sourceRect, GraphicsUnit.Pixel);
}
If you want to do this without WinForms, there is the extra step of creating the target Graphics instance.
int width = 60;
int height = 60;
// Create a Bitmap object from a file.
Image sourceImage = Image.FromFile(#"C:\Users\Mike\Downloads\logo.png");
// Create a drawing target
Bitmap bitmap = new Bitmap(width, height, sourceImage.PixelFormat);
Graphics graphics = Graphics.FromImage(bitmap);
// Draw a portion of the source image.
Rectangle sourceRect = new Rectangle(0, 0, width, height);
graphics.DrawImage(sourceImage, 0, 0, sourceRect, GraphicsUnit.Pixel);
// Save
bitmap.Save(#"C:\Users\Mike\Downloads\out.png");
I am trying to make a bitmap appear in my form, but it won't work.
my code:
private void button2_Click(object sender, EventArgs e)
{
Graphics g = this.CreateGraphics();
Pen pen = new Pen(Color.Black);
Bitmap bitmap = new Bitmap(1000, 1000);
Graphics gfx = Graphics.FromImage(bitmap);
gfx.Clear(Color.Red);
for (int i = 0; i < 5; i++)
{
gfx.DrawRectangle(pen, i + 50, 50, 50, 50);
}
}
All your code is doing is drawing to a bitmap, in memory. You don't have any code to actually display that bitmap anywhere.
You could modify the code to paint the bitmap onto the form, but as nvoigt suggested in comments, a better solution would be to use a PictureBox control. When you create your bitmap, you can assign that bitmap to the picture box's Image property:
Bitmap bitmap = new Bitmap(1000, 1000);
// render bitmap
pictureBox1.Image = bitmap;
If you absolutely must draw on the form itself, you can override the form's OnPaint method, and use the graphics object's DrawImage() method to render your bitmap there.
I would like to add to picture black box. How to do it?
using (var image = Image.FromFile(imagePath))
{
using (var newImage = ScaleImage(image, 300, 400))
{
int width = newImage.Size.Width;
int height = newImage.Size.Height;
Graphics DrawingSurface = Graphics.FromImage(newImage);
//graphics.DrawRectangle(); ????
newImage.Save(imagePathDuzy);
}
}
Use one of the FillRectangle methods on the Graphics type: http://msdn.microsoft.com/en-us/library/yysstebh.aspx
Probably something like this:
DrawingSurface.FillRectangle(new SolidBrush(Colors.Black), new Rectangle(0, height - 100, width, height));
This shold draw a black rectangle with 100px height at the bottom of the image.
I am currently starting to build a simple version of the Game of Life following the same logic. I am using a picture box. In order to know where an area is clicked, it is advised to use 2 x 2 squares. How can I create 2 x 2 squares and give it a grid like style inside the pictureBox?
CODE
private void Form1_Load(object sender, EventArgs e)
{
this.pictureBox1.Image = this.Draw(this.pictureBox1.Width, this.pictureBox1.Height);
}
public Bitmap Draw(int width, int height)
{
var bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb);
var graphics = Graphics.FromImage(bitmap);
graphics.SmoothingMode = SmoothingMode.AntiAlias;
graphics.FillRectangle(new SolidBrush(Color.Tomato), 60, 60, 10, 10);
return bitmap;
}
EXAMPLE of outlook