|
It looks like the problem is that once you finish the first sibling with custom behaviour, you reset the value of behaviour to null. In other words, the logic as coded starts ignoring the value passed in after discovering the first sibling with parentModel.HasBehaviour == true .
Changing the code as follows avoids this problem:
if(item.type = parent) {
ParentModel parentModel = (parentModel)item;
ApplyBehaviour(
parentModel.Children.GetEnumerator()
, parentModel.HasBehaviour ? parentModel.Behaviour : behaviour
);
}
|
|
|
|
|
What is the reason of memory consumption in the DrawRoi function leading to hundreds of Mb?
There is a Frame bitmap and its FrameWithRoi copy to assign to PictureBox.
On the mouse move event new ROI coords are estimated and DrawRoi() is called.
DrawRoi()
{
RectangleF roi = Roi;
RectangleF rect = new RectangleF()
{
X = (float)Frame.Width * roi.X,
Y = (float)Frame.Height * roi.Y,
Width = (float)Frame.Width * roi.Width,
Height = (float)Frame.Height * roi.Height
};
if (rect.Left > 0 || rect.Right < (float)FrameWithRoi.Width ||
rect.Top > 0 || rect.Bottom < (float)FrameWithRoi.Height)
{
Graphics g = Graphics.FromImage(FrameWithRoi);
g.DrawImage(Frame, 0, 0);
using (Bitmap region = new Bitmap(FrameWithRoi.Width, FrameWithRoi.Height, FrameWithRoi.PixelFormat))
{
Graphics roi_g = Graphics.FromImage(region);
roi_g.FillRectangle(new SolidBrush(Color.FromArgb(64, 0, 0, 0)), new Rectangle(0, 0, FrameWithRoi.Width, FrameWithRoi.Height));
roi_g.FillRectangle(new SolidBrush(Color.Red), rect);
region.MakeTransparent(Color.Red);
g.DrawImage(region, 0, 0);
}
}
this.framePictureBox.Image = FrameWithRoi;
}
Чесноков
|
|
|
|
|
Two things strike me immediately:
- you are not disposing of the graphics objects you obtain. This might actually be a resource leak.
- you create a new RectangleF every time (though I think this is a value type, so it shouldn't matter).
It's also possible that the bitmap doesn't get garbage collected immediately, even though it is being disposed of at the end of the using. But it should do.
|
|
|
|
|
Yes, disposing graphics objects solved the problem.
But why the drawing is very slow? The larger the image the slower update.
Чесноков
|
|
|
|
|
Graphics objects are expensive, and you should dispose them. Why not use a using statement, just like you did for the region Bitmap ?
And why would you need two Graphics instances, and a DrawImage() ? Couldn't you just use the Bitmap(Image) constructor, and have its Graphics , just the one?
Luc Pattyn [My Articles] Nil Volentibus Arduum
The quality and detail of your question reflects on the effectiveness of the help you are likely to get. Please use <PRE> tags for code snippets, they improve readability. CP Vanity has been updated to V2.3
|
|
|
|
|
I was looking for a way to darken non ROI region in the image.
You optimizations would be welcomed.
Why the picture box update is very slow if I keep drawing on every mouse move event?
Чесноков
|
|
|
|
|
Mouse-move events are fired continuesly, and the drawing routine looks expensive. You might want to check whether the mouse has moved in the meantime, not redrawing if there's no movement detected.
Bastard Programmer from Hell
|
|
|
|
|
I recommend overlaying the semitransparent mask over the base image (either in OnPaint on the picture box or by placing another object over the top). Then all you have to redraw is the mask.
Creating graphics objects is slow, which is why you should typically do it in OnPaint. In fact, in this case, you should do that, and your mouse move handler should only call Invalidate.
|
|
|
|
|
One other thing to bear in mind. The managed version of GDI+ is slow in comparison to the unmanaged version. You pay a price for the simplicity, and that price is speed.
|
|
|
|
|
Chesnokov Yuriy wrote: Why the picture box update is very slow if I keep drawing on every mouse move event?
Because the MouseMove events fire at high frequency (allowing you to track well assuming your handler is fast), possibly 50Hz or higher (which is too high for the human eye to notice), because Graphics objects are expensive, and finally because PictureBoxes are stupid (I wouldn't be surprised if the fact you change the image just causes another mouse move event).
You want to run such things continuously? I would experiment with keeping the two Graphics and the Bitmap around as class members, i.e. not create new objects at all, just keep using them over and over.
Luc Pattyn [My Articles] Nil Volentibus Arduum
The quality and detail of your question reflects on the effectiveness of the help you are likely to get. Please use <PRE> tags for code snippets, they improve readability. CP Vanity has been updated to V2.3
|
|
|
|
|
I need to implement rubber band like ROI selection in the image as in paint editor
Чесноков
|
|
|
|
|
What I understand is that you are trying to darken a rectangle within a image, and that rectangle must be refreshed as long as the mouse is moving. Am I right?
If this is what you want to do, the problem is that you are creating too many new Graphics and Bitmap objects in a very short time (and these are expensive objects), and updating the Image property a lot of times as well. The best way to do it is to subscribe to the Paint event of the control and code everything in this event handler, so you will receive a Graphics object as a parameter. In the next example there is only a PictureBox in the Form, called pct :
public partial class Form1 : Form
{
bool drawRect = false;
Rectangle r = new Rectangle();
Brush br = new SolidBrush(Color.FromArgb(50, Color.Red));
public Form1()
{
InitializeComponent();
}
private void pct_Paint(object sender, PaintEventArgs e)
{
if (drawRect)
e.Graphics.FillRectangle(br, r);
}
private void pct_MouseDown(object sender, MouseEventArgs e)
{
drawRect = true;
r.X = e.X;
r.Y = e.Y;
}
private void pct_MouseMove(object sender, MouseEventArgs e)
{
r.Width = e.X - r.X;
r.Height = e.Y - r.Y;
Refresh();
}
private void pct_MouseUp(object sender, MouseEventArgs e)
{
drawRect = false;
Refresh();
}
}
I've made it quick. You would have to modify it in order to draw the rectangle if the mouse moves to a lower X and/or lower Y coordinate.
|
|
|
|
|
No, I need to darken the area outside rectangle.
Consider ROI region. ROI remains clear and the area outside it is darked.
I tried preinitialization of graphics and bitmaps and found that the problem part taking much of the time is:
...
roi_g.FillRectangle(new SolidBrush(Color.FromArgb(64, 0, 0, 0)), new Rectangle(0, 0, FrameWithRoi.Width, FrameWithRoi.Height));
roi_g.FillRectangle(new SolidBrush(Color.Red), rect);
region.MakeTransparent(Color.Red);
g.DrawImage(region, 0, 0);
...
Despite prinitialization it takes about 150ms
Чесноков
|
|
|
|
|
Well, then, draw four rectangles around the area you want to keep clear. Just change the Paint event handler I posted before this way:
private void pct_Paint(object sender, PaintEventArgs e)
{
if (drawRect)
{
e.Graphics.FillRectangle(br, 0, 0, pct.Width, r.Y);
e.Graphics.FillRectangle(br, 0, r.Y, r.X, pct.Height);
e.Graphics.FillRectangle(br, r.X, r.Y + r.Height, pct.Width, pct.Height);
e.Graphics.FillRectangle(br, r.X + r.Width, r.Y, pct.Width, r.Height);
}
}
This will work pretty well. Do you also want to save the image after you have darkened the area?
|
|
|
|
|
Hi
How can load an image with geotiff format in the .Net application?
And, how can read the coordination(x,y) of each point at geotiff?
thanks in advance
Best Regards,
Reza Shojaee
|
|
|
|
|
You're going to need a third party library to read GeoTiff files because they are non-standard, and the metadata inside them is not supported by the default readers. There are a number of libraries available such as libtiff.net[^] but you're probably going to be better off with GDAL[^].
|
|
|
|
|
Hi is in the following example is possible to add method Create() directly in the abstract class
instead of in each derived class (basically the methos do the same: return inizialide class of its type).
Something like this, that it doesn't works:
abstract class b
{
public b Create()
{
{ return new b(); } // but can not understand the derived class type
}
}
Hope to be clear
Thanks for your time
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace general
{
class Program
{
static void Main(string[] args)
{
D1 myClass = new D1();
D1 newClass = myClass.Create();
}
}
abstract class b
{
}
class D1:b
{
public double KM ;
public D1() { KM = 1.0; }
public D1 Create() { return new D1(); }
}
class D2 : b
{
public double KM ;
public D2() { KM = 2.0; }
public D2 Create() { return new D2(); }
}
}
<div class="signature">
<div class="modified">modified on Wednesday, June 1, 2011 3:15 AM</div></div>
|
|
|
|
|
abstract class b
{
public dynamic Create()
{
return Activator.CreateInstance(this.GetType());
}
}
"You get that on the big jobs."
|
|
|
|
|
Thanks a lot
It works . The only constrain is that you need VS10 to use "dymanic". Is there an old workaround?
|
|
|
|
|
I don't think you need dynamic here. You know what type the object will be: it will be a b .
public virtual b Create() { return (b)Activator.CreateInstance(GetType()); }
It's probably best to make this method virtual so that subclasses can do something different if they need to.
This is quite an unusual thing to want to do unless you are trying to copy an object:
void SomeFunction(b instance){
b copy = instance.Create();
instance.CopyTo(copy);
}
... as it requires you to have an instance of the object to create the new one from.
|
|
|
|
|
Thanks a lot! So suppose I do the following,
abstract class b
{
public virtual b Create() { return (b)Activator.CreateInstance(GetType()); }
}
I'm not able to use method of the derived class?
class Program
{
static void Main(string[] args)
{
D1 myClass = new D1();
D1 newClass = myClass.Create();
Console.WriteLine(newClass.KM);
b myClassAb = new D1();
b newClassAb = myClassAb.Create();
Console.WriteLine(newClassAb.KM);
}
}
|
|
|
|
|
That's correct (unless you cast it). That's kind of an unavoidable consequence of putting any method on the base class. Typically in an abstract class hierarchy, the base class will define (either concrete or abstract) most of the public interface, so you can do most things through the base.
If you know that you are working with D1, after all, you can just create a new instance with new D1() . The dynamic Create method is only needed when you want a new instance of the same type as another object, and you don't know what type that is, so you wouldn't be able to call class-specific functionality on it anyway.
|
|
|
|
|
Thank you for your clear answer.
So:
b myClassAb = new D1();
b newClassAb = myClassAb.Create();
even if newClassAb is a D1 type, I cannot use D1 methods unless cast it.
So no way to avoid to write the same piece of code in each derived class even if they basically do the same thing, if I want to use all methods of derived class. Is it?
class D1:b
{
..
public D1 Create() { return new D1(); }
}
class D2 : b
{
..
public D2 Create() { return new D2(); }
}
|
|
|
|
|
You can use generics like this:
abstract class b<T> where T: b, new()
{
...
public T Create() { return new T(); }
}
class D1 : b<D1>
{
...
}
class D2 : b<D2>
{
...
}
So, you can do:
D1 myClassD1 = new D1();
D1 newClassD1 = D1.Create();
But, you can't do anymore:
b myClassAb = new D1;
D1 newClassAb = myClassAb.Create();
because you'd have to specify the generic type for class b.
|
|
|
|
|
Now you can't call Create on an arbitrary b instance, which renders it pointless.
|
|
|
|
|