1

I am trying to convert an array of integers in to a bitmap. I have an array of integers in range [0 - 4095] and I want to display them in to a bitmap, than have the user pick an area in the bitmap make a copy of that area and then get the integers back.

I have code that works for cutting the area of the bitmap, but I am having problems with making the bitmap with values as high as 4095, and getting values back from the bitmap as high as 4095.

public Bitmap InttoBitmap(int[] array)
{
    unsafe
    {
        int[] pixels = new int[array.Length];
        for (int i = 0; i < keepWidth * keepHeight; i++)
        {
            pixels[i] = array[i] * 64;
        }
        IntPtr pixptr = Marshal.AllocHGlobal(keepWidth * keepHeight * 2);
        Marshal.Copy(pixels, 0, pixptr, keepWidth * keepHeight);
        Bitmap bitmap = new Bitmap(keepWidth, keepHeight, 2 * keepWidth, System.Drawing.Imaging.PixelFormat.Format16bppGrayScale, pixptr);

        return bitmap;
    }
}

I get a run time error at:

Marshal.Copy(pixels, 0, pixptr, keepWidth * keepHeight);

it says:

System.AccessViolationException: 'Attempted to read or write protected memory. This is often an indication that other memory is corrupt.'

update:

 double Average_intensity2(Bitmap bmp)
    {

        double[,] image;
        double answer = 0;
        image = imageToByteArray(bmp);
        double l = 0;

        for (int y = 0; y < bmp.Height; y++)
        {
            for (int x = 0; x < bmp.Width; x++)
            {
                answer = answer + image[y,x];

                l++;
            }
        }
        answer = answer / l;
        return answer;
    }
Axel
  • 29
  • 7
  • It looks like you want to work with the bitmap data directly. Are you locking/unlocking the bitmap? You do realize that an `int` is 32-bits while a 16bpp is a `ushort` right? – Ron Beyer Jun 18 '19 at 18:26
  • 1
    I don't understand what you think that code is going to do. Are you trying to create an image file? Display something in a UI? WinForm? UWP? A web page. I suggest starting with a graphics book or tutorial. – Dour High Arch Jun 18 '19 at 18:28
  • Possible duplicate of [How to Convert 2-D array into Image in c#](https://stackoverflow.com/questions/5113919/how-to-convert-2-d-array-into-image-in-c-sharp) – Joelius Jun 18 '19 at 18:32
  • You use `Format16bppGrayScale`, which doesn't work in .Net. If it's indeed a grayscale image, you could just shift it down, show a simplified 8bpp gray image for selecting the area, and then just look up the corresponding chunk in your original data. – Nyerguds Jul 06 '19 at 13:25

1 Answers1

2

This answer should correct the System.AccessViolationException being thrown.

Marshal.AllocHGlobal takes the size in bytes.

Allocates memory from the unmanaged memory of the process by using the specified number of bytes.

Let's say that keepWidth = 10 and keepHeight = 10.

You would need to allocate enough space for 10 * 10 = 100 32-bit integers, which would be 10 * 10 * 4 = 400 bytes.

But, you're only allocating 10 * 10 * 2 = 200 bytes. Then, you're trying to copy 100 32-bit integers (400 bytes) into that 200 byte space.

This example will go from an int[] where each item in the array represents a single, RGB pixel in a bitmap. Then it will take the Bitmap and go back to an int[] containing the pixel data.

I'm no expert on this, not by a long shot. I used TheCodeKing's answer from this question to figure out how to get the pixel data from the Bitmap (the BitmapToInts function).

using System;
using System.Drawing;
using System.Runtime.InteropServices;

namespace Example
{
   class Program
   {
      static void Main(string[] args)
      {
         IntPtr bitmapData = IntPtr.Zero; //Declaring it here and passing it to IntsToBitmap because it needs to be freed.
         try
         {
            int[] pixels = new int[32 * 32]; //32x32 bitmap.
            for (int i = 0; i < pixels.Length; i++)
            {
               pixels[i] = 4080;
            }
            var bmp = IntsToBitmap(pixels, 32, 32, out bitmapData);
            //bmp.Save("SomefilePath") //If you want to see the bitmap.
            var bmpPixels = BitmapToInts(bmp, 0, 0, 32, 32);
            bmp.Dispose();
         }
         finally
         {
            if (bitmapData != IntPtr.Zero)
            {
               Marshal.FreeHGlobal(bitmapData);
            }
         }
      }

      static int[] BitmapToInts(Bitmap bitmap, int x, int y, int width, int height)
      {
         var bitmapData = bitmap.LockBits(
            new Rectangle(x, y, width, height), 
            System.Drawing.Imaging.ImageLockMode.ReadOnly, 
            bitmap.PixelFormat);
         var lengthInBytes = bitmapData.Stride * bitmapData.Height;

         int[] pixels = new int[lengthInBytes / 4];
         Marshal.Copy(bitmapData.Scan0, pixels, 0, pixels.Length);
         bitmap.UnlockBits(bitmapData);
         return pixels;
      }

      static Bitmap IntsToBitmap(int[] pixels, int width, int height, out IntPtr bitmapData)
      {
         bitmapData = Marshal.AllocHGlobal(width * height * 4);
         Marshal.Copy(pixels, 0, bitmapData, pixels.Length);
         return new Bitmap(width, height, 4 * width, System.Drawing.Imaging.PixelFormat.Format32bppArgb, bitmapData);
      }
   }
}
Joshua Robinson
  • 3,399
  • 7
  • 22
  • wait is not working. sorry about that. I did not get any errors, so I thought it was. but when I cover my camera the video should turn black, but it is not. The values coming in are 0s, but the bitmap is still white. so that means it us not working. – Axel Jun 18 '19 at 19:51
  • If you're using `PixelFormat.Format32bppArgb` then a value of 0 will be transparent. You need to use 0xFF000000 (-16777216) to get a black pixel. Or use `PixelFormat.Format32bppRgb`. – Joshua Robinson Jun 18 '19 at 20:58
  • ok so that turned my 4080 Value in to a blue color. however, I can cover the camera and get black. but when I convert the bitmap back in to a integer value, I get 85, which I think is blue. I am new to this, but can you store a number greater than 255, in a bitmap ? because so far nothing I have tried seem to work. – Axel Jun 18 '19 at 21:53
  • I'm afraid I'm no expert either, but as long as the PixelFormat is more than 8 bits per pixel, I don't see why not. It doesn't seem like your code which takes the `Bitmap` to an `int[]` has been posted? I've added an example that does the whole round trip, and the ints I get back from the `Bitmap` are all 4080. Hopefully it helps. – Joshua Robinson Jun 18 '19 at 22:35
  • I added the code for my bitmap to double [] conversion – Axel Jun 19 '19 at 03:06