Screen Capture (Screen Copying) example / the perils of Image/ Bitmapcopying to file

R

raylopez99

Beware newbies: I spent a day before I figured this out: copying a
bitmap (image) file to file is not quite like copying a text file--you
have to do some tricks (see below), like using a "Graphics" object to
wrap around the image (!). It's not so simple as shown in most
examples (where they have a simple image file and hard copy it into a
harddrive along the lines of : image.Save(@"C:\\temp\\myimage.pgn");
That will work, but it's a rare bird that needs this.

The below is adapted from Chris Sells book and from another thread
here. The only thing I have not figured out is whether you need to
use .Close on the stream that the image is stored /backed into--I
think it can be safely deleted, since it's redundant to the using
bracket, but I'll await expert commentary from here.

RL

http://tinyurl.com/5a7p5q (older thread that outlines problem)

I found the solution. It was indeed the pecularities of Image and
Bitmap (which is a subset of Image). It's very bizarre. I assumed
Bitmap and Image are like 'text files' except binary, but in fact you
have to 'wrap them' in a graphics object. See the below complete
code, which works, on a form of screen capture.

Adapted from Chris Sells Chapter 5 "Windows Forms 2.0 Programming"

//declare this member variable before class Form instantiation as a
member variable (that is, outside the class that has
InitializeComponent();), say just after your second bracket after the
namespace bracket "{" will do, after ' public partial class MyForm:
Form'. Don't initialize, just declare it: Bitmap
myBitmapScreenShot;

//click on this button to capture what's painted on the screen.

private void ScreenCapture_button (object sender, EventArgs e)
{
Rectangle screenRect = Screen.PrimaryScreen.WorkingArea;
myBitmapScreenShot = new Bitmap (screenRect.Width,
screenRect.Height);
using (Graphics targetGraphics = Graphics.FromImage
(myBitmapScreenShot))
{
targetGraphics.CopyFromScreen(0,0,0,0,new
Size(myBitmapScreenShot.Width,myBitmapScreenShot.Height));

}

// now click on this button to save the screenshot to file

private void MySAVEButton_Click(object sender, EventArgs e)
{

String path;
Stream myStream;
saveFileDialog1.InitialDirectory = "C:\
\imageScreenSave.png";
saveFileDialog1.Filter = "picture files (*.png)|*.png";
saveFileDialog1.FilterIndex = 2;
saveFileDialog1.RestoreDirectory = true;

using (Graphics displayGraphics = this.CreateGraphics())
//create Bitmap to draw into based on existing Graphics
object (p. 222 Sells)

using (Image image = new Bitmap(myBitmapScreenShot))

//wrap Graphics object around image to draw into

using (Graphics imageGraphics =
Graphics.FromImage(image))
{

if (saveFileDialog1.ShowDialog() == DialogResult.OK)
{

if ((myStream = saveFileDialog1.OpenFile()) !=
null)
{

path = saveFileDialog1.FileName;

//image.Save(path);//works not at all- why?
Who cares!

image.Save(myStream,
System.Drawing.Imaging.ImageFormat.Png);
//works fine! (and that's all that matters)
myStream.Close(); //is this redundant since
wrapped in a 'using'?
}
}
}

}
 
M

Mark Salsbery [MVP]

raylopez99 said:
Beware newbies: I spent a day before I figured this out: copying a
bitmap (image) file to file is not quite like copying a text file--you
have to do some tricks (see below), like using a "Graphics" object to
wrap around the image (!). It's not so simple as shown in most
examples (where they have a simple image file and hard copy it into a
harddrive along the lines of : image.Save(@"C:\\temp\\myimage.pgn");
That will work, but it's a rare bird that needs this.

The below is adapted from Chris Sells book and from another thread
here. The only thing I have not figured out is whether you need to
use .Close on the stream that the image is stored /backed into--I
think it can be safely deleted, since it's redundant to the using
bracket, but I'll await expert commentary from here.

...


I'm not sure what you're trying to say.

Saving Bitmaps has nothing to do with the Graphics class.

Bitmap bits are often written to directly, which doesn't involve a Graphics.

Creating a Graphics from a Bitmap lets you use the Graphics methods to draw
on the Bitmap.

Cheers,
Mark
 
R

raylopez99

I'm not sure what you're trying to say.

Saving Bitmaps has nothing to do with the Graphics class.

Bitmap bits are often written to directly, which doesn't involve a Graphics.

Creating a Graphics from a Bitmap lets you use the Graphics methods to draw
on the Bitmap.

Cheers,
Mark

I'm sure you're right, but, since this particular application was for
a screenshot (which uses the Graphics class), I could not get it to
work until I wrapped the Bitmap in the graphics class as shown. The
bitmap was stored in a picturebox, which I thought was
'static' (doesn't change on Paint) but I could not store it. Perhaps
the problem was I was downcasting from Image to Bitmap (not clear if I
was, but see the link in the original thread), which apparently is not
good. In any event, following the template I posted, and upcasting
from Bitmap to Image, it worked and the screenshot is fine, and saves
properly.

All's well that ends well, which is all you can ever hope for in these
complex managed languages (unless you want to dive under the hood and
get into assembly-like language and decorator classes, vtables and
what not to see what went wrong).

RL
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top