C#/GDI+ - Any way to make this faster

Started by
7 comments, last by Aardvajk 16 years, 11 months ago
I'm trying to learn C# so I can write a tilemap editor. The following code just draws a bitmap in a grid across the form, but it seems really laggy compared to my existing unmanaged C++ Win32 API version, which does the same thing but obviously with BitBlt. Is there any way to speed the below up? Am I missing something? I've tried drawing to an offscreen bitmap then dumping it on the form, but it doesn't seem any quicker.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace WindowsApplication1
{
    public partial class Form1:Form
    {
        public Form1()
        {
        InitializeComponent();
        }

        private void Form1_Paint(object sender,PaintEventArgs e)
        {
            Bitmap Bmp=new Bitmap("/Graphics/Udo/Udo/left.bmp");

            for(int Y=0;Y<32;++Y)
            {
                for(int X=0;X<42;++X)
                {
                    e.Graphics.DrawImageUnscaled(Bmp,new Point(X*32,Y*32));
                }
            }
        }

    }
}


Thanks.
Advertisement
The thing that sticks out from that to me is that every time paint is called, you read the bitmap from the file. That definitely is slowing it up. Load the bitmap in the Load event of the form and then use that bitmap in the Paint event, that should speed things up nicely.
Quote:Original post by Zoso
The thing that sticks out from that to me is that every time paint is called, you read the bitmap from the file. That definitely is slowing it up. Load the bitmap in the Load event of the form and then use that bitmap in the Paint event, that should speed things up nicely.


Sorry - should have said I have tried that. I've even tried just FillRectangle-ing with solid colour rather than drawing an image and it still seems really slow compared to the Win32 API equivalent code.

Thanks anyway. Any other suggestions?
did you also do the equivalent for Win32's WM_ERASEBKGND? i think it's
something like this:

// set styles to reduce flicker and painting over twice
Setstyle(Controlstyles.AllPaintingInWmPaint, true);
Setstyle(Controlstyles.UserPaint, true);
Setstyle(Controlstyles.OptimizedDoubleBuffer, true);
Just a thought, this could be more trouble than it's worth, or impossible (I know very little GDI+ and even less C#).

I would try drawing all the tiles onto one large bitmap, then overwriting portions of that whenever a new tile is placed. Seems like you would save some time only making the one draw call for the large bitmap, but I could be wrong here *shrug*.
You should draw the bitmaps to an offscreen buffer and then just draw that to the screen. Also, you create a new Point several times. Just make one Point and change it's X and Y in the loop.
zoso - As I say, I've tried that already. It is no quicker drawing to an offscreen bitmap than to the screen. I can try the Point idea, but I'm convinced it is the drawing operations that are slow.

Driv3Me - That's a good idea, but unfortunatley it is not feasible to create an offscreen image the potential size of an entire tilemap since it could potentially be huge. I need to just be able to draw the visible portion of the tile map on a scroll or resize, much as my C++ version works.

yadango - interesting. I'll have a look at that tonight. Thanks.

Keep the ideas coming [smile].
Use Vista? [wink]

I've had general performance issues with fast GDI+ rendering on XP. It hasn't been so much the actual drawing, but the presentation of the area I've been drawing to to the display (by this I mean that if I got something running slowly, I could drag the window off the screen and the framerate would rocket). sirob wrote a pixel-pushing test app that ran incredibly fast on his machine (Vista), but on my XP machine ran at under 1FPS. Again, moving the window partially off the display greatly increased the framerate, even though the same amount of drawing was being done.

My project was doing all of the rendering in software and copying an array of integers (containing the pixel information) to a Bitmap. This was changed to dump the data onto a texture (XNA), and went from 100% CPU usage, 30FPS to ~20% CPU usage, 60FPS.

If you find a workaround, I'd love to hear it.

[Website] [+++ Divide By Cucumber Error. Please Reinstall Universe And Reboot +++]

Nah, no workarounds. I've tried yandango's suggestion without any speed up, and moved the new Point and bitmap load out of the paint event but no joy.

Doesn't matter. It is not too bad really and bearable for a map editor.

Thanks anyway.

This topic is closed to new replies.

Advertisement