【问题标题】:OpenTK Getting pixels byte array from a BitmapOpenTK 从位图中获取像素字节数组
【发布时间】:2014-11-02 19:40:09
【问题描述】:

我需要将一些 OpenGL 代码移植到 C# OpenTK。 这是我从 C++ 中的像素数组更新映射 PBO 的块:

    GLubyte* ptr = (GLubyte*)glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY);
    if(ptr)
    {

        memcpy(ptr,imageInfo.Data,IMG_DATA_SIZE);
        glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);  

    }

我需要在 OpenTK 中做同样的事情。我的图像数据来自 Bitmap 的一个实例。 我尝试了以下方法:

        IntPtr ptr = GL.MapBuffer(BufferTarget.PixelUnpackBuffer, BufferAccess.WriteOnly);
        if(ptr != IntPtr.Zero)
       {
           BitmapData data = updateColorMap.LockBits(new System.Drawing.Rectangle(0, 0, updateColorMap.Width, updateColorMap.Height),
                 ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
                 Marshal.Copy(data.Scan0, 0, ptr, IMG_DATA_SIZE);
       }

但是 Marshal.Copy 要求第一个参数是 byte[] 类型。我没有找到如何从 BitmapData 中检索它。它只返回 IntPtr (data.Scan0)。

那么如何从 Bitmap 中获取字节数组呢?

更新:

与此同时,我从 OpenTK 论坛获得了帮助,他们提议改为这样做:

           unsafe
            {
                GL.BufferData(BufferTarget.PixelUnpackBuffer, new IntPtr(IMG_DATA_SIZE), IntPtr.Zero, BufferUsageHint.StreamDraw);
                byte* ptr = (byte*)GL.MapBuffer(BufferTarget.PixelUnpackBuffer, BufferAccess.WriteOnly);


                if (ptr != null)
                {
                    BitmapData data = updateDepthMap.LockBits(new System.Drawing.Rectangle(0, 0, updateDepthMap.Width, updateDepthMap.Height),
                    ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);

                    byte* scan0 = (byte*)data.Scan0.ToPointer();
                    for (int i = 0; i < IMG_DATA_SIZE; ++i)
                    {

                        *ptr = *scan0;
                        ++ptr;
                        ++scan0;
                    }

                    updateDepthMap.UnlockBits(data);
                    GL.UnmapBuffer(BufferTarget.PixelUnpackBuffer);

                }
            }//unsafe

现在,这可行,但它非常慢!常规纹理更新的运行速度比这快 2 倍,即 错误,因为异步 PBO 传输应该加快纹理上传。在我的 C++ 版本中,PBO 上传确实会导致几乎 2 倍的性能提升。

【问题讨论】:

  • 使用 IntPtr 应该没问题,否则我遗漏了一些东西,但也有 stackoverflow.com/questions/5298930/…
  • 不正确,会导致编译错误。第一个参数需要 byte[] 而不是 IntPtr

标签: c# opengl opentk


【解决方案1】:

好的,解决方案在这里:Copy data from from IntPtr to IntPtr

在 linux 上测试。

【讨论】:

  • 缓冲区超出范围。但我仔细检查了所有缓冲区的大小。
  • 尝试将第一个 IntPtr 设置为这样的数组:'Marshal.Copy(new IntPtr[]{data.Scan0},0, ptr, IMG_DATA_SIZE);'所有像素上的循环非常慢,正常....
  • 我试过了,这不是我猜的。但是请看这里:stackoverflow.com/questions/15975972/…,如果您对 pinvoke 没有任何意见,它应该可以很好地解决您的问题。
  • 我以为 Marshal.copy 会将 IntPtr 数组内容连接到目标 IntPtr,但我错了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-23
  • 2016-05-18
  • 2012-06-07
  • 2013-05-08
  • 2016-09-20
相关资源
最近更新 更多