I want to provide different parts of an application with independent Graphics instances which end up painting on the same base Graphics. Simply cloning the Graphics works, but since both instances refer to the same GDI handle, there are not independent. I can't use Begin and EndContainer as well since I have a method which has to provide the new Graphics instances. -so I cannot determine when to call EndContainer. The use case is quite similar to the Graphics.create() method in Java.
I've found some workarounds, but none of them works for a Graphics provided by the PrintController.
Is there any proxy-Graphics I can use? Or is there a possibility to create another Graphics for the same device for instance?
This sounds bad. Do not store references to a Graphics object, it only ever lives temporarily and is only valid while a Paint or PrintPage event handler is running. Do make sure to pass it as an argument to whatever method does the drawing instead of storing it in a field or a global variable.
If the method is altering the state of the object then use the Save() and Restore() methods to prevent this from causing problems in subsequent methods that use that same object. Cloning it is never necessary with this approach.
Graphics objects are not meant to be persisted. You could use a backbuffer approach by drawing to a Bitmap before your final render.
Perhaps you could raise an event to which listening drawing components could subscribe, and your calling code could chain these together. That way you could use the same Graphics instance without compromising GDI efficiency.
Not sure what exactly you're trying to do but you can use CreateGraphics() on a Control or Graphics.FromImage(xx) to create a new Graphics object for the control and/or image. There's also a few more functions in Graphics.FromXXX
A possibility would be to create multiple graphics objects which are pointing to multiple targets, for example an memory image. Then after done, combine all images into one.
But the thing I don't understand is, if all graphics instances should paint to the same target why do you need multiple graphics objects in the first place?
I was facing same problem, I found the only solution is to duplicate the drawings code line !!
Like the following:
e.Graphics.DrawString(points(i).pointText, myFont, Brushes.Blue, New Point(points(i).crossPointX4, points(i).crossPointY4)) : G.DrawString(points(i).pointText, myFont, Brushes.Blue, New Point(points(i).crossPointX4, points(i).crossPointY4))
Related
Today my intstructor, where I'm intern, said I should use
HImage hi = null;
HOperatorSet.GenEmptyObject(out hi);
hi.Dispose();
hi = f.GrabImageAsync(-1.0);
Instead of
HImage hi = null;
hi = f.GrabImageAsync(-1.0);
Prototypes of used functions as follows
void HOperatorSet.GenEmptyObj(out HObject emptyObject);
HImage HFramegrabber.GrabImageAsync(double maxDelay);
I respect my instructor ,but I don't see any meaningful explanation at creating and disposing an object before calling hi = f.GrabImageAsync(-1.0); as that functions returns an instance of that object and therefore no need for Generating and Disposing object first, at least in my opinion.
So anyone can clarify if it is really needed or not. Thank you in advance.
I agree with you. Generally there is no use in creating and immediately disposing a variable.
As far as we can see from the code, HOperatorSet.GenEmptyObject doesn't interact with your f variable, so there would be no meaning in calling that method.
Also, there is no point in setting HImage hi to null, since that is probably the default already and it is set using the out parameter.
So my bet would be on:
HImage hi = f.GrabImageAsync(-1.0);
Most of the time Dispose() is called to release all managed resources that no longer in need. So let's assume that HOperatorSet.GenEmptyObject(out hi) method opens FileStream and saves reference to some field in new HImage instance. Later in code you would like to do other operation with this HImage instance and no longer need this FileStream or any other resources. It's a good moment to call hi.Dispose() that closes it before you proceed with doing anything else. But in any other case your instructor is misleading you.
There are a few classes in WinForms which have multiple purposes, some of which require resources and some of which don't. The one I'm most familiar with is Font. A Font instance encapsulates a combination of font settings as well as a GDI handle to a GDI font resource. The Font property setter of most WinForms controls will cause the controls to copy of the settings from the passed-in font object and store a copy of the passed in Font reference so that it may be returned by a call to the property getter, but will not cause the controls to actually use the passed-in font for drawing. Since the settings can be read from a Font object even after is is disposed, it is in fact possible to create and dispose Font objects when setting controls' Font properties; in some cases it may arguably be a reasonable least-of-evils approach:
If Font objects are created and abandoned without disposal, that will usually not cause too much of a GDI resource drain, but such wishful thinking doesn't represent good design.
A policy of calling Dispose on a control's old value of Font before setting a new value will require that every control own its own separate Font object, which will then encapsulate a resource the control will never use. The one advantage is that code which reads a control's Font property will be able to draw using that Font object directly.
Having controls hold references to font objects that are already disposed will make it possible for multiple controls to safely share the same font object, and will consume fewer GDI resources than either of the other approaches. The one limitation is that any code which reads a control's Font property and wants to draw with that font will have to use it to construct a new Font object for the purpose (and probably dispose of it after use).
IMHO, the fact that disposing Font objects immediately on creation is a useful pattern suggests that the Framework should have included separate types for the purposes of describing fonts (the purpose of a control's Font property) and encapsulating GDI font objects (the purpose of the Font parameter to string-drawing methods). If the latter type had included Dispose and the former type not, there would have been no question about how to use each. Since the Font type exists, however, along with code that uses it for those disjoint purposes, the eager-dispose pattern may be a reasonable least-of-evils approach.
I'm not sure that approach represents what's going on in your instructor's example since I'm not familiar with the types involved. It may be that the object returned by GenEmptyObject doesn't actually allocate any resources and its Dispose method does nothing (and stating that the particular object may be safely abandoned may be better than calling Dispose prematurely) but if the object acquires resources which won't be needed for its intended use, early disposal might possibly be appropriate if commented.
I create a new Pen Object:
Private NewPen As New Pen(New SolidBrush(Color.FromArgb(12,52,220)))
When I now call NewPen.Dispose does it also dispose of the SolidBrush I used to create the pen, or do I have to dispose of it separately?
No. The Private keyword in your snippet is the only real hint that you are making a mistake. That implies that you made the pen a field of a class. That's never the correct thing to do, drawing objects are very cheap to create (about a microsecond) but expensive to keep around. They get allocated on a desktop heap that all programs that run on that desktop need to share. You never want to occupy space in that heap needlessly.
Always create a drawing object at the moment you need it. Which lets you fall in the pit of success with the Using statement:
Protected Overrides Sub OnPaint(e As PaintEventArgs)
Using sbr = New SolidBrush(Color.FromArgb(12, 52, 220))
Using pen = New Pen(sbr)
'' Use the pen
''....
End Using
End Using
End Sub
This tends to be pretty unintuitive to many programmers, they usually learn that keeping objects around and re-using them is a Good Thing. The general rule you'd want to keep in mind is that it is usually the reverse for disposable objects. There are some types of objects that are expensive to create so seem to warrant keeping them around. The .NET Framework however always makes an effort to cache them itself. The Font class is a good example.
Simple answer: no. The Pen class (click to view the .net source code) doesn't store any references to the brush. You are responsible for disposing the brush. That's why this returns False:
Using b As New SolidBrush(Color.Black)
Using p As New Pen(b)
Debug.WriteLine("Is equal: {0}", (b Is p.Brush))
End Using
End Using
How do you get a bitmap from a graphics object (or at least a pointer to it's Scan0)?
If a graphics object really always refers to a bitmap, then it IS possible to get to the bitmap data from the graphics object. (Think: the graphics object HAS TO have a pointer to the bmp data. I'd code it in C but I'm on a project that requires everyone be hobbled by .NET.)
Applications of this would include things like:
- using unsafe code to obtain faster screenshots
- modifying what's on a control using CreateGraphics
- (and the task I'm actually trying to accomplish which would take too long to explain)
Yes, this has been asked before but never answered. I'm not looking for how to get a graphics object from a bitmap (obviously trivial).
FAIL1, FAIL2, FAIL3, FAIL4, FAIL5, FAIL6, FAIL7
I don't think what you're trying to do is possible since your assumption that "a graphics object really always refers to a bitmap" is false.
There's a good article here that shows how to render a control to bitmap if you really want a bitmap and another one here that shows how to quickly update the screen at the WndProc level. If you're more familiar with C++ that might get you going the right direction.
I'm trying to AND two bitmaps like this:
[DllImport("gdi32.dll")]
public static extern int SetROP2(IntPtr hDC, int nDrawMode);
const int SRCAND = 0x008800C6; // AND raster op.
lock (g.Clip)
{
IntPtr pDC = g.GetHdc ();
SetROP2 (pDC, SRCAND);
g.DrawImageUnscaled (currentBitmap, bound.Location);
g.ReleaseHdc (pDC);
}
But I get an "Object is currently in use elsewhere" exception from the Draw statement. Moving the ReleaseHdc statement before the Draw statement runs, but doesn't use the specified raster op.
The LockBits approach is too slow, since it copies the whole bitmap twice, one of the bitmaps is huge, and this has to happen many times per second.
Any ideas how I can trick .NET into ANDing bitmaps?
lock (g.Clip)
This cannot work. You are getting this exception because you use the bitmap in more than one thread. I'd guess at another thread that's drawing the bitmap. To make that work, you have to make sure that the two threads cannot use the bitmap at the same time. And that indeed requires the lock keyword. But on the same lock object. The Graphics instance you use won't be the same. The lock doesn't work.
Create a dedicated locking object that both threads use.
Though you found a workaround, it is worth noting the actual source of the exception. GDI and GDI+ operations cannot be interleaved - either one or the other can operate at once, but not both.
In your code, calling g.GetHdc() switches the Graphics object into a state where the newly created HDC can be used for GDI rendering. The Graphics object will then be "in use" until calling g.ReleaseHdc(). At this point, the HDC is destroyed, and the Graphics object can then be used again for rendering.
Noting that the HDC returned by the call to GetHdc() was ney created, and only exists until the call to ReleaseHdc(), where it is destroyed, it is apparent why the ROP is not applied to later operations performed by the Graphics object.
If you needed to use GDI ROPs, you would have to do all associated rendering in a pure GDI context - using Bitmap.GetHbitmap() to get the necessary handles. Be aware that similar to Graphics.GetHdc(), the HBITMAP is newly created from the Bitmap, but shares no state with it.
More details about GDI/GDI+ interop are given in KB 311221
I'm using the System.Drawing classes to generate thumbnails and watermarked images from user-uploaded photos. The users are also able to crop the images using jCrop after uploading the original. I've taken over this code from someone else, and am looking to simplify and optimize it (it's being used on a high-traffic website).
The previous guy had static methods that received a bitmap as a parameter and returned one as well, internally allocating and disposing a Graphics object. My understanding is that a Bitmap instance contains the entire image in memory, while Graphics is basically a queue of draw operations, and that it is idempotent.
The process currently works as follows:
Receive the image and store it in a temporary file.
Receive crop coordinates.
Load the original bitmap into memory.
Create a new bitmap from the original, applying the cropping.
Do some crazy-ass brightness adjusting on the new bitmap, maybe (?) returning a new bitmap (I'd rather not touch this; pointer arithmetics abound!), lets call this A.
Create another bitmap from the resulting one, applying the watermark (lets call this B1)
Create a 175x175 thumbnail bitmap from A.
Create a 45x45 thumbnail bitmap from A.
This seems like a lot of memory allocations; my question is this: is it a good idea to rewrite portions of the code and reuse the Graphics instances, in effect creating a pipeline? In effect, I only need 1 image in memory (the original upload), while the rest can be written directly to disk. All the generated images will need the crop and brightness transformations, and a single transformation that is unique to that version, effectively creating a tree of operations.
Any thought or ideas?
Oh, and I should probably mention that this is the first time I'm really working with .NET, so if something I say seems confused, please bear with me and give me some hints.
Reusing Graphics objects will probably not result in significant performance gain.
The underlying GDI code simple creates a device context for the bitmap you have loaded in RAM (a Memory DC).
The bottleneck of your operation appears to be in loading the image from disk.
Why reload the image from disk? If it is already in a byte array in RAM, which it should be when it is uploaded - you can just create a memory stream on the byte array and then create a bitmap from that memory stream.
In other words, save it to the disk, but don't reload it, just operate on it from RAM.
Also, you shouldn't need to create a new bitmap to apply the watermark (depending on how it'd done.)
You should profile the operation to see where it needs improvement (or even if it needs to be improved.)
The process seems reasonable. Each image has to exist in memory before it is saved to disk - so each version of your thumbnails will be in memory first. The key to making sure this works efficiently is to Dispose your Graphics and Bitmap objects. The easiest way to do that is with the using statement.
using( Bitmap b = new Bitmap( 175, 175 ) )
using( Graphics g = Graphics.FromBitmap( b ) )
{
...
}
I completed a similar project a while ago and did some practical testing to see if there was a difference in performance if I reused the Graphics object rather than spin up a new one for every image. In my case, I was working on a steady stream of large numbers of images (>10,000 in a "batch"). I found that I did get a slight performance increase by reusing the Graphics object.
I also found I got a slight increase by using GraphicsContainers in the Graphics object to easily swap different states into/out of the object as it was used to perform various actions. (Specifically, I had to apply a crop and draw some text and a box (rectangle) on each image.) I don't know if this makes sense for what you need to do. You might want to look at the BeginContainer and EndContainer methods in the Graphics object.
In my case, the difference was slight. I don't know if you would get more or less improvement in your implementation. But since you will incur a cost in rewriting your code, you might want to consider finishing the current design and doing some perf tests before rewriting. Just a thought.
Some links you might find useful:
Using Nested Graphics Containers
GraphicsContainer Class
I am only going to throw this out there casually, but if you wanted a quick 'guide' to best practices for working with images, look at the Paint.NET project. For free high-proformance tools for doing image manipulation, look at AForge.NET.
The benefit of AForge is to allow you to do alot of these steps without creating a new bitmap every time. If this is for a website, I can almost guarentee that the code you are working with will be the performance bottleneck for the application.