【问题标题】:Get size of a buffer in C#在 C# 中获取缓冲区的大小
【发布时间】:2016-10-04 02:24:49
【问题描述】:

我有一个 C++/CLI dll,其中一种方法需要一个指针及其缓冲区大小作为其参数。

C++/CLI

  • Param1:BufferPtr = 指向缓冲区开头的指针。
  • Param2:BufferSize = 缓冲区大小。

// Example..
uint LoadImageFromMemory(const unsigned char * const  BufferPtr, const int BufferSize);

C#

Bitmap Img = Bitmap.FromFile(@"C:/my.jpg") as Bitmap;
.
.
// Convert the 'Img' to byte* pointer.
byte[] TempByte = new byte[TempStorage.Height * TempStorage.Width * 3];
byte[] ActualByte = null;

System.Drawing.Imaging.BitmapData m_pImageData = null;

// Converting Bitmap to Byte array...
try
{
     m_pImageData = TempStorage.LockBits(new Rectangle(0, 0, TempStorage.Width, TempStorage.Height),
                                             System.Drawing.Imaging.ImageLockMode.ReadWrite,
                                             System.Drawing.Imaging.PixelFormat.Format24bppRgb);

     System.IntPtr pScan = m_pImageData.Scan0; // 5
     int nStride = m_pImageData.Stride;// 6
     ActualByte = new byte[m_pImageData.Height * m_pImageData.Width * 3];

     unsafe
     {
          byte* pBuffer = (byte*)(void*)pScan;// 7

          int noffset = nStride - TempStorage.Width * 3;

          int count = 0;
          for (int nY = 0; nY < TempStorage.Height; nY++)
          {
               for (int nX = 0; nX < TempStorage.Width; nX++)
               {

                    ActualByte[count] = pBuffer[0];
                    ActualByte[count + 1] = pBuffer[1];
                    ActualByte[count + 2] = pBuffer[2];
                    count += 3;
                    pBuffer += 3;
               }
               pBuffer += noffset;
            }
        }
    }
finally
{
     if (m_pImageData != null)
     {
         TempStorage.UnlockBits(m_pImageData);
     }
}

.
.
// At the end... 
.
.
fixed (byte* ptrAdd = ActualByte)
{
                  // this second parameter ( below ) is problematic...
    rst = CppAPI.LoadImageFromMemory(ptrAdd, ?????);
}

如何获取缓冲区大小?

由于我不知道缓冲区大小在这里的确切含义,我尝试将这些值传递给第二个参数,即疯狂猜测。

  • 实际字节长度,
  • 此“my.jpg”图片的步幅
  • int 形式的地址值(愚蠢的猜测!

不幸的是,它们都不起作用。

我在 C# 中有图像、它的位图对象和它的指针。这些还不足以获取缓冲区大小吗?

【问题讨论】:

  • 你如何将'Img'转换为字节指针*?
  • @KenWhite 更新了ActualByte 的制作方式。
  • 如果您已将ActualByte 分配给byte* ptrAdd,那么您可以传递的唯一可能的有效值是ActualByte.Length。你说过你已经尝试过了,并且说当然,它们都不起作用。但是,您还没有解释它们是如何工作的。当您说它们都不起作用时,具体是什么意思?它以什么方式不起作用
  • @KenWhite DLL 抛出图像格式未知。我认为这与第二个参数有关——但仔细想想,转换可能是罪魁祸首。
  • @KenWhite 我找到了解决方案!你让我觉得从 Bitmap 对象制作字节数组可能是错误的工作——谢谢。

标签: c# pointers


【解决方案1】:

在我阅读了 Ken White 提到的 cmets 之后,我想到转换工作本身可能首先是错误的。

所以我把下面这段代码去掉了

try
{
     m_pImageData = TempStorage.LockBits(new Rectangle(0, 0, TempStorage.Width, TempStorage.Height),
                                             System.Drawing.Imaging.ImageLockMode.ReadWrite,
                                             System.Drawing.Imaging.PixelFormat.Format24bppRgb);

     System.IntPtr pScan = m_pImageData.Scan0; // 5
     int nStride = m_pImageData.Stride;// 6
     ActualByte = new byte[m_pImageData.Height * m_pImageData.Width * 3];

     unsafe
     {
          byte* pBuffer = (byte*)(void*)pScan;// 7

          int noffset = nStride - TempStorage.Width * 3;

          int count = 0;
          for (int nY = 0; nY < TempStorage.Height; nY++)
          {
               for (int nX = 0; nX < TempStorage.Width; nX++)
               {

                    ActualByte[count] = pBuffer[0];
                    ActualByte[count + 1] = pBuffer[1];
                    ActualByte[count + 2] = pBuffer[2];
                    count += 3;
                    pBuffer += 3;
               }
               pBuffer += noffset;
            }
        }
    }
finally
{
     if (m_pImageData != null)
     {
         TempStorage.UnlockBits(m_pImageData);
     }
}

并决定改用MemoryStream

using (MemoryStream ms = new MemoryStream())
{
    Img.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
    ActualByte = ms.ToArray();
}

它现在工作正常,第二个参数值应该是字节数组长度,正如 Ken White 在他的评论中所说。

// This should be...
CppAPI.LoadImageFromMemory(ptrAdd, ?????);

// Like this..
CppAPI.LoadImageFromMemory(ptrAdd, ActualByte.length);

【讨论】:

    【解决方案2】:

    您将数组定义为字节数组,因此它与您定义的一样大。 m_pImageData.Height * m_pImageData.Width * 3 字节长。

    【讨论】: