Search code examples
c#exceptionimage-processingbitmapbitmapdata

Bitmap to Integer routine generating exception


    public static bool IsGrayscale(Bitmap bitmap)
    {
        return bitmap.PixelFormat == PixelFormat.Format8bppIndexed ? true : false;
    }

.

    public static int[,] ToInteger(Bitmap image)
    {
        if (Grayscale.IsGrayscale(image))
        {
            Bitmap bitmap = (Bitmap)image.Clone();

            int[,] array2d = new int[bitmap.Width, bitmap.Height];

            BitmapData bitmapData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height),
                                                     ImageLockMode.ReadWrite,
                                                     PixelFormat.Format8bppIndexed);
            int bytesPerPixel = sizeof(byte);

            unsafe
            {
                byte* address = (byte*)bitmapData.Scan0;

                int paddingOffset = bitmapData.Stride - (bitmap.Width * bytesPerPixel);

                for (int i = 0; i < bitmap.Width; i++)
                {
                    for (int j = 0; j < bitmap.Height; j++)
                    {
                        int iii = 0;

                        //If there are more than 1 channels...
                        //(Would actually never occur)
                        if (bytesPerPixel >= sizeof(int))
                        {
                            byte[] temp = new byte[bytesPerPixel];

                            //Handling the channels.
                            //PixelFormat.Format8bppIndexed == 1 channel == 1 bytesPerPixel == byte
                            //PixelFormat.Format32bpp       == 4 channel == 4 bytesPerPixel == int
                            for (int k = 0; k < bytesPerPixel; k++)
                            {
                                temp[k] = address[k];
                            }

                            iii = BitConverter.ToInt32(temp, 0);
                        }
                        else//If there is only one channel:
                        {
                            iii = (int)(*address);
                        }

                        array2d[i, j] = iii;

                        address += bytesPerPixel;
                    }

                    address += paddingOffset;
                }
            }

            bitmap.UnlockBits(bitmapData);

            return array2d;
        }
        else
        {
            throw new Exception("Not a grayscale");
        }
    }

The exception in the following line:

 iii = (int)(*address);

An unhandled exception of type 'System.AccessViolationException' occurred in Fast Fourier Transform.exe

Additional information: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.

enter image description here

What is the cause of that exception?

How can I fix that?

.

.

P.S. I am using the following PNG image:

enter image description here


Solution

  • You have mistaken bitmap.Width for bitmap.Height in your loops. You should iterate over the height in the outer loop and over the width in the inner loop, as the stride represents the whole width + the offset of the image. Then you can add padding on a line basis, instead for each line traversed. So

    for (int i = 0; i < bitmap.Height; i++)
    {
        for (int j = 0; j < bitmap.Width; j++)
        {
    

    is working. Also, you must swap the array access from array2d[i, j] = iii to array2d[j, i] = iii as the indices are now belonging to the other dimension of the image