0

My problem is that I need to convert an image to a byte array to obtain its pixels.

My image size is 268x188 and when I use the property PixelsFormat it returns Format24bppRgb, so I understand that each pixel contains 3 bytes.

If this is true, the size of the pixels should be 268*188*3 = 151152 bytes, but the byte array that I am creating has a size of 4906 bytes, which is the size of the image file in my computer.

I don´t know if there is another way to obtain these pixels or you can only obtain image file size.

froggy_
  • 43
  • 1
  • 10

3 Answers3

1

If you want to ignore the header and the compression of the file you can do the following.

var path = ...
using(var image = Image.FromFile(path))
using(var bitmap = new Bitmap(image))
{
    var bitmapData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadOnly, bitmap.PixelFormat);

    var bytesPerPixel = 4; // bitmapData.PixelFormat (image.PixelFormat and bitmapData.PixelFormat can be different)
    var ptr = bitmapData.Scan0;
    var imageSize = bitmapData.Width * bitmapData.Height * bytesPerPixel;
    var data = new byte[imageSize];
    for (int x = 0; x < imageSize; x += bytesPerPixel)
    {
        for(var y = 0; y < bytesPerPixel; y++)
        {
            data[x + y] = Marshal.ReadByte(ptr);
            ptr += 1;
        }
    }

    bitmap.UnlockBits(bitmapData);
}
NtFreX
  • 10,379
  • 2
  • 43
  • 63
  • Probably cleanest answer thus far but if this is as simple as it gets then it is a shame on the API designers. – lijat Sep 11 '19 at 06:07
0

To get image pixel try this:

public static byte[] GetImageRaw(Bitmap image)
{
    if (image == null)
    {
        throw new ArgumentNullException(nameof(image));
    }

    if (image.PixelFormat != PixelFormat.Format24bppRgb)
    {
        throw new NotSupportedException("Invalid pixel format.");
    }

    const int PixelSize = 3;

    var data = image.LockBits(
        new Rectangle(Point.Empty, image.Size),
        ImageLockMode.ReadWrite,
        image.PixelFormat);

    try
    {
        var bytes = new byte[data.Width * data.Height * PixelSize];

        for (var y = 0; y < data.Height; ++y)
        {
            var source = (IntPtr)((long)data.Scan0 + y * data.Stride);

            // copy row without padding
            Marshal.Copy(source, bytes, y * data.Width * PixelSize, data.Width * PixelSize);
        }

        return bytes;
    }
    finally
    {
        image.UnlockBits(data);
    }
}

Take a look at Bitmap.LockBits

Alessandro D'Andria
  • 8,663
  • 2
  • 36
  • 32
-1

I use this code in ASP.NET application. Very simple:

var imagePath = GetFilePathToYourImage();

 using (var img = System.IO.File.OpenRead(imagePath))
 {
        var imageBytes = new byte[img.Length];
        img.Read(imageBytes, 0, (int)img.Length);
 }
koviroli
  • 1,422
  • 1
  • 15
  • 27
  • Or maybe even just `var imageBytes = System.IO.File.ReadAllBytes(GetFilePathToYourImage());` – Corak Sep 14 '18 at 07:52
  • 1
    @FernandodelCastillo-Olivares - it probably *worked*, but not in a way you expect. The `byte[]` you get is still the compressed bytes. It seems like what you want is more like this: https://stackoverflow.com/a/24383391/1336590 – Corak Sep 14 '18 at 08:05