简体   繁体   中英

Creating 1bppIndexed image, trouble with stride and accessviolationexception

How can I put values into array of image? Actually I cannot do it in whole array due to bmpData.Stride. The size of bytes storing values should be around 100, actually is 40.

I get accessviolationexception while using System.Runtime.InteropServices.Marshal.Copy .

I was using in code example from MSDN Library - Bitmap.LockBits Method (Rectangle, ImageLockMode, PixelFormat)

Why I cannot write something like that?

// Declare an array to hold the bytes of the bitmap.
        int bytes = Math.Abs(bmpData.Width) * b.Height;

My whole code is:

        //Create new bitmap 10x10 = 100 pixels
        Bitmap b = new Bitmap(10, 10, System.Drawing.Imaging.PixelFormat.Format1bppIndexed);

        Rectangle rect = new Rectangle(0, 0, b.Width, b.Height);
        System.Drawing.Imaging.BitmapData bmpData =
            b.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite,
            b.PixelFormat);

        // Get the address of the first line.
        IntPtr ptr = bmpData.Scan0;

        // Declare an array to hold the bytes of the bitmap.
        int bytes = Math.Abs(bmpData.Stride) * b.Height;//error if bmpData.Width
        byte[] rgbValues = new byte[bytes];

        // Copy the RGB values into the array.
        System.Runtime.InteropServices.Marshal.Copy(ptr, rgbValues, 0, bytes);

        //Create random constructor
        Random r = new Random();

        //Generate dots in random cells and show image
        for (int i = 0; i < bmpData.Height; i++)
        {
            for (int j = 0; j < b.Width; j++)
            {
                rgbValues[i + j] = (byte)r.Next(0, 2);
            }
        }

        // Copy back values into the array.
        System.Runtime.InteropServices.Marshal.Copy(rgbValues, 0, ptr, bytes);

        // Unlock the bits.
        b.UnlockBits(bmpData);

        // Draw the modified image.
        pictureBox1.Image = (Image)b;

Format1bppIndexed means that there is one bit per pixel, not byte. Also, BMP format requires that each row begins on a four-byte boundary. This is where 40 comes from:

  1. [10-pixel row] x [1 bit per pixel] = 10 bits = 2 bytes.
  2. Row size should be a multiple of 4, so 4 - 2 = 2 bytes will be appended to each row.
  3. [10 rows] x [4 bytes per row] = 40 bytes.

To generate a random 1bpp image, you should rewrite the loop like this:

// Generate dots in random cells and show image
for (int i = 0; i < bmpData.Height; i++)
{
    for (int j = 0; j < bmpData.Width; j += 8)
    {
        rgbValues[i * bmpData.Stride + j / 8] = (byte)r.Next(0, 256);
    }
}

Or just use the Random.NextBytes method instead of the loop:

r.NextBytes(rgbValues);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM