Azar Shaikh
Azar Shaikh

Reputation: 449

c# RGB Values from Bitmap Data

I am new in working with Bitmap and using 16 bits per pixel Format16bppRgb555;

I want to Extract RGB Values from Bitmap Data. Here is my code

static void Main(string[] args)
    {

        BitmapRGBValues();
        Console.ReadKey();
    }


 static unsafe void BitmapRGBValues()
    {

        Bitmap cur = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height, PixelFormat.Format16bppRgb555);
        //Capture Screen
        var screenBounds = Screen.PrimaryScreen.Bounds;
        using (var gfxScreenshot = Graphics.FromImage(cur))
        {
            gfxScreenshot.CopyFromScreen(screenBounds.X, screenBounds.Y, 0, 0, screenBounds.Size, CopyPixelOperation.SourceCopy);
        }

        var curBitmapData = cur.LockBits(new Rectangle(0, 0, cur.Width, cur.Height),
                                 ImageLockMode.ReadWrite, PixelFormat.Format16bppRgb555);


        try
        {
            byte* scan0 = (byte*)curBitmapData.Scan0.ToPointer();

            for (int y = 0; y < cur.Height; ++y)
            {
                ulong* curRow = (ulong*)(scan0 + curBitmapData.Stride * y);

                for (int x = 0; x < curBitmapData.Stride / 8; ++x)
                {

                    ulong pixel = curRow[x];

                    //How to get RGB Values  from pixel;







                }

            }


        }
        catch
        {

        }
        finally
        {
            cur.UnlockBits(curBitmapData);

        }


    }

Upvotes: 3

Views: 5190

Answers (1)

Nyerguds
Nyerguds

Reputation: 5639

LockBits can actually convert your image to a desired pixel format, meaning no further conversion should be needed. Just lock the image as Format32bppArgb and you can simply take your colour values from single bytes.

BitmapData curBitmapData = cur.LockBits(new Rectangle(0, 0, cur.Width, cur.Height),
    ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
Int32 stride = curBitmapData.Stride;
Byte[] data = new Byte[stride * cur.Height];
Marshal.Copy(curBitmapData.Scan0, data, 0, data.Length);
cur.UnlockBits(curBitmapData);

With this code, you end up with the byte array data, which is filled with your image data in ARGB format, meaning the colour component bytes will be in there in the order [B, G, R, A]. Note that the stride is the amount of bytes to skip to get to a next line on the image, and since this is not always equal to "width * bytes per pixel", it should always be taken into account.

Now you got that, you can do whatever you want with it...

Int32 curRowOffs = 0;
for (Int32 y = 0; y < cur.Height; y++)
{
    // Set offset to start of current row
    Int32 curOffs = curRowOffs;
    for (Int32 x = 0; x < cur.Width; x++)
    {
        // ARGB = bytes [B,G,R,A]
        Byte b = data[curOffs];
        Byte g = data[curOffs + 1];
        Byte r = data[curOffs + 2];
        Byte a = data[curOffs + 3];
        Color col = Color.FromArgb(a, r, g, b);

        // Do whatever you want with your colour here
        // ...

        // Increase offset to next colour
        curOffs += 4;
    }
    // Increase row offset
    curRowOffs += stride;
}

You can even edit the bytes, and then build a new image from them if you want.

Upvotes: 7

Related Questions