L
Leung a7 biu
Guest
Hello all,
I have successfully use directshow to preview and record an image from webcam, but the problem is when I used the application from the tablet, the orientation is not the same as what I saw in PC. Is there a possibility to rotate this preview image? I can rotate the bitmap image taken from the preview before it is saved, but if I can show the correct orientation in the preview , that would be very helpful for me.
I have read through some of the suggestion liked using igraphbuilder, render file and etc.... but since I am not an very experienced VB.net developer, I have a very hard time to understand all these concept. I spend many many days just to find out different code to make the camera capture works. But now came across the orientation problem.
This is what the code looks like and if anyone can help to add some filter so that I can preview the image in a 90 degree view.
Many many thanks to all of you.
Imports DirectShowLib
Imports System
Imports System.Diagnostics
Imports System.Drawing
Imports System.Drawing.Imaging
Imports System.Runtime.InteropServices
Imports System.Windows.Forms
Imports System.Runtime.InteropServices.ComTypes
Public Class Form2
Dim MyPicturesFolder As String = Environment.GetFolderPath(Environment.SpecialFolder.MyPictures)
Dim D As Integer = &H8000
Dim D As Integer = Convert.ToInt32("0X8000", 16)
Public WM_GRAPHNOTIFY As Integer = D + 1
Dim VideoWindow As IVideoWindow = Nothing
Dim MediaControl As IMediaControl = Nothing
Dim MediaEventEx As IMediaEventEx = Nothing
Dim GraphBuilder As IGraphBuilder = Nothing
Dim CaptureGraphBuilder As ICaptureGraphBuilder2 = Nothing
Enum PlayState
Stopped
Paused
Running
Init
End Enum
Dim CurrentState As PlayState = PlayState.Stopped
Dim rot As DsROTEntry = Nothing
Private Sub Form1_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs)
closeinterfaces()
End Sub
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
CaptureVideo()
PictureBox1.Visible = True
End Sub
Private Sub CaptureVideo()
Dim hr As Integer = 0
Dim sourceFilter As IBaseFilter = Nothing
Try
GetInterfaces()
hr = CaptureGraphBuilder.SetFiltergraph(GraphBuilder) Specifies filter graph "graphbuilder" for the capture graph builder "captureGraphBuilder" to use.
sourceFilter = FindCaptureDevice()
hr = GraphBuilder.AddFilter(sourceFilter, "Video Capture")
hr = CaptureGraphBuilder.RenderStream(PinCategory.Preview, MediaType.Video, sourceFilter, Nothing, Nothing)
Marshal.ReleaseComObject(sourceFilter)
SetupVideoWindow()
rot = New DsROTEntry(GraphBuilder)
hr = MediaControl.Run()
CurrentState = PlayState.Running
Catch ex As Exception
MessageBox.Show("An unrecoverable error has occurred.With error : " & ex.ToString)
End Try
End Sub
Private Sub GetInterfaces()
Dim hr As Integer = 0
GraphBuilder = CType(New FilterGraph, IGraphBuilder)
CaptureGraphBuilder = CType(New CaptureGraphBuilder2, ICaptureGraphBuilder2)
MediaControl = CType(GraphBuilder, IMediaControl)
VideoWindow = CType(GraphBuilder, IVideoWindow)
MediaEventEx = CType(GraphBuilder, IMediaEventEx)
hr = MediaEventEx.SetNotifyWindow(Me.Handle, WM_GRAPHNOTIFY, IntPtr.Zero) This method designates a window as the recipient of messages generated by or sent to the current DirectShow object
End Sub
Public Function FindCaptureDevice() As IBaseFilter
Dim hr As Integer = 0
Dim classEnum As IEnumMoniker = Nothing
Dim moniker As IMoniker() = New IMoniker(0) {}
Dim source As Object = Nothing
Dim devEnum As ICreateDevEnum = CType(New CreateDevEnum, ICreateDevEnum)
hr = devEnum.CreateClassEnumerator(FilterCategory.VideoInputDevice, classEnum, 0)
Marshal.ReleaseComObject(devEnum)
If classEnum Is Nothing Then
Throw New ApplicationException("No video capture device was detected.\r\n\r\n" & _
"This sample requires a video capture device, such as a USB WebCam,\r\n" & _
"to be installed and working properly. The sample will now close.")
End If
If classEnum.Next(moniker.Length, moniker, IntPtr.Zero) = 0 Then
Dim iid As Guid = GetType(IBaseFilter).GUID
moniker(0).BindToObject(Nothing, Nothing, iid, source)
Else
Throw New ApplicationException("Unable to access video capture device!")
End If
Marshal.ReleaseComObject(moniker(0))
Marshal.ReleaseComObject(classEnum)
Return CType(source, IBaseFilter)
End Function
Public Sub SetupVideoWindow()
Dim hr As Integer = 0
set the video window to be a child of the main window
putowner : Sets the owning parent window for the video playback window.
hr = VideoWindow.put_Owner(PictureBox1.Handle) Me.Handle)
PictureBox1.Visible = False
hr = VideoWindow.put_WindowStyle(WindowStyle.Child Or WindowStyle.ClipChildren)
Use helper function to position video window in client rect of main application window
ResizeVideoWindow()
Make the video window visible, now that it is properly positioned
put_visible : This method changes the visibility of the video window.
hr = VideoWindow.put_Visible(OABool.True)
End Sub
Public Sub ResizeVideoWindow()
Resize the video preview window to match owner window size
left , top , width , height
If Not (VideoWindow Is Nothing) Then if the videopreview is not nothing
VideoWindow.SetWindowPosition(0, 0, Me.Width, Me.ClientSize.Height)
End If
End Sub
Public Sub closeinterfaces()
//stop previewing data
If Not (Me.MediaControl Is Nothing) Then
Me.MediaControl.StopWhenReady()
End If
Me.CurrentState = PlayState.Stopped
//stop recieving events
If Not (Me.MediaEventEx Is Nothing) Then
Me.MediaEventEx.SetNotifyWindow(IntPtr.Zero, WM_GRAPHNOTIFY, IntPtr.Zero)
End If
// Relinquish ownership (IMPORTANT!) of the video window.
// Failing to call put_Owner can lead to assert failures within
// the video renderer, as it still assumes that it has a valid
// parent window.
If Not (Me.VideoWindow Is Nothing) Then
Me.VideoWindow.put_Visible(OABool.False)
Me.VideoWindow.put_Owner(IntPtr.Zero)
End If
// Remove filter graph from the running object table
If Not (rot Is Nothing) Then
rot.Dispose()
rot = Nothing
End If
// Release DirectShow interfaces
Marshal.ReleaseComObject(Me.MediaControl) : Me.MediaControl = Nothing
Marshal.ReleaseComObject(Me.MediaEventEx) : Me.MediaEventEx = Nothing
Marshal.ReleaseComObject(Me.VideoWindow) : Me.VideoWindow = Nothing
Marshal.ReleaseComObject(Me.GraphBuilder) : Me.GraphBuilder = Nothing
Marshal.ReleaseComObject(Me.CaptureGraphBuilder) : Me.CaptureGraphBuilder = Nothing
End Sub
Private Sub btnGrab_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnGrab.Click
GrabImage()
End Sub
Public Sub GrabImage()
Get image from clipboard and convert it to a bitmap
Try
MediaControl.Pause()
Clipboard.SetImage(PictureBox1.Image)
If Clipboard.ContainsImage Then
PictureBox2.Image = Clipboard.GetImage()
End If
Catch
End Try
Try
MediaControl.Pause()
Dim bmp As New Bitmap(PictureBox1.Width, PictureBox1.Height)
Using g As Graphics = Graphics.FromImage(bmp)
Dim pt As Point = PictureBox1.PointToScreen(New Point(0, 0))
g.CopyFromScreen(pt.X, pt.Y, 0, 0, bmp.Size)
End Using
PictureBox2.Image = bmp
PictureBox2.Visible = True
PictureBox1.Visible = False
Catch
MsgBox("error")
End Try
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click, btnGrab.Click
MediaControl.Run()
End Sub
Private Sub btnSave_Click(sender As System.Object, e As System.EventArgs) Handles BtnSave.Click
Dim newimage As Image = PictureBox2.Image
Dim gr As Graphics = Graphics.FromImage(newimage)
Dim myFontLabels As New Font("Arial", 40)
Dim myBrushLabels As New SolidBrush(Color.Black)
Dim FolderBrowser As New FolderBrowserDialog
If FolderBrowser.ShowDialog = Windows.Forms.DialogResult.OK Then
Me.lblPath.Text = FolderBrowser.SelectedPath & "\Amytest.bmp"
MsgBox("msg" & Me.lblPath.Text)
End If
newimage.Save(Me.lblPath.Text, ImageFormat.Jpeg)
MsgBox("The picture has been successfully copied and saved")
End Sub
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
Dim newimage As Image = PictureBox2.Image
Dim gr As Graphics = Graphics.FromImage(newimage)
Dim myFontLabels As New Font("Arial", 40)
Dim myBrushLabels As New SolidBrush(Color.Black)
Dim _sourcefilename$ = Me.lblPath.Text
Dim _destinationfilename$ = "C:\test.jpg"
JpegSaveClass.SaveImage(_sourcefilename, _destinationfilename)
End Sub
End Class
Continue reading...
I have successfully use directshow to preview and record an image from webcam, but the problem is when I used the application from the tablet, the orientation is not the same as what I saw in PC. Is there a possibility to rotate this preview image? I can rotate the bitmap image taken from the preview before it is saved, but if I can show the correct orientation in the preview , that would be very helpful for me.
I have read through some of the suggestion liked using igraphbuilder, render file and etc.... but since I am not an very experienced VB.net developer, I have a very hard time to understand all these concept. I spend many many days just to find out different code to make the camera capture works. But now came across the orientation problem.
This is what the code looks like and if anyone can help to add some filter so that I can preview the image in a 90 degree view.
Many many thanks to all of you.
Imports DirectShowLib
Imports System
Imports System.Diagnostics
Imports System.Drawing
Imports System.Drawing.Imaging
Imports System.Runtime.InteropServices
Imports System.Windows.Forms
Imports System.Runtime.InteropServices.ComTypes
Public Class Form2
Dim MyPicturesFolder As String = Environment.GetFolderPath(Environment.SpecialFolder.MyPictures)
Dim D As Integer = &H8000
Dim D As Integer = Convert.ToInt32("0X8000", 16)
Public WM_GRAPHNOTIFY As Integer = D + 1
Dim VideoWindow As IVideoWindow = Nothing
Dim MediaControl As IMediaControl = Nothing
Dim MediaEventEx As IMediaEventEx = Nothing
Dim GraphBuilder As IGraphBuilder = Nothing
Dim CaptureGraphBuilder As ICaptureGraphBuilder2 = Nothing
Enum PlayState
Stopped
Paused
Running
Init
End Enum
Dim CurrentState As PlayState = PlayState.Stopped
Dim rot As DsROTEntry = Nothing
Private Sub Form1_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs)
closeinterfaces()
End Sub
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
CaptureVideo()
PictureBox1.Visible = True
End Sub
Private Sub CaptureVideo()
Dim hr As Integer = 0
Dim sourceFilter As IBaseFilter = Nothing
Try
GetInterfaces()
hr = CaptureGraphBuilder.SetFiltergraph(GraphBuilder) Specifies filter graph "graphbuilder" for the capture graph builder "captureGraphBuilder" to use.
sourceFilter = FindCaptureDevice()
hr = GraphBuilder.AddFilter(sourceFilter, "Video Capture")
hr = CaptureGraphBuilder.RenderStream(PinCategory.Preview, MediaType.Video, sourceFilter, Nothing, Nothing)
Marshal.ReleaseComObject(sourceFilter)
SetupVideoWindow()
rot = New DsROTEntry(GraphBuilder)
hr = MediaControl.Run()
CurrentState = PlayState.Running
Catch ex As Exception
MessageBox.Show("An unrecoverable error has occurred.With error : " & ex.ToString)
End Try
End Sub
Private Sub GetInterfaces()
Dim hr As Integer = 0
GraphBuilder = CType(New FilterGraph, IGraphBuilder)
CaptureGraphBuilder = CType(New CaptureGraphBuilder2, ICaptureGraphBuilder2)
MediaControl = CType(GraphBuilder, IMediaControl)
VideoWindow = CType(GraphBuilder, IVideoWindow)
MediaEventEx = CType(GraphBuilder, IMediaEventEx)
hr = MediaEventEx.SetNotifyWindow(Me.Handle, WM_GRAPHNOTIFY, IntPtr.Zero) This method designates a window as the recipient of messages generated by or sent to the current DirectShow object
End Sub
Public Function FindCaptureDevice() As IBaseFilter
Dim hr As Integer = 0
Dim classEnum As IEnumMoniker = Nothing
Dim moniker As IMoniker() = New IMoniker(0) {}
Dim source As Object = Nothing
Dim devEnum As ICreateDevEnum = CType(New CreateDevEnum, ICreateDevEnum)
hr = devEnum.CreateClassEnumerator(FilterCategory.VideoInputDevice, classEnum, 0)
Marshal.ReleaseComObject(devEnum)
If classEnum Is Nothing Then
Throw New ApplicationException("No video capture device was detected.\r\n\r\n" & _
"This sample requires a video capture device, such as a USB WebCam,\r\n" & _
"to be installed and working properly. The sample will now close.")
End If
If classEnum.Next(moniker.Length, moniker, IntPtr.Zero) = 0 Then
Dim iid As Guid = GetType(IBaseFilter).GUID
moniker(0).BindToObject(Nothing, Nothing, iid, source)
Else
Throw New ApplicationException("Unable to access video capture device!")
End If
Marshal.ReleaseComObject(moniker(0))
Marshal.ReleaseComObject(classEnum)
Return CType(source, IBaseFilter)
End Function
Public Sub SetupVideoWindow()
Dim hr As Integer = 0
set the video window to be a child of the main window
putowner : Sets the owning parent window for the video playback window.
hr = VideoWindow.put_Owner(PictureBox1.Handle) Me.Handle)
PictureBox1.Visible = False
hr = VideoWindow.put_WindowStyle(WindowStyle.Child Or WindowStyle.ClipChildren)
Use helper function to position video window in client rect of main application window
ResizeVideoWindow()
Make the video window visible, now that it is properly positioned
put_visible : This method changes the visibility of the video window.
hr = VideoWindow.put_Visible(OABool.True)
End Sub
Public Sub ResizeVideoWindow()
Resize the video preview window to match owner window size
left , top , width , height
If Not (VideoWindow Is Nothing) Then if the videopreview is not nothing
VideoWindow.SetWindowPosition(0, 0, Me.Width, Me.ClientSize.Height)
End If
End Sub
Public Sub closeinterfaces()
//stop previewing data
If Not (Me.MediaControl Is Nothing) Then
Me.MediaControl.StopWhenReady()
End If
Me.CurrentState = PlayState.Stopped
//stop recieving events
If Not (Me.MediaEventEx Is Nothing) Then
Me.MediaEventEx.SetNotifyWindow(IntPtr.Zero, WM_GRAPHNOTIFY, IntPtr.Zero)
End If
// Relinquish ownership (IMPORTANT!) of the video window.
// Failing to call put_Owner can lead to assert failures within
// the video renderer, as it still assumes that it has a valid
// parent window.
If Not (Me.VideoWindow Is Nothing) Then
Me.VideoWindow.put_Visible(OABool.False)
Me.VideoWindow.put_Owner(IntPtr.Zero)
End If
// Remove filter graph from the running object table
If Not (rot Is Nothing) Then
rot.Dispose()
rot = Nothing
End If
// Release DirectShow interfaces
Marshal.ReleaseComObject(Me.MediaControl) : Me.MediaControl = Nothing
Marshal.ReleaseComObject(Me.MediaEventEx) : Me.MediaEventEx = Nothing
Marshal.ReleaseComObject(Me.VideoWindow) : Me.VideoWindow = Nothing
Marshal.ReleaseComObject(Me.GraphBuilder) : Me.GraphBuilder = Nothing
Marshal.ReleaseComObject(Me.CaptureGraphBuilder) : Me.CaptureGraphBuilder = Nothing
End Sub
Private Sub btnGrab_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnGrab.Click
GrabImage()
End Sub
Public Sub GrabImage()
Get image from clipboard and convert it to a bitmap
Try
MediaControl.Pause()
Clipboard.SetImage(PictureBox1.Image)
If Clipboard.ContainsImage Then
PictureBox2.Image = Clipboard.GetImage()
End If
Catch
End Try
Try
MediaControl.Pause()
Dim bmp As New Bitmap(PictureBox1.Width, PictureBox1.Height)
Using g As Graphics = Graphics.FromImage(bmp)
Dim pt As Point = PictureBox1.PointToScreen(New Point(0, 0))
g.CopyFromScreen(pt.X, pt.Y, 0, 0, bmp.Size)
End Using
PictureBox2.Image = bmp
PictureBox2.Visible = True
PictureBox1.Visible = False
Catch
MsgBox("error")
End Try
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click, btnGrab.Click
MediaControl.Run()
End Sub
Private Sub btnSave_Click(sender As System.Object, e As System.EventArgs) Handles BtnSave.Click
Dim newimage As Image = PictureBox2.Image
Dim gr As Graphics = Graphics.FromImage(newimage)
Dim myFontLabels As New Font("Arial", 40)
Dim myBrushLabels As New SolidBrush(Color.Black)
Dim FolderBrowser As New FolderBrowserDialog
If FolderBrowser.ShowDialog = Windows.Forms.DialogResult.OK Then
Me.lblPath.Text = FolderBrowser.SelectedPath & "\Amytest.bmp"
MsgBox("msg" & Me.lblPath.Text)
End If
newimage.Save(Me.lblPath.Text, ImageFormat.Jpeg)
MsgBox("The picture has been successfully copied and saved")
End Sub
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
Dim newimage As Image = PictureBox2.Image
Dim gr As Graphics = Graphics.FromImage(newimage)
Dim myFontLabels As New Font("Arial", 40)
Dim myBrushLabels As New SolidBrush(Color.Black)
Dim _sourcefilename$ = Me.lblPath.Text
Dim _destinationfilename$ = "C:\test.jpg"
JpegSaveClass.SaveImage(_sourcefilename, _destinationfilename)
End Sub
End Class
Continue reading...