1

This is a follow on to my question How To Handle Image as Background to CAD Application

I applied the resizing/resampling code but it is not making any difference. I am sure I do not know enough about GDI+ etc so please excuse me if I seem muddled.

I am using a third party graphics library (Piccolo). I do not know enough to be sure what it is doing under the hood other than it evenually wraps GDI+.

My test is to rotate the display at different zoom levels - this is the process that causes the worst performance hit. I know I am rotating the camera view. At zoom levels up to 1.0 there is no performance degradation and rotation is smooth using the mouse wheel. The image has to be scaled to the CAD units of 1m per pixel at a zoom level of 1.0. I have resized/ resampled the image to match that. I have tried different ways to speed this up based on the code given me in the last question:

public static Bitmap ResampleImage(Image img, Size size) {
            using (logger.VerboseCall()) {

                var bmp = new Bitmap(size.Width, size.Height, PixelFormat.Format32bppPArgb);
                using (var gr = Graphics.FromImage(bmp)) {
                    gr.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.Low;
                    gr.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighSpeed;
                    gr.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighSpeed;                 

                    gr.DrawImage(img, new Rectangle(Point.Empty, size));
                }
                return bmp;
            }
        }

I guess this speeds up the resample but as far as I can tell has no effect on the performance when trying to rotate the display at high zoom levels. User a performance profiler (ANTS) I am able to find the code that is causing the performance hit:

 protected override void Paint(PPaintContext paintContext) {
            using (PUtil.logger.DebugCall()) {
                try {
                    if (Image != null) {
                        RectangleF b = Bounds;

                        Graphics g = paintContext.Graphics;

                        g.DrawImage(image, b);
                    }
                }
                catch (Exception ex) {
                    PUtil.logger.Error(string.Format("{0}\r\n{1}", ex.Message, ex.StackTrace));
                    //----catch GDI OOM exceptions
                }
            }
        }

The performance hit is entirely in g.DrawImage(image, b);

Bounds is the bounds of the image of course. The catch block is there to catch GDI+ OOM exceptions which seem worse at high zoom levels also.

The number of times this is called seems to increase as the zoom level increases....

There is another hit in the code painting the camera view but I have not enough information to explain that yet except that this seems to paint all the layers attached to the camera - and all the objects on them I assume - when when the cameras view matrix and clip are applied to the paintContext (whatever that means).

So is there some other call to g.DrawImage(image, b); that I could use? Or am I at the mercy of the graphics engine? Unfortunately it is so embedded that it would be very hard to change for me

Thanks again

Community
  • 1
  • 1
ScruffyDuck
  • 2,606
  • 3
  • 34
  • 50
  • The code uses two different objects, one named Image, the other named image. Accuracy is important here. If this graphics library applies a transformation (Graphics.Transform is not the identity matrix) then resampling the image won't get you ahead. – Hans Passant Jul 06 '11 at 16:13
  • Hmmm - I had not noticed that. I will check that piece of code again. Your comment on resampling is right of course. At the moment I am resampling the image to a suitable size and also changing its color depth to 8bit in an attempt to make the image smaller. I am not sure that is having much if any effect. Unless I can find some way either to reduce the calls to g.DrawImage or find a way to execute that faster (with unmanaged code?) I think I am going no where. – ScruffyDuck Jul 07 '11 at 06:15

1 Answers1

1

I think you you use,if I'm not mistake, PImageNode object form Piccolo. The quantity of calls to that method could increase because Piccolo engine traces "real" drawing area on the user screen, based on zoom level (kind of Culling) and draws only the nodes which are Visible ones. If you have a lot of PImageNode objects on your scene and make ZoomOut it will increase the quantity of PImageNode objects need to be drawn, so the calls to that method.

What about the performance:

1) Try to use SetStyle(ControlStyles.DoubleBuffer,true); of the PCanvas (if it's not yet setted up)

2) look here CodeProject

Regards.

Tigran
  • 61,654
  • 8
  • 86
  • 123
  • Thanks - it is nice to know that someone else knows something about Piccolo. Yes I am using the PImage Node. I have double buffering enabled. There is only one Image and the problem increases as I zoom in rather than out. – ScruffyDuck Jul 05 '11 at 20:23
  • Really good written .NET library, I used it years ago for industrial control systems programming IDE development with great results. – Tigran Jul 05 '11 at 20:25
  • Too bad it relies on GDI+ though. Direct2D would be the way to go for such applications and you would get much better performance. – Igor Brejc Jul 06 '11 at 16:55
  • As much as i remember Piccolo is University based project and , at least initially (don't know about current state) was looking for Mono support too. I believe this one of the reasons why thay relay on pure GDI+. – Tigran Jul 06 '11 at 17:18