1

I am trying to create a bitmap from an array of pixels.

var height = 2;
var width = 2;
var output = new byte[4] { 0, 0, 0, 0 };
var gcHandle = GCHandle.Alloc(output, GCHandleType.Pinned);

var stride = width * sizeof(byte);
var pointer = gcHandle.AddrOfPinnedObject();
using (var bitmap = new Bitmap(width, height, stride, PixelFormat.Format8bppIndexed, pointer))
{
}

However I get System.ArgumentException: 'Parameter is not valid.', with no inner exception or further details.

I don't want to use SetPixel because my real array is very large.

This is using the System.Drawing.Common 4.5.0 library for .Net Standard 2.0

1
  • 1
    You have to understand the bitmap format to get this right, 8bpp is painful due to its need for a palette and stride. Just do it the other way around to make it easier, use new Bitmap(int, int, PixelFormat) and then LockBits to poke the values into it. And do keep in mind that everybody and his brother gave up on 8bpp with a big sigh of relieve 20 years ago. More than plenty of oomph available today to afford the much faster 32bpp. Which lets you ignore palette and stride. Commented Sep 21, 2018 at 8:19

1 Answer 1

1

You could do something like this maybe:

unsafe public static void Main()
{
   var height = 2;
   var width = 2;
   var output = new byte[4] { 1, 2, 3, 4};
   using (var bitmap = new Bitmap(width, height, PixelFormat.Format8bppIndexed))
   {
      var data = bitmap.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadWrite, PixelFormat.Format8bppIndexed);
      Marshal.Copy(data.Scan0, output, 0, 4);
      bitmap.UnlockBits(data);
      bitmap.Save(@"D:\blah.bmp");
   }
}

Bitmap.LockBits Method

Bitmap.LockBits Method

Locks a Bitmap into system memory.

Marshal.Copy Method

Copies data from a managed array to an unmanaged memory pointer, or from an unmanaged memory pointer to a managed array.


As noted just work in the 32bpp, and make your life easier

public static void Main()
{
   var height = 2;
   var width = 2;
   var c = Color.White.ToArgb();
   var output = new int[4] { c, c, c, c };
   using (var bitmap = new Bitmap(width, height, PixelFormat.Format8bppIndexed))
   {
      var data = bitmap.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadWrite, PixelFormat.Format32bppPArgb);

      Marshal.Copy(output, 0, data.Scan0, 4);
      bitmap.UnlockBits(data);
      bitmap.Save(@"D:\trdy.bmp");
   }
}
Sign up to request clarification or add additional context in comments.

1 Comment

If you use Marshal.Copy, the method does not need to be marked as unsafe. Do note that you have to copy line by line or the stride will be messed up, since the internals of an object in .Net will always have a stride divisible by 4 bytes.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.