Closed orionkubilay closed 4 years ago
I haven't worked with WinForms in a long time, but the basic idea will be to get the image data in a MemoryStream and load it into a Bitmap
instance which can then be used by a PictureBox. Does the below help at all? I haven't tested this code but it should hopefully put you in the right direction.
private async void Form1_Load(object sender, EventArgs e)
{
MMALCameraConfig.StillResolution = new Resolution(640, 480);
MMALCamera cam = MMALCamera.Instance;
using (var imgCaptureHandler = new MemoryStreamCaptureHandler())
using (var imgEncoder = new MMALImageEncoder())
using (var nullSink = new MMALNullSinkComponent())
{
cam.ConfigureCameraSettings();
var portConfig = new MMALPortConfig(MMALEncoding.JPEG, MMALEncoding.I420, quality: 90);
// Create our component pipeline.
imgEncoder.ConfigureOutputPort(portConfig, imgCaptureHandler);
cam.Camera.StillPort.ConnectTo(imgEncoder);
cam.Camera.PreviewPort.ConnectTo(nullSink);
// Camera warm up time
await Task.Delay(2000);
await cam.ProcessAsync(cam.Camera.StillPort);
using (var bitmap = Bitmap.FromStream(imgCaptureHandler.CurrentStream))
{
var pictureBox = new PictureBox()
{
Width = 640,
Height = 480,
Image = (Image)bitmap
};
// Do something with your picturebox...
}
}
}
Thanks for quick reply.
MMALCameraConfig.StillResolution = new Resolution(640, 480); line give me "StillResolution not found" error message. I ve changed that line to MMALCameraConfig.Resolution = new Resolution(640, 480); Ok this is working for still image. How can I do this for video? I think I have to use callbacks. How can I do that? I am newbye MMALSharp. Thanks in advace.
Ah sorry, yes, I assumed you were using the current version in NuGet (v0.6) - that property has been changed recently in the latest development branch.
Yes, so with processing video to a PictureBox I think you should be able to construct your own capture handler which accepts a delegate and do the processing in there. In the below example I'm using the rapid capture functionality documented here which will pass a JPEG to the delegate on each full frame processed. Again, not tested but hopefully will point you in the right direction:
public class PictureBoxInMemoryCaptureHandler : InMemoryCaptureHandler, IVideoCaptureHandler
{
private Action<byte[]> _callback;
public PictureBoxInMemoryCaptureHandler(Action<byte[]> callback)
{
_callback = callback;
}
public override void Process(ImageContext context)
{
// The InMemoryCaptureHandler parent class has a property called "WorkingData".
// It is your responsibility to look after the clearing of this property.
// The "eos" parameter indicates whether the MMAL buffer has an EOS parameter, if so, the data that's currently
// stored in the "WorkingData" property plus the data found in the "data" parameter indicates you have a full image frame.
Console.WriteLine("I'm in here");
base.Process(context);
if (context.Eos)
{
_callback(this.WorkingData.ToArray());
this.WorkingData.Clear();
Console.WriteLine("I have a full frame. Clearing working data.");
}
}
public void Split()
{
throw new NotImplementedException();
}
}
private void ProcessFrameCallback(byte[] callbackData)
{
using (var ms = new MemoryStream(callbackData))
using (var bitmap = Bitmap.FromStream(ms))
{
var pictureBox = new PictureBox()
{
Width = 640,
Height = 480,
Image = (Image)bitmap
};
// Do something with your picturebox...
}
}
private async void Form1_Load(object sender, EventArgs e)
{
MMALCameraConfig.Resolution = new Resolution(640, 480);
MMALCamera cam = MMALCamera.Instance;
using (var imgCaptureHandler = new PictureBoxInMemoryCaptureHandler(this.ProcessFrameCallback))
using (var splitter = new MMALSplitterComponent())
using (var imgEncoder = new MMALImageEncoder(continuousCapture: true))
using (var nullSink = new MMALNullSinkComponent())
{
cam.ConfigureCameraSettings();
var portConfig = new MMALPortConfig(MMALEncoding.JPEG, MMALEncoding.I420, quality: 90);
// Create our component pipeline.
imgEncoder.ConfigureOutputPort(portConfig, imgCaptureHandler);
cam.Camera.VideoPort.ConnectTo(splitter);
splitter.Outputs[0].ConnectTo(imgEncoder);
cam.Camera.PreviewPort.ConnectTo(nullSink);
// Camera warm up time
await Task.Delay(2000);
var cts = new CancellationTokenSource(TimeSpan.FromSeconds(15));
// Process images for 15 seconds.
await cam.ProcessAsync(cam.Camera.VideoPort, cts.Token);
}
}
Thanks for help. ProcessFrameCallback routine creats new picturebox for every frame. But want to render over a picturebox on Windows form. So I changed this routine as below.
private void ProcessFrameCallback(byte[] callbackData) { using (var ms = new MemoryStream(callbackData)) using (var bitmap = Bitmap.FromStream(ms)) { var g = Graphics.FromImage(pictureBox1.Image); g.DrawImage(bitmap, new PointF(0, 0)); pictureBox1.Refresh(); } }
This is enought for my startup. Thanks again.
I want to try prewiev on a picturebox. How can I do this?