By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
435,453 Members | 3,225 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 435,453 IT Pros & Developers. It's quick & easy.

Saving and loading bmp using graphics object

P: n/a
Vin
Hi,

I am using the following code to draw whatever the user draws using
x,y.

// draws lines directly on a winform.
CreateGraphics().DrawLine(APen, x, y, OldX, OldY);

Now how do I save the drawing on to a bmp file on my harddisk? C# code
in this regard would be very helpful. I tried all forums but invain.

I tried with Graphics object and then

objBitmap=new Bitmap(400, 200, objGraphics);
objBitmap.Save(@"c:\test.bmp", ImageFormat.Bmp);

which didn't work, leaving me with a blank test.bmp.

Also help me load a bmp from hard disk to this form? C# code please.

Anyone out there who could help me?

Cheers
Vin
Nov 16 '05 #1
Share this Question
Share on Google+
5 Replies


P: n/a
Hi Vin,

The simplest way might be to create a Bitmap the size of your window and
either draw on both Bitmap and graphics or draw on the bitmap and use
DrawImage to draw the bitmap on the graphics.
This way you can also load the bitmap from a file and use DrawImage to
paste it back to the screen

However, this way won't store any undo information. To do this you would
have to store each line drawn in some array or other, possibly a
GraphicsPath.

Your code won't work because simply using DrawLine doesn't retain
information. If something covers your window or you minimize/maximize it
the drawing will be gone. You might want to read Bob Powell's Faq in this
regard.

http://www.bobpowell.net/faqmain.htm

