tags:

views:

36

answers:

2

hi I'm using code from the following link and using the fast / unsafe option. however on slower pc's there is still a lag. http://www.vcskicks.com/custom_shape_form_region.php

I was wondering if on first run the app creates the region and then stores it somewhere or even I supply it with the app if that would speed it up!??

if so how would you save and read a region?

or is there a better/faster approach I could use?

it's a .net4 windows app.

cheers

+2  A: 

Converting a bitmap to a Region is a fundamentally slow process. However, I saw the author mentioning GetPixel() which is about as slow you could ever make it. Reading pixels in a bitmap can be a lot faster if you use an unsafe pointer.

The code in this web page does so and generates the Region you need.

Hans Passant
thank you for your reply, however the link I gave has two ways a "safe" way which uses GetPixel and a fast / unsafe option that uses a pointer and is similar to the code you gave. as I say I'm using the getRegionFast way.
Adrian
Important to mention these details in a question. Well, that's about it for possible speed improvements. As I said, converting a bitmap to a Region is expensive. Scan-converting a bitmap from a raster format to a vector format is difficult. Focus on not actually using a bitmap but creating the GraphicsPath directly. Maybe you can do it offline (on your dev machine) instead of executing that code every single time when you create the window. So you can quickly re-create the path from a file.
Hans Passant
hi Hans, yes this was approach I was asking about in my question "I was wondering if on first run the app creates the region and then stores it somewhere or even I supply it with the app if that would speed it up!??" BTW I ran the code in your link and the code I had and wrapped it with stopwatch and the code in your link is 500 -800ms quicker!and in the comments there is an option which runs as safe code which is just as quick :)so that's a good start.But as above and per my question how do I save the region to disk and read it back?
Adrian
I kinda tuned you out after finding out that you already tried what I recommended without mentioning it in your question. You tuned me out too by focusing only on the last part of my comment. GraphicsPath.GetData, something like that. Good luck with it.
Hans Passant
hmm I'm sorry but if you look at my question you will see it was stated " I'm using code from the following link and using the fast / unsafe option" but thanks anyway...
Adrian
+1  A: 

The region object can't be directly serialized as it isn't marked with Serializable. However, you can easily serialize it anyways and I agree that reading the region from a file will lead to increased speed on slower machines.

The method shown below will probably be enough for you and shows the idea but it would make more sense in production code to save region.dat as a resource and compile it with your application.

  1. Move the GraphicsPath to the argument list in getRegionFast (we need to get it back), so it looks like this:

    public unsafe static Region getRegionFast(Bitmap bitmap, Color transparencyKey, int tolerance, GraphicsPath path)

  2. Remove path.Dispose() from that method.

  3. Create this class:

    [Serializable]
    public class SerializedData
    {
       public SerializedData(GraphicsPath path) 
       {
        Points = new List<PointF>(path.PathPoints);
        Types = new List<byte>(path.PathTypes);
       }            
       public List<PointF> Points { get; set; }
       public List<byte> Types { get; set; }
    

    }

  4. Change the Form1 constructor so the region is set like this:

    this.Region = GetRegionTryCached();
    
  5. Copy/paste the GetRegionTryCached method into Form1:

    private Region GetRegionTryCached()
    {
        const string filePath = @".\path.dat";           
    
    
    
    // Check if the path has been serialized:
    if (File.Exists(filePath))
    {                
    using (FileStream fs = File.OpenRead(filePath))
    {
        BinaryFormatter formatter = new BinaryFormatter();
        SerializedData data = (SerializedData)formatter.Deserialize(fs);
        GraphicsPath path = new GraphicsPath(data.Points.ToArray(), data.Types.ToArray());
        return new Region(path);
    }
    }
    else
    {
    GraphicsPath path = new GraphicsPath();
    
    
    // Create it as before:                
    Region region = BitmapToRegion.getRegionFast((Bitmap)this.BackgroundImage, Color.FromArgb(0, 255, 0), 100, path);                                               
    
    
    BinaryFormatter formatter = new BinaryFormatter();
    // Serialize the path:
    using (FileStream fs = File.Open(filePath, FileMode.Create, FileAccess.Write))
    {
        SerializedData data = new SerializedData(path);
        formatter.Serialize(fs, data);
        path.Dispose();
    }
    
    
    return region;
    }            
    
    }
steinar
There is something really funky going on in the formatting of this, I'm trying to resolve that.
steinar