[英]How to convert ISampleGrabber::BufferCB's buffer to a bitmap
I am trying to use the ISampleGrabberCB::BufferCB
to convert the current frame to bitmap using the following code: 我正在尝试使用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;
}
However this does not seem to be working. 但是,这似乎不起作用。
Additionally it seems to call this function when i press a button which runs the following code: 另外,当我按下运行以下代码的按钮时,似乎会调用此函数:
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;
}
Once this code is ran I get a message box which shows 'Works' thus meaning my BufferCB
must of been called however does not update my picture box with the current image. 一旦运行了此代码,我将得到一个显示“ Works”的消息框,这意味着必须调用BufferCB
,但是不会使用当前图像更新我的图片框。
Is the BufferCB
not called after every new frame? 是否在每个新帧之后都不调用BufferCB
? If so why do I not recieve the 'Works' message box? 如果是这样,为什么我没有收到“ Works”消息框?
Finally is it possible to convert every new frame into a bitmap (this is used for later processing) using BufferCB
and if so how? 最后,可以使用BufferCB
将每个新帧转换成一个位图(用于以后的处理),如果可以,怎么办?
Edited code: 编辑代码:
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;
}
Button code: 按钮代码:
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;
}
I also still need to press the button to run the BufferCB
我还需要按一下按钮才能运行BufferCB
Thanks for reading. 谢谢阅读。
BufferCB
is called for every new frame that has been captured by the camera. 相机已捕获的每个新帧都会调用BufferCB
。 You don't see the message box, because the method is called from another thread (not the ui thread). 您不会看到消息框,因为该方法是从另一个线程(不是ui线程)调用的。 See this question for details. 有关详细信息,请参见此问题 。
In my code I used AutoResetEvent
for capturing a frame: 在我的代码中,我使用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;
}
The image can then be decoded from the IntPtr
with another function: 然后可以使用另一个函数从IntPtr
解码图像:
public Image Decode (IntPtr data)
{
var bitmap = new Bitmap (_width, _height, _stride, PixelFormat.Format24bppRgb, data);
bitmap.RotateFlip (RotateFlipType.RotateNoneFlipY);
return bitmap;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.