0

I'm writing a simple OpenCV application using .NET which the goal is to render the webcam stream on a simple window.

Here's the code I use to do this:

private static BitmapSource ToBitmapSource(IImage image)
{
    using (System.Drawing.Bitmap source = image.Bitmap)
    {
        IntPtr ptr = source.GetHbitmap();
        BitmapSource bs = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
            ptr,
            IntPtr.Zero,
            Int32Rect.Empty,
            System.Windows.Media.Imaging.BitmapSizeOptions.FromEmptyOptions());
        DeleteObject(ptr);
        return bs;
    }
}

private void CameraShow()
{
    ImageViewer viewer = new Emgu.CV.UI.ImageViewer(); //create an image viewer
    Capture capture = new Capture(); //create a camera captue

    this.isCamOff = false;
    while (this.CamStat != eCamRun.CamStop)
    {
        Thread.Sleep(60);
        viewer.Image = capture.QueryFrame(); //draw the image obtained from camera
        System.Windows.Application.Current.Dispatcher.Invoke(
            DispatcherPriority.Normal,
            (ThreadStart)delegate
        {
            this.ImageStream.Source = ToBitmapSource(viewer.Image); //BitmapSource
        });
    }

    viewer.Dispose();
    capture.Dispose();
    this.isCamOff = true;
    Thread.CurrentThread.Interrupt();
}

But now I want to display on the console the content of the pixel buffer contained into the System.Drawing.Bitmap object (I know the void* native type is contained into the IntPtr variable into the Bitmap object). So according to my source code just below to recover the IntPtr variable I have to write the following line of code (into an 'unsafe' context):

IntPtr buffer = viewer.Image.Bitmap.GetHbitmap();

byte[] pPixelBuffer = new byte[16]; //16 bytes allocation
Marshal.Copy(buffer, pPixelBuffer, 0, 9); //I copy the 9 first bytes into pPixelBuffer

Unfortunately, I have an Access Violation Exception into the method 'Copy'! And I don't understand why.

Does anyone can help me, please ?

Thanks a lot in advance for your help.

Jeru Luke
  • 20,118
  • 13
  • 80
  • 87
user1364743
  • 5,283
  • 6
  • 51
  • 90

2 Answers2

0

You can cast an IntPtr to void* in an unsafe context. Sou you can do this:

unsafe
{
    var bytePtr = (byte*)(void*)buffer;

    // Here use *bytePtr to get the byte value at bytePtr, just like in C/C++
}
Lucas Trzesniewski
  • 50,214
  • 11
  • 107
  • 158
  • @AlexD Not when your pointer points to a resource acquired from a native API. The GC can only relocate .NET objects, and `fixed` prevents just that. Native objects won't move in memory. – Lucas Trzesniewski Jul 04 '14 at 21:44
  • You are explaining me I can't print the frame video buffer because EMGU use a native API ? So it's normal if the Visual Studio debugger shows me that my 'ptr' pointer is an invalid pointer? And so I can't print its content ? – user1364743 Jul 04 '14 at 23:56
  • @user1364743 I'm not saying anything like that. My comment was a response to a previous comment that got deleted. I don't know emgu, but as long as the `IntPtr` is not zero, it points to some data, and you should be able to read that data with the method of the answer. If your buffer points to the video frame, you should be able to read it. – Lucas Trzesniewski Jul 05 '14 at 00:01
0

How about using Marshal.Copy? With this, you can copy the contents of the IntPtr to an byte[] all without going into unsafe

http://msdn.microsoft.com/en-us/library/ms146631(v=vs.110).aspx

Mike Hixson
  • 5,071
  • 1
  • 19
  • 24