0

The following picture shows what happens when we convert a 24-bit color image of size 1x2.

enter image description here

.

The following picture shows what happens when we convert a a 32-bit color image of size 1x2.

enter image description here

I thought, 24-bit image will occupy 6-bytes. But, both are taking 8-bytes.

As a result, my C# code is failing. Coz, it assumes that a pixel needs (ColorDepth/8)*Width*Height number of bytes.

    public static int[,] ToInteger(Bitmap bitmap)
    {
        BitmapLocker locker = new BitmapLocker(bitmap);

        locker.Lock();

        byte[] data = locker.ImageData;
        int Width = locker.Width;
        int Height = locker.Height;
        int noOfBytesPerPixel = locker.BytesPerPixel;
        int[,] integerImage = new int[Width, Height];
        int byteCounter = 0;

        for (int i = 0; i < Width; i++)
        {
            for (int j = 0; j < Height; j++)
            {
                int integer = BitConverter.ToInt32(data, byteCounter);

                integerImage[i, j] = integer;

                byteCounter += noOfBytesPerPixel;
            }
        }

        locker.Unlock();

        return integerImage;
    }

So, what is going on really?

user366312
  • 16,949
  • 65
  • 235
  • 452
  • Maybe its memory alignment: https://en.wikipedia.org/wiki/Data_structure_alignment – Kfir Guy Apr 16 '17 at 08:51
  • 1
    Look into [stride](http://stackoverflow.com/questions/24595836/size-of-bitmap-byte-differs-from-bmp-memorystream-size/24595963#24595963)! – TaW Apr 16 '17 at 10:56

1 Answers1

1

Why are images occupying the same number of bytes ?

We can't tell for sure since you didn't show how you're acquiring them (maybe they get promoted to 32bpp by default which is the fastest to process, like in WriteableBitmapEx for instance ?)

The proper formula to compute bytes per pixel:

bytesPerPixel = (bitsPerPixel + 7) / 8

Here's an example that will convert whatever that is from 8 to 32 bpp to int:

private static void DoWork(Bitmap bitmap)
{
    var width = bitmap.Width;
    var height = bitmap.Height;
    var rectangle = new Rectangle(0, 0, width, height);
    var data = bitmap.LockBits(rectangle, ImageLockMode.ReadOnly, bitmap.PixelFormat);

    var bitsPerPixel = GetBitsPerPixel(bitmap.PixelFormat);
    var bytesPerPixel = (bitsPerPixel + 7) / 8;
    var stride = data.Stride;
    var length = stride * data.Height;
    var pixels = new byte[length];
    Marshal.Copy(data.Scan0, pixels, 0, length);

    for (var y = 0; y < height; y++)
    for (var x = 0; x < width; x++)
    {
        var offset = y * stride + x * bytesPerPixel;
        var value = 0;
        for (var i = 0; i < bytesPerPixel; i++)
            value |= pixels[offset + i] << i;
    }
    bitmap.UnlockBits(data);
}

private static int GetBitsPerPixel(PixelFormat format)
{
    switch (format)
    {
        case PixelFormat.Format8bppIndexed:
            return 1;
        case PixelFormat.Format16bppRgb555:
            return 2;
        case PixelFormat.Format24bppRgb:
            return 24;
        case PixelFormat.Format32bppRgb:
            return 32;
        default: // TODO
            throw new NotSupportedException();
    }
}

(not sure about the usefulness, though)

Note: I've 'emulated' what was necessary since I didn't use BitmapLocker class as you did.

aybe
  • 15,516
  • 9
  • 57
  • 105
  • what about monochrome and 4-bit images? – user366312 Apr 17 '17 at 09:59
  • Can you be more precise ? – aybe Apr 17 '17 at 16:12
  • this source code can't handle 1-bit monochrome image and 4-bit/16-color images. – user366312 Apr 17 '17 at 16:29
  • http://i.imgur.com/F0uxRKk.png This is a monochrome image. – user366312 Apr 17 '17 at 16:31
  • http://i.imgur.com/TeTupcN.png This is a 4-bit(16-color) image. – user366312 Apr 17 '17 at 16:32
  • You should update your question and clearly explain what you're looking for, because it's unclear for me :) Are you looking for a code that converts any depth to `int` ? etc ... – aybe Apr 18 '17 at 20:58
  • There is a perfectly valid `Image.GetPixelFormatSize()` to get the accurate amount of bits for a `PixelFormat`. As for converting an image to 32bpp, I find that a very easy general method is to just make a new 32bpp image object, open its `Graphics`, and simply _paint the other image on it_. – Nyerguds Sep 05 '17 at 14:37