--
Happy Coding!
Morten Wennevik [C# MVP]
Nov 16 '05 #2

P: n/a
Vin
Thanks Morten,

I understand what you want to say.
But in terms of code I have no clue what you are saying.

A c# code snippet would surely do a world of good to me.
GraphicsPath and all, I am still a novice. Even bob powell's FAQ are a
too elaborative and I got lost somewhere.

Help much appreciated

Thanks
Vin

*** Sent via Developersdex http://www.developersdex.com ***
Don't just participate in USENET...get rewarded for it!
Nov 16 '05 #3

P: n/a
First of all, this is not a good way to draw onto the window. You'll find
that if anything causes the window to need repainting (e.g. it is obscured
by some other window, or resized, or minimized, or is moved partially off
the screen and then back on) you'll lose all your drawing.

This is because there is nothing that actually stores what you've drawn onto
the window - you're just drawing onto the screen.

Windows has always relied on the ability of applications to recreate their
appearance on demand. It sends them a message (WM_PAINT) whenever it wants
them to repaint themselves, and in .NET this is manifest through the OnPaint
event in Windows Forms.

So the fact that nothing is actually storing your drawing output should make
it fairly clear that there isn't any method you can call to save the
output...

In fact the output might not even make it onto the screen - if you run the
code below when the window happens to be obscured or minimized, that drawing
won't go anywhere at all, not even onto the screen.

Here's what you should do:

public class MyForm : Form
{
private Bitmap bmp;

... and in whatever function it was that you were going to do your
drawing,
put this code....

bmp = new Bitmap(ClientRectangle.Width, ClientRectangle.Height);
using (Graphics g = Graphics.FromImage(bmp)
{
g.DrawLine(APen, x, y, OldX, OldY);
}

...

protected override void OnPaint(PaintEventArgs e)
{
e.Graphics.DrawImage(bmp, 0, 0);

base.OnPaint(e);
}

}
And now you'll be able to save that image with this code:

bmp.Save("MyBitmap.bmp", ImageFormat.Bmp);
What's been done here is that we've created a Bitmap object to hold the
image. If you want to have the image stored somewhere it's your
responsibility to make that happen, so in this example, that's why we create
the Bitmap.

By overriding OnPaint, we make sure that the contents of the Bitmap get
shown on the screen whenever Windows asks us to refresh our application's
appearance.

And because we've stored the drawing inside a Bitmap, we can now save it out
to disk whenever we like using the code shown above.

To load it back from disk, do this:

bmp = new Bitmap("MyBitmap.bmp");

Hope that helps.
--
Ian Griffiths - http://www.interact-sw.co.uk/iangblog/
DevelopMentor - http://www.develop.com/

"Vin" <kg*******@gmail.com> wrote:> Hi,

I am using the following code to draw whatever the user draws using
x,y.

// draws lines directly on a winform.
CreateGraphics().DrawLine(APen, x, y, OldX, OldY);

Now how do I save the drawing on to a bmp file on my harddisk? C# code
in this regard would be very helpful. I tried all forums but invain.

I tried with Graphics object and then

objBitmap=new Bitmap(400, 200, objGraphics);
objBitmap.Save(@"c:\test.bmp", ImageFormat.Bmp);

which didn't work, leaving me with a blank test.bmp.

Also help me load a bmp from hard disk to this form? C# code please.

Anyone out there who could help me?

Cheers
Vin

Nov 16 '05 #4

P: n/a
Vin
Thanks Ian, you've been of great help.
I did what you suggested and it seems to work. But I got couple of
problems.

1> I can't see my lines being drawn on mousemove. When I move the
window, resize it the drawing gets shown. but no on mouse move.

2> When I save the bitmap, the bmp file is black, where as my form
suface is white. No clue what's going wrong here.

Here's my code.

Kindly point me where am I making a mistake.

private Pen APen;
private int OldX;
private int OldY;

private void DrawPoint(int x, int y)
{
using (objGraphics = Graphics.FromImage(objBitmap))
{
objGraphics.DrawLine(APen, x, y, OldX, OldY);
}
}

protected override void OnPaint(PaintEventArgs e)
{
e.Graphics.DrawImage(objBitmap, 0, 0);
base.OnPaint(e);
}

private void ResetOffset(int x, int y)
{
ResetOffset(x, y, false);
}

private void ResetOffset(int x, int y, bool Reset)
{
OldX = x + System.Convert.ToInt32(Reset);
OldY = y + System.Convert.ToInt32(Reset);
}

private void Scribbler_MouseMove(object sender,
System.Windows.Forms.MouseEventArgs e)
{
StatusBar1.Text = string.Format("X:{0:d},Y:{0:d}", e.X, e.Y);
if ((e.Button == MouseButtons.Left))
{

DrawPoint(e.X, e.Y);
}
ResetOffset(e.X, e.Y, e.Button == MouseButtons.None);
}

private void Scribbler_MouseDown(object sender,
System.Windows.Forms.MouseEventArgs e)
{
DrawPoint(e.X, e.Y);
}

private void Button1_Click(object sender, System.EventArgs e)
{
APen = new Pen(Color.Red);
}

private void Button2_Click(object sender, System.EventArgs e)
{
APen = new Pen(Color.Blue);
}

private void Button3_Click(object sender, System.EventArgs e)
{
APen = new Pen(Color.Green);
}

private void Button4_Click(object sender, System.EventArgs e)
{
APen = new Pen(Color.Black);
}

private void btnSave_Click(object sender, System.EventArgs e)
{
objBitmap.Save(@"c:\Save.bmp", ImageFormat.Bmp);
objBitmap.Dispose();
objGraphics.Dispose();
}

private void Scribbler_Load(object sender, System.EventArgs e)
{
objBitmap = new Bitmap(ClientRectangle.Width,
ClientRectangle.Height);
}

Thanks
Vin
Nov 16 '05 #5

P: n/a
Windows needs to know that part of your window needs redrawing. Remember
that you're now drawing into an off-screen bitmap, and Windows doesn't know
that this bitmap is a copy of what you want to appear on screen. (Windows
has no intrinsic support for this idea of a window with some bitmap backing
store, so it just plain doesn't understand the idea that a bitmap might be
associated with what's on screen.)

So you need to tell Windows. The way to do this is to call the Invalidate
method on your control. You could just call it with no parameters - that
will refresh the whole control. However, that can be a little slow - a more
efficient way of doing it would be to call the one that takes a rectangle,
telling it which part just changed. When you do either of these, your
OnPaint method will get called, allowing the results to appear on screen.

So here's the simple but slow version:

private void DrawPoint(int x, int y)
{
using (objGraphics = Graphics.FromImage(objBitmap))
{
objGraphics.DrawLine(APen, x, y, OldX, OldY);
}

Invalidate();
}

I'll leave it as an exercise to work out the faster version. ;-)
Also, you're going to have to think about what you want to do when the
window is resized. Resizing the bitmap is one option, but to do that you'd
have to build a new one, and then draw the existing one into the new one.
Or you could just pick a bitmap size up front and not resize it. (So think
about what Windows PaintBrush does. It doesn't keep resizing the bitmap
every time you resize the window. The bitmap size remains the same until
you change it.)
--
Ian Griffiths - http://www.interact-sw.co.uk/iangblog/
DevelopMentor - http://www.develop.com/

"Vin" wrote:
Thanks Ian, you've been of great help.
I did what you suggested and it seems to work. But I got couple of
problems.

1> I can't see my lines being drawn on mousemove. When I move the
window, resize it the drawing gets shown. but no on mouse move.

2> When I save the bitmap, the bmp file is black, where as my form
suface is white. No clue what's going wrong here.

Here's my code.

Kindly point me where am I making a mistake.

private Pen APen;
private int OldX;
private int OldY;

private void DrawPoint(int x, int y)
{
using (objGraphics = Graphics.FromImage(objBitmap))
{
objGraphics.DrawLine(APen, x, y, OldX, OldY);
}
}

protected override void OnPaint(PaintEventArgs e)
{
e.Graphics.DrawImage(objBitmap, 0, 0);
base.OnPaint(e);
}

private void ResetOffset(int x, int y)
{
ResetOffset(x, y, false);
}

private void ResetOffset(int x, int y, bool Reset)
{
OldX = x + System.Convert.ToInt32(Reset);
OldY = y + System.Convert.ToInt32(Reset);
}

private void Scribbler_MouseMove(object sender,
System.Windows.Forms.MouseEventArgs e)
{
StatusBar1.Text = string.Format("X:{0:d},Y:{0:d}", e.X, e.Y);
if ((e.Button == MouseButtons.Left))
{

DrawPoint(e.X, e.Y);
}
ResetOffset(e.X, e.Y, e.Button == MouseButtons.None);
}

private void Scribbler_MouseDown(object sender,
System.Windows.Forms.MouseEventArgs e)
{
DrawPoint(e.X, e.Y);
}

private void Button1_Click(object sender, System.EventArgs e)
{
APen = new Pen(Color.Red);
}

private void Button2_Click(object sender, System.EventArgs e)
{
APen = new Pen(Color.Blue);
}

private void Button3_Click(object sender, System.EventArgs e)
{
APen = new Pen(Color.Green);
}

private void Button4_Click(object sender, System.EventArgs e)
{
APen = new Pen(Color.Black);
}

private void btnSave_Click(object sender, System.EventArgs e)
{
objBitmap.Save(@"c:\Save.bmp", ImageFormat.Bmp);
objBitmap.Dispose();
objGraphics.Dispose();
}

private void Scribbler_Load(object sender, System.EventArgs e)
{
objBitmap = new Bitmap(ClientRectangle.Width,
ClientRectangle.Height);
}

Nov 16 '05 #6

This discussion thread is closed

Replies have been disabled for this discussion.