6 Replies - 79929 Views - Last Post: 03 December 2010 - 05:43 PM Rate Topic: -----

#1 microchip  Icon User is offline

  • New D.I.C Head

Reputation: 4
  • View blog
  • Posts: 37
  • Joined: 14-August 05

[C#] Fast acces to bitmap pixels?

Posted 19 February 2006 - 06:20 AM

Hi everyone
I've been trying to mess around with image recognition in C# for some time now. But to do that, I need acces to all the pixels in the bitmap individually. At the moment, I'm using getPixel and setPixel. It works, but it's VERY slow. Is there any faster way to acces pixels in a bitmap? Unsafe code maybe?
Is This A Good Question/Topic? 0
  • +

Replies To: [C#] Fast acces to bitmap pixels?

#2 Amadeus  Icon User is offline

  • g+ + -o drink whiskey.cpp
  • member icon

Reputation: 248
  • View blog
  • Posts: 13,506
  • Joined: 12-July 02

Re: [C#] Fast acces to bitmap pixels?

Posted 19 February 2006 - 08:43 AM

I'm afriad I don't know very much about working with images programatically...are you just using the Bitmap class? I seem to remember that working in unsafe mode could speed things up, but I've never performed the comparison.
Was This Post Helpful? 0
  • +
  • -

#3 microchip  Icon User is offline

  • New D.I.C Head

Reputation: 4
  • View blog
  • Posts: 37
  • Joined: 14-August 05

Re: [C#] Fast acces to bitmap pixels?

Posted 19 February 2006 - 09:41 AM

Jup, the bitmap class. The problem is, to access the pixels unsafly, I need the starting adress of the array (assuming it is an array internally), and the format.
Was This Post Helpful? 0
  • +
  • -

#12 microchip  Icon User is offline

  • New D.I.C Head

Reputation: 4
  • View blog
  • Posts: 37
  • Joined: 14-August 05

Re: [C#] Fast acces to bitmap pixels?

Posted 08 March 2006 - 10:59 AM

Okay, I'm back with a solution. With some help of a msdn article, I made this class :) :

using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Drawing.Imaging;

namespace SampleGrabberNET
{
    public unsafe class UnsafeBitmap
    {
        Bitmap bitmap;

  // three elements used for MakeGreyUnsafe
  int width;
  BitmapData bitmapData = null;
  Byte* pBase = null;

  public UnsafeBitmap(Bitmap bitmap)
  {
 	 this.bitmap = new Bitmap(bitmap);
  }

        public UnsafeBitmap(int width, int height)
        {
            this.bitmap = new Bitmap(width, height, PixelFormat.Format24bppRgb);
        }

  public void Dispose()
  {
 	 bitmap.Dispose();
  }

  public Bitmap Bitmap
  {
 	 get
 	 {
    return(bitmap);
 	 }
  }

  private Point PixelSize
  {
 	 get
 	 {
    GraphicsUnit unit = GraphicsUnit.Pixel;
    RectangleF bounds = bitmap.GetBounds(ref unit);

    return new Point((int) bounds.Width, (int) bounds.Height);
 	 }
  }

  public void LockBitmap()
  {
 	 GraphicsUnit unit = GraphicsUnit.Pixel;
 	 RectangleF boundsF = bitmap.GetBounds(ref unit);
 	 Rectangle bounds = new Rectangle((int) boundsF.X,
    (int) boundsF.Y,
    (int) boundsF.Width,
    (int) boundsF.Height);

 	 // Figure out the number of bytes in a row
 	 // This is rounded up to be a multiple of 4
 	 // bytes, since a scan line in an image must always be a multiple of 4 bytes
 	 // in length. 
 	 width = (int) boundsF.Width * sizeof(PixelData);
 	 if (width % 4 != 0)
 	 {
    width = 4 * (width / 4 + 1);
 	 }
 	 bitmapData = 
    bitmap.LockBits(bounds, ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);

 	 pBase = (Byte*) bitmapData.Scan0.ToPointer();
  }

  public PixelData GetPixel(int x, int y)
  {
            PixelData returnValue = *PixelAt(x, y);
 	 return returnValue;
  }

        public void SetPixel(int x, int y, PixelData colour)
        {
            PixelData* pixel = PixelAt(x, y);
            *pixel = colour;
        }

  public void UnlockBitmap()
  {
 	 bitmap.UnlockBits(bitmapData);
 	 bitmapData = null;
 	 pBase = null;
  }
        public PixelData* PixelAt(int x, int y)
        {
            return (PixelData*)(pBase + y * width + x * sizeof(PixelData));
        }
    }
    public struct PixelData
    {
        public byte blue;
        public byte green;
        public byte red;
    }
}



Use it, if you find it useful :)

You can use it like this:

UnsafeBitmap your_fast_bitmap = new UnsafeBitmap(old_safe_bitmap);
your_fast_bitmap.LockBitmap();
PixelData pixel = your_fast_bitmap.getPixel(3, 4);
//more setpixel/getpixel calls here!
your_fast_bitmap.UnlockBitmap();

Here's the article on msdn that deals with unsafe bitmap access: http://msdn.microsof...arp11152001.asp

This post has been edited by microchip: 08 March 2006 - 11:04 AM

Was This Post Helpful? 1

#13 woodjom  Icon User is offline

  • D.I.C Addict
  • member icon

Reputation: 29
  • View blog
  • Posts: 549
  • Joined: 08-May 08

Re: [C#] Fast acces to bitmap pixels?

Posted 08 May 2008 - 08:04 AM

I have a question....what if i am wanting to look for a pattern within a screen shot. Specifically for mapping of game areas? I have a VB.net form that will automate screenshots ever few seconds but currently am unable to find a way to do a matching algorithm based on a predefined pattern. Reason for the pattern is cause different users may have this pattern located in different areas of the screen during play.

this would be the pattern area:
Posted Image

The gold area ring for the most part....not too worried about the compass points. If i could streamline this before the screenshot that would be great but at minimal....taking the screenshot and then searching the bitmap created for this pattern is the least i want to be able to do.

I realize this is the C# board but i can easily transverse from c# to vb.net with little to no problem. This thread just seems to be the more in line with what i am trying to do but is not the exact solution i am looking for. At least point me in the correct direction :)

This post has been edited by woodjom: 08 May 2008 - 08:12 AM

Was This Post Helpful? 0
  • +
  • -

#14 Public_account  Icon User is offline

  • New D.I.C Head

Reputation: 1
  • View blog
  • Posts: 37
  • Joined: 16-February 07

Re: [C#] Fast acces to bitmap pixels?

Posted 18 May 2008 - 05:19 PM

hey. Thanks for the unsafe bitmap code microchip, saved me a lot of effort trying to churn out some code in a hurry.

To WOW guy (it is wow right?)

If you are trying to do that match, the first thing I would do would be to exlude all the pixels that are the wrong colour. The map thing isnt semitransparent or affected by light in the game, so remove everything but the ring using RGB matching. Remove the rest just by setting it to black, and make a note to just not evaluate anything black later.

You may find that some of the screen is just the right colour later on. This would be quite inconvenient. You can remove this by 2 methods:
SIMPLE METHOD:
if, after some experimenting, you find that only a small bit of the screen is the same clour as the map surround, you can just find the biggest lump of "right colour", by like taking a sum of the number of pixels in each quater of the screen that are the right colour, then subdividing or something. Dead easy to code, maybe no the most efficient though... and only works if map is biggest.
MIDDLE METHOD:
or you can take into account that the map surround is the only bit never moving by keeping a buffer of a few maps, and comparing say current clip to a clip 6 frames ago. not moved? probably the map. Then do the simple method. again easy to code up, but a bit more computationaly expensive.
THE HARD WAY:
http://ieeexplore.ie...rnumber=4118765
if you can get hold of this paper, its a really cool fast way of shape matching, and can be configured to be learning :-). Do 1, and maybe 2, then run that, and your map thing will almost always be found regardless of what colour the background is.
Was This Post Helpful? 0
  • +
  • -

#15 Guest_Anton*


Reputation:

Re: [C#] Fast acces to bitmap pixels?

Posted 03 December 2010 - 05:43 PM

Thanks microchip, this was pretty helpful.

But this code doesn't work for me: actually, GetPixel returns {0,0,0} color.
Change this
  public UnsafeBitmap(Bitmap bitmap)
  {
 	 this.bitmap = new Bitmap(bitmap);
  }


to this to avoid the problem
  public UnsafeBitmap(Bitmap bitmap)
  {
 	 this.bitmap = new Bitmap(bitmap);
  }


Was This Post Helpful? 0

Page 1 of 1