将int数组转换为位图

时间:2019-06-18 18:20:44

标签: c# bitmap

我正在尝试将整数数组转换为位图。我有一个范围为[0-4095]的整数数组,我想将它们显示在位图中,而不是让用户在位图中选择一个区域来制作该区域的副本,然后取回整数。

我有一些用于剪切位图区域的代码,但是我在制作值高达4095的位图以及从位图获取高达4095的值时遇到了问题。

dcast(test, id ~ class)

我在以下位置遇到运行时错误:

dput(test)
structure(list(class = c("foo", "bar", "baz", "baz", "bar", "foo", 
"foo", "foo", "foo"), id = c(1, 1, 1, 2, 2, 2, 3, 3, 3)), row.names = c(NA, 
-9L), class = "data.frame")

它说:

  

System.AccessViolationException:'试图读取或写入受保护的内存。这通常表明其他内存已损坏。'

更新:

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;
    }
}

1 个答案:

答案 0 :(得分:1)

此答案应更正抛出的System.AccessViolationException

Marshal.AllocHGlobal takes the size in bytes.

  

使用指定的字节数从进程的非托管内存中分配内存。

让我们说keepWidth = 10keepHeight = 10

您需要为10 * 10 = 100个32位整数分配足够的空间,该整数将为10 * 10 * 4 = 400个字节。

但是,您仅分配10 * 10 * 2 = 200个字节。然后,您尝试将100个32位整数(400个字节)复制到该200个字节的空间中。

此示例将从int[]开始,其中数组中的每个项目代表位图中的单个RGB像素。然后将使用Bitmap,然后返回到包含像素数据的int[]

我不是这个专家,不是很远。我使用了this question的TheCodeKing答案来弄清楚如何从BitmapBitmapToInts函数)获取像素数据。

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);
      }
   }
}