klijo
klijo

Reputation: 16461

C# print pixel value

I have a 8 bit bitmap color image. when i do a

Color pixelcolor = b.GetPixel(j,i);    
Console.Write(pixelcolor.ToString() + " " );

I get

 Color [A=255, R=255, G=255, B=255]

I need to get only the 8 bit value. not 24 bit seperate values for R,G,B ,A.

Upvotes: 3

Views: 3177

Answers (4)

vidstige
vidstige

Reputation: 13085

There is no way to do this using the Bitmap class directly. However, you can use the LockBits method to access the pixels directly.

Using unsafe code: (remember to enable unsafe code in your project first)

public static unsafe Byte GetIndexedPixel(Bitmap b, Int32 x, Int32 y)
{
    if (b.PixelFormat != PixelFormat.Format8bppIndexed) throw new ArgumentException("Image is not in 8 bit per pixel indexed format!");
    if (x < 0 || x >= b.Width) throw new ArgumentOutOfRangeException("x", string.Format("x should be in 0-{0}", b.Width));
    if (y < 0 || y >= b.Height) throw new ArgumentOutOfRangeException("y", string.Format("y should be in 0-{0}", b.Height));
    BitmapData data = b.LockBits(new Rectangle(0, 0, b.Width, b.Height), ImageLockMode.ReadOnly, b.PixelFormat);
    try
    {
        Byte* scan0 = (Byte*)data.Scan0;
        return scan0[x + y * data.Stride];
    }
    finally
    {
        if (data != null) b.UnlockBits(data);
    }
}

The safe alternative, using Marshal.Copy:

public static Byte GetIndexedPixel(Bitmap b, Int32 x, Int32 y)
{
    if (b.PixelFormat != PixelFormat.Format8bppIndexed) throw new ArgumentException("Image is not in 8 bit per pixel indexed format!");
    if (x < 0 || x >= b.Width) throw new ArgumentOutOfRangeException("x", string.Format("x should be in 0-{0}", b.Width));
    if (y < 0 || y >= b.Height) throw new ArgumentOutOfRangeException("y", string.Format("y should be in 0-{0}", b.Height));
    BitmapData data = b.LockBits(new Rectangle(0, 0, b.Width, b.Height), ImageLockMode.ReadOnly, b.PixelFormat);
    try
    {
        Byte[] pixel = new Byte[1];
        Marshal.Copy(new IntPtr(data.Scan0.ToInt64() + x + y * data.Stride), pixel, 0, 1);
        return pixel[0];
    }
    finally
    {
        if (data != null) b.UnlockBits(data);
    }
}

Upvotes: 5

Pedro77
Pedro77

Reputation: 5294

If you don't want to use LockBits, you can do this:

Warning: This method only works if the palette does not have duplicated values and if it is not changed by another thread after pixelRGB is set.

/// <summary>
/// Gets the pixel value in bytes. Uses Bitmap GetPixel method.
/// </summary>
/// <param name="bmp">Bitmap</param>
/// <param name="location">Pixel location</param>
/// <returns>Pixel value</returns>
public static byte Get8bppImagePixel(Bitmap bmp, Point location)
{
    Color pixelRGB = bmp.GetPixel(location.X, location.Y);
    int pixel8bpp = Array.IndexOf(bmp.Palette.Entries, pixelRGB);
    return (byte)pixel8bpp;
}

Upvotes: -1

Guffa
Guffa

Reputation: 700730

The methods in the Bitmap class doesn't let you get the palette index directly.

You can get the palette for the image using the Palette property, and look for the color there, but that's a bit of a workaround.

To get the palette index directly, you would use the LockBits method to get access to the image data directly. You would either have to use marshalling to copy the data into an array, or use pointers in unsafe mode to access it.


The A property in a Color value is the Alpha component. It can have the value 0 to 255, where 0 is fully transparent and 255 is fully solid.

Upvotes: 1

Tigran
Tigran

Reputation: 62265

The values you want are actually R, G and B, which are 8bit bitmap values of corresponding Red, Green and Blue components of the color.

A is a Alfa coponent, the transparency value of the color. If you don't care about it, just don't show it in string output.

Upvotes: -1

Related Questions