【问题标题】:Multiple pointers to another arrays from one Bitmap从一个位图中指向另一个数组的多个指针
【发布时间】:2019-10-20 10:05:04
【问题描述】:

我有一种使用Marshal.CopyBitmap 复制到byte 数组的方法:

    public byte[][] PrepareTestSamples(Bitmap bitmap, int imageCount, out BitmapData bitmapData)
    {
        bitmapData = bitmap.LockBits(
            new Rectangle(0, 0, bitmap.Width, bitmap.Height),
            ImageLockMode.ReadWrite,
            bitmap.PixelFormat);

        int pixelsCount = bitmapData.Stride * bitmap.Height;
        byte[][] images = new byte[imageCount * 3][];

        for (int i = 0; i < imageCount * 3; i++)
        {
            images[i] = new byte[pixelsCount];
            Marshal.Copy(bitmapData.Scan0, images[i], 0, pixelsCount);
        }

        return images;
    }

而且这段代码运行良好。我可以将图像复制到字节数组imageCount * 3 次。

然后我使用这个数组来测试我的算法。任何算法的定义都是这样的:

    byte[] Execute(byte[] pixels, int stride, int height, int width);

在执行算法后,我会返回新的byte[] 并更改像素。然后我再次使用Lockbits 将其复制回新的Bitmap

var bmp = new Bitmap(bitmap.Width, bitmap.Height);
BitmapData bmpData = bmp.LockBits(
           new Rectangle(0, 0, bmp.Width, bmp.Height),
           ImageLockMode.ReadWrite,
           bitmap.PixelFormat);

        Marshal.Copy(images[1], 0, bmpData.Scan0, images[1].Length);
        bmp.UnlockBits(bmpData);

我想使用pointers 测试我的程序。我想检查一下,在这种情况下指针是否会比托管内存快。

我认为,任何算法的定义都必须改为:

byte[] Execute(byte* pixels, int stride, int height, int width);

但我有疑问,如何将BitmapData 复制到指针数组之类的东西?如何将imagesCount * 3图像存储为指针并将pointer一一传递给方法?

【问题讨论】:

  • 创建一个包含步幅、高度、宽度和像素的结构。之前的像素还包括数组计数。这使得创建项目数组变得容易。然后你有一个 bitmapData[] 数组。
  • 这是有道理的。我是否可以访问存储在BitmapData 数组中的每个BitmapData 的指针?你说的是逻辑吗?我需要制作(例如)30 个BitmapData,将其打包到array,然后在每次算法迭代中分别访问每个?

标签: c# image pointers bitmap marshalling


【解决方案1】:

你的代码看起来像这样

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;

namespace ConsoleApplication1
{
    class Program
    {
        public struct BitmapData
        {
            public int stride { get; set; }
            public int height { get; set; }
            public int width { get; set; }
            public long length { get; set; }
            public byte[] pixels { get; set; } 
        }
        public class ManagedBitmapData
        {
            public int stride { get; set; }
            public int height { get; set; }
            public int width { get; set; }
            public long length { get; set; }
            public byte[] pixels { get; set; }
        }

        static void Main(string[] args)
        {
            //source data
            List<ManagedBitmapData> managedData = new List<ManagedBitmapData>();
            IntPtr[] UnmanagedData = new IntPtr[managedData.Count];
            BitmapData[] bitMaps = new BitmapData[managedData.Count];
            for (int i = 0; i < managedData.Count; i++)
            {
                bitMaps[i] = new BitmapData();
                bitMaps[i].stride = managedData[i].stride;
                bitMaps[i].height = managedData[i].height;
                bitMaps[i].width = managedData[i].width;
                bitMaps[i].length = managedData[i].length;
                bitMaps[i].pixels = managedData[i].pixels;
                Marshal.StructureToPtr(bitMaps[i], UnmanagedData[i], true);
            }
        }
    }
}

【讨论】:

  • 您好,感谢您的回答! Lockbits 和解锁位呢?你为什么不做Lockbits?您能否提供一些代码说明,您在做什么以及您在做什么?
  • 像 data[][] 这样的双点实际上是一个指针数组,其中每个指针指向一个已知大小的内存块的起始地址。因此,当将数据传递给 c++ 方法时,data[][] 等价于 IntPrt[] UnmanagedData。因此,要将数据传递给 c++,您需要将每个托管内存对象 (managedData) 复制到非托管空间 (bitMaps)。然后将非托管内存块的 IntPtr(数据起始地址)传递给 c++。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-23
  • 2020-07-02
  • 1970-01-01
  • 1970-01-01
  • 2012-08-14
相关资源
最近更新 更多