0

**

How to make 'GetPixel2' work for finding the color at a point

** So I have a bitmap with lots of single colored shapes. I have a list of x,y points for those shapes. Then, a second list with the expected color at those points.

Finally have an algorithm using bitmap.Getpixel and SetPixel working. Which was definitely slow. http://csharpexamples.com/fast-image-processing-c/ Suggests using direct memory access to solve this. I'd like to use their sample without looping through the entire image, and hit a single x,y point.

Bitmap bmp2 = (Bitmap)Bitmap.FromFile(Environment.CurrentDirectory + @"\Content\map\provinces.bmp");
BitmapData bitmapData = bmp2.LockBits(new System.Drawing.Rectangle(0, 0, bmp2.Width, bmp2.Height), ImageLockMode.ReadWrite, bmp2.PixelFormat);
int bytesPerPixel = System.Drawing.Bitmap.GetPixelFormatSize(bmp2.PixelFormat) / 8;
int heightInPixels = bitmapData.Height;
int widthInBytes = bitmapData.Width * bytesPerPixel;
System.Drawing.Point pt = new System.Drawing.Point((int)provpos2[0].X, (int)provpos2[0].Y);
System.Drawing.Color targetColor = System.Drawing.Color.FromArgb(255, provcolors[0].R, provcolors[0].G, provcolors[0].B);
if (!ColorMatch(GetPixel2(pt.X, pt.Y, bytesPerPixel, bitmapData), targetColor)){ 
    // This hits the completely wrong area.
}


public System.Drawing.Color GetPixel2(int x, int y, int bytesPerPixel, BitmapData bitmapData)
{
    unsafe
    {
        byte* ptrFirstPixel = (byte*)bitmapData.Scan0;
        byte* currentLine = ptrFirstPixel + (y * bitmapData.Stride);
        x = x + bytesPerPixel;
        System.Drawing.Color a = System.Drawing.Color.FromArgb(255, currentLine[x + 2], currentLine[x + 1], currentLine[x]);

        return a;
    }
}

public static bool ColorMatch(System.Drawing.Color a,System.Drawing.Color b)
{

    return (a.ToArgb() & 0xffffff) == (b.ToArgb() & 0xffffff);
}

bytesPerPixel comes out at 3. Tried changing it to 4 just hits another undesired location on the bitmap.

  • It seems to hit around 1023x,351y instead of the desired 3084x,319y on a 5632x2048 bitmap.
Jordan
  • 19
  • 5

1 Answers1

0

Not entirely sure why it doesnt workout fo you, but keep in mind this:

Bits per pixel comes from colour format used there are a few formats some are handier then others, and sometimes you need to convert them to a strict RGB format. ea 8 bits per colour channel, there also exists RGBA, and there is RGB in bitwise 565 notation as used in some camera's, and there is 24bits per colour. Some formats are not supported in winforms, but are supported in wpf based applications, like 16bit gray formats. (since wpf is more new age like design friendly)

maybe try this it works great for me: http://www.codeproject.com/Tips/240428/Work-with-bitmap-faster-with-Csharp?msg=5136670

if its 565 maybe do something like

     private Bitmap Convert565bppTo24bpp(Bitmap ConvertMe)
     {
       Bitmap clone = new Bitmap(ConvertMe.Width, ConvertMe.Height, System.Drawing.Imaging.PixelFormat.Format24bppRgb);//.Format32bppPArgb);
       using (Graphics gr = Graphics.FromImage(clone)) 
        { gr.DrawImage(ConvertMe, new Rectangle(0, 0, clone.Width, clone.Height)); }
        return clone;
     }
Peter
  • 2,043
  • 1
  • 21
  • 45
  • clicked wrongly i intended to put it as a comment to your question. ohwell maybe this reads better. – Peter Dec 11 '15 at 10:56
  • Amazingly spot on! Exactly what I was looking for, thanks! – Jordan Dec 11 '15 at 11:17
  • Actually using the Convert565 method or the class in the link, seem to produce slower results and an out of memory crash after about 500 entries. The originals pixelformat is already in 24bppRgb. – Jordan Dec 11 '15 at 11:39
  • ehm if its not 565 then you dont need to use that function either i think. But are you sure the source input is 24bppRgb ?. The code was part of something i used in the past, had improved it later using a diffrent method which worked faster, need to lookback to find newer version. – Peter Dec 11 '15 at 12:33
  • If it is for a camera be sure to dispose images when ready as otherwise they could fill memory and indeed crash after several frames. ea pseudo code camera_frame_update >> update picturebox(frame) >> dispose(frame) Visualstudio 2015, might detect such forgotten dispose actions. – Peter Dec 11 '15 at 12:44