Why CopyFromScreeen and not CopyToScreen?

  • Thread starter Thread starter bern11
  • Start date Start date
B

bern11

CopyFromScreen has alot of cool options in the CopyPixelOperation
enumeration. But, I don't get it. I want to overlay bitmaps using the
various options, so I have to first draw each on screen then copy it to
a graphics object???? Doesn't sound right, I must be missing something,
what is it?
 
CopyFromScreen has alot of cool options in the CopyPixelOperation
enumeration. But, I don't get it. I want to overlay bitmaps using the
various options, so I have to first draw each on screen then copy it to
a graphics object???? Doesn't sound right, I must be missing something,
what is it?

CopyFromScreen exists to get the bits from a specific place: the displayed
video buffer. There's no requirement that when you draw, you draw to the
screen.

If you want to composite a variety of bitmaps without drawing them to the
screen, simply create a Bitmap instance of appropriate size for your
operations, use Graphics.FromImage() to get a Graphics instance from that
Bitmap, and then draw each of your other Bitmap instances using the
various options you would have used drawing to the screen instead.

After doing that, you will have a final Bitmap instance that is the same
as if you had drawn everything to the screen and then used CopyFromScreen
to get the results.

Pete
 
Peter said:
CopyFromScreen exists to get the bits from a specific place: the
displayed video buffer. There's no requirement that when you draw, you
draw to the screen.

If you want to composite a variety of bitmaps without drawing them to
the screen, simply create a Bitmap instance of appropriate size for
your operations, use Graphics.FromImage() to get a Graphics instance
from that Bitmap, and then draw each of your other Bitmap instances
using the various options you would have used drawing to the screen
instead.

After doing that, you will have a final Bitmap instance that is the
same as if you had drawn everything to the screen and then used
CopyFromScreen to get the results.

Pete

But CopyFromScreen doesn't take a bitmap or 2nd graphics as an argument.
It appears to copy from one part of a graphics object to another. I
could extend the graphics object to have an off-screen area, draw there,
then copy (with the desired effects options). That is the way I am
thinking now. I was hoping to avoid a DrawImage-then-Copy. Thinking
about it, it looks like a video-memory-type operation where you would
keep objects off-screen but in video memory for fast copies.
Unfortunately, when it was brought into GDI, its functionality wasn't
extended.

Memory is cheap - I'll just size the graphics object for twice the
screen-size.
 
But CopyFromScreen doesn't take a bitmap or 2nd graphics as an argument.

And that's relevant how? My point is that it's the wrong method to use,
given what it _appears_ you asked about doing. The parameters it takes or
does not take aren't relevant because you shouldn't be using it. It is
specifically for taking an image from the screen, and copying it somewhere
else (for example, a Graphics instance you got from a different Bitmap
instance). If you don't want to start by drawing to the screen in the
first place, you can't use CopyFromScreen.
It appears to copy from one part of a graphics object to another.

The CopyFromScreen method copies a specified area from the screen _to_ the
Graphics instance on which it's called. It does not "copy from one part
of a graphics object to another" unless the Graphics instance used to call
the method turns out to represent the screen itself.
I could extend the graphics object to have an off-screen area, draw
there, then copy (with the desired effects options). That is the way I
am thinking now.

How, exactly, do you intend to "extend the graphics object"? If you have
a Graphics instance that currently represents the screen, it's not like
you can just tell it "okay, you're now twice as big".

Conversely, if your Graphics instance doesn't represent the screen, then
you're already dealing with an off-screen image.

It _seems_ to me that you are trying to take advantage of the
CopyPixelOperation enumeration without actually drawing the source image
to the screen, but unfortunately there's just no way (that I know of) to
do that using the Graphics class in .NET.

Now, all that said, the underlying source for this enumeration is the
drawing modes found in the native Windows HDC object. So, if what you
want is off-screen drawing that uses something more complex than the two
compositing modes that the Graphics class does offer, that's one approach.

It may be that the Windows Presentation Foundation also offers something
along these lines. I haven't used it, so I don't know. Guess I ought to
upgrade to .NET 3.0 some day. :)

Pete
 
Peter said:
And that's relevant how? My point is that it's the wrong method to
use, given what it _appears_ you asked about doing. The parameters it
takes or does not take aren't relevant because you shouldn't be using
it. It is specifically for taking an image from the screen, and
copying it somewhere else (for example, a Graphics instance you got
from a different Bitmap instance). If you don't want to start by
drawing to the screen in the first place, you can't use CopyFromScreen.



The CopyFromScreen method copies a specified area from the screen _to_
the Graphics instance on which it's called. It does not "copy from one
part of a graphics object to another" unless the Graphics instance used
to call the method turns out to represent the screen itself.
yup. Any idea if the function could be fooled into thinking another
graphics object is the screen? I am using a BufferedGraphicsContext, so
I am doing off-screen rendering.
How, exactly, do you intend to "extend the graphics object"? If you
have a Graphics instance that currently represents the screen, it's not
like you can just tell it "okay, you're now twice as big".
//BufferedGraphicsContext.Allocate Method (Graphics, Rectangle)
// Allocates a graphics buffer using the pixel format
// of the specified Graphics object.
grafx = appDomainBufferedGraphicsContext.Allocate(this.CreateGraphics(),
new Rectangle( 0, 0, screenHeight, screenWidth*2 ));

// Now you're twice as big :)
Conversely, if your Graphics instance doesn't represent the screen,
then you're already dealing with an off-screen image.

It _seems_ to me that you are trying to take advantage of the
CopyPixelOperation enumeration without actually drawing the source
image to the screen, but unfortunately there's just no way (that I know
of) to do that using the Graphics class in .NET.
YUP (unfortunately)
Now, all that said, the underlying source for this enumeration is the
drawing modes found in the native Windows HDC object. So, if what you
want is off-screen drawing that uses something more complex than the
two compositing modes that the Graphics class does offer, that's one
approach.
Don't want to go there.
I messed around trying to mix HDC object calls with managed drawing, it
got extremely complicated very quickly
It may be that the Windows Presentation Foundation also offers
something along these lines. I haven't used it, so I don't know.
Guess I ought to upgrade to .NET 3.0 some day. :)

Pete

so many cool options, just out of reach......
 
yup. Any idea if the function could be fooled into thinking another
graphics object is the screen?

Doubtful. Especially if you are already shy about mixing managed and
unmanaged rendering. Even if possible, I would guess that somehow
impersonating the display video buffer would be orders of magnitude more
difficult than just using unmanaged GDI/GDI+ to do your rendering.
I am using a BufferedGraphicsContext, so I am doing off-screen rendering.

Any particular reason you're doing the double-buffering explicitly? I
have found that simply setting the Control's rendering style to
double-buffered works fine.

In any case, there should be very little difference between using the
BufferedGraphicsContext and simply creating an intermediate bitmap, at
least from an API point of view. I admit, since I'm happy using the
built-in double-buffering, I have basically no experience with the
BufferedGraphicsContext, but I suspect that if it has any advantage over
simply drawing to an intermediate Bitmap instance, it's that it somehow
uses video memory for the frame buffer, rather than system memory.
//BufferedGraphicsContext.Allocate Method (Graphics, Rectangle)
// Allocates a graphics buffer using the pixel format
// of the specified Graphics object.
grafx = appDomainBufferedGraphicsContext.Allocate(this.CreateGraphics(),
new Rectangle( 0, 0, screenHeight, screenWidth*2 ));

// Now you're twice as big :)

Okay...so you have a Graphics instance that does not actually represent
the screen, which you are drawing to.

Is your reasoning behind expanding the BufferedGraphicsContext that you
can use CopyFromScreen without incurring the video-memory-to-system-memory
performance hit? If so: have you confirmed that there is a significant
performance hit for your usage? and have you confirmed that using
BufferedGraphicsContext avoids that?

In particular, if BufferedGraphicsContext doesn't actually allow you to do
a video-memory-to-video-memory copy, then it's not really getting you
anything except more complication. Even if it does do that, keep in mind
that with PCI-E, there is no longer the terrible asymmetric data bandwidth
going from the video to system memory versus the other direction.

Basically, it seems like you've created a fairly complicated scenario, one
that is no less complicated than would be simply using unmanaged GDI to
composite your bitmaps.

Even if the expansion of the BufferedGraphicsContext does what it seems
like you're hoping it does, you still have to draw all of your data to the
screen sequentially, copying it back to the BufferedGraphicsContext to get
the compositing you want, and then presumably copy the result back to the
screen. You might get that to happen quickly, but I doubt you can get it
to happen quickly enough that the user won't notice (in particular, I'd
expect a fair amount of flickering as the different images get put on the
screen so that you can copy them back to your off-screen Graphics
instance).
[...]
Now, all that said, the underlying source for this enumeration is the
drawing modes found in the native Windows HDC object. So, if what you
want is off-screen drawing that uses something more complex than the
two compositing modes that the Graphics class does offer, that's one
approach.
Don't want to go there.
I messed around trying to mix HDC object calls with managed drawing, it
got extremely complicated very quickly

I don't know what you mean by "extremely complicated", but it sure seems
to me that what you're talking about doing instead is at least as
complicated.

Pete
 
Back
Top