如何将 ISampleGrabber::BufferCB 的缓冲区转换为位图

本文关键字:缓冲区 转换 位图 BufferCB ISampleGrabber | 更新日期: 2023-09-27 18:37:12

我正在尝试使用以下代码使用ISampleGrabberCB::BufferCB将当前帧转换为位图:

int ISampleGrabberCB.BufferCB(double sampleTime, IntPtr buffer, int bufferLength)
    {
        try
        {
            Form1 form1 = new Form1("", "", "");
            if (pictureReady == null)
            {
                Debug.Assert(bufferLength == Math.Abs(pitch) * videoHeight, "Wrong Buffer Length");
            }
            Debug.Assert(imageBuffer != IntPtr.Zero, "Remove Buffer");
            Bitmap bitmapOfCurrentFrame = new Bitmap(width, height, capturePitch, PixelFormat.Format24bppRgb, buffer);
            MessageBox.Show("Works");
            form1.changepicturebox3(bitmapOfCurrentFrame);
            pictureReady.Set();
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.ToString());
        }
        return 0;
    }

然而,这似乎不起作用。

此外,当我按下运行以下代码的按钮时,它似乎调用了这个函数:

public IntPtr getFrame()
    {
        int hr;
        try
        {
            pictureReady.Reset();
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.ToString());
        }
        imageBuffer = Marshal.AllocCoTaskMem(Math.Abs(pitch) * videoHeight);
        try
        {
            gotFrame = true;
            if (videoControl != null)
            {
                hr = videoControl.SetMode(stillPin, VideoControlFlags.Trigger);
                DsError.ThrowExceptionForHR(hr);
            }
            if (!pictureReady.WaitOne(9000, false))
            {
                throw new Exception("Timeout waiting to get picture");
            }
        }
        catch
        {
            Marshal.FreeCoTaskMem(imageBuffer);
            imageBuffer = IntPtr.Zero;
        }
        return imageBuffer;
    }

运行此代码后,我会收到一个消息框,显示"Works",这意味着我的BufferCB必须被调用,但不会使用当前图像更新我的图片框。

BufferCB不是在每个新帧之后调用的吗?如果是这样,为什么我没有收到"作品"消息框?

最后,是否可以使用 BufferCB 将每个新帧转换为位图(用于以后的处理),如果是,如何?

编辑的代码:

int ISampleGrabberCB.BufferCB(double sampleTime, IntPtr buffer, int bufferLength)
    {           
            Debug.Assert(bufferLength == Math.Abs(pitch) * videoHeight, "Wrong Buffer Length"); 
            Debug.Assert(imageBuffer != IntPtr.Zero, "Remove Buffer");
            CopyMemory(imageBuffer, buffer, bufferLength);
            Decode(buffer);   

        return 0;
    }
public Image Decode(IntPtr imageData)
    {
        var bitmap = new Bitmap(width, height, pitch, PixelFormat.Format24bppRgb, imageBuffer);
        bitmap.RotateFlip(RotateFlipType.RotateNoneFlipY);
        Form1 form1 = new Form1("", "", "");
        form1.changepicturebox3(bitmap);
        bitmap.Save("C:''Users''...''Desktop''A2 Project''barcode.jpg");
        return bitmap;
    }

按钮代码:

public void getFrameFromWebcam()
{
   if (iPtr != IntPtr.Zero)
   {
       Marshal.FreeCoTaskMem(iPtr);
       iPtr = IntPtr.Zero;
   }
        //Get Image
        iPtr = sampleGrabberCallBack.getFrame();
        Bitmap bitmapOfFrame = new Bitmap(sampleGrabberCallBack.width, sampleGrabberCallBack.height, sampleGrabberCallBack.capturePitch, PixelFormat.Format24bppRgb, iPtr);
        bitmapOfFrame.RotateFlip(RotateFlipType.RotateNoneFlipY);
        barcodeReader(bitmapOfFrame);
}
public IntPtr getFrame()
    {
        int hr;
        try
        {
            pictureReady.Reset();
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.ToString());
        }
        imageBuffer = Marshal.AllocCoTaskMem(Math.Abs(pitch) * videoHeight);
        try
        {
            gotFrame = true;
            if (videoControl != null)
            {
                hr = videoControl.SetMode(stillPin, VideoControlFlags.Trigger);
                DsError.ThrowExceptionForHR(hr);
            }
            if (!pictureReady.WaitOne(9000, false))
            {
                throw new Exception("Timeout waiting to get picture");
            }
        }
        catch
        {
            Marshal.FreeCoTaskMem(imageBuffer);
            imageBuffer = IntPtr.Zero;
        }
        return imageBuffer;
    }

我还需要按下按钮才能运行BufferCB

感谢您的阅读。

如何将 ISampleGrabber::BufferCB 的缓冲区转换为位图

BufferCB 为相机捕获的每个新帧调用。您看不到消息框,因为该方法是从另一个线程(而不是 ui 线程)调用的。有关详细信息,请参阅此问题。

在我的代码中,我使用 AutoResetEvent 来捕获帧:

#region samplegrabber
/// <summary>
///   buffer callback, COULD BE FROM FOREIGN THREAD.
/// </summary>
int ISampleGrabberCB.BufferCB (double sampleTime,
                              IntPtr pBuffer,
                              int bufferLen)
{
  if (_sampleRequest)
  {
    _sampleRequest = false;
    if (bufferLen > _bufferSize)
      throw new Exception ("buffer is wrong size");
    Win32.CopyMemory (_buffer, pBuffer, _bufferSize);
    // Picture is ready.
    _resetEvent.Set ();
  }
  else
    _dropped++;
  return 0;
}

然后可以使用另一个功能从IntPtr解码图像:

public Image Decode (IntPtr data)
{
  var bitmap = new Bitmap (_width, _height, _stride, PixelFormat.Format24bppRgb, data);
  bitmap.RotateFlip (RotateFlipType.RotateNoneFlipY);
  return bitmap;
}