mirror of
https://github.com/staxrip/staxrip.git
synced 2026-10-18 14:40:32 +08:00
615 lines
23 KiB
VB.net
615 lines
23 KiB
VB.net
|
|
Imports System.Drawing.Imaging
|
|
Imports System.Text
|
|
Imports Microsoft.VisualBasic.FileIO
|
|
Imports StaxRip.UI
|
|
|
|
Public Class VideoComparisonForm
|
|
Shared Property Pos As Integer
|
|
Shared Property TabBackColor As ColorHSL
|
|
|
|
Private ShowMessageSavedPngs As Boolean = True
|
|
Public CropLeft, CropTop, CropRight, CropBottom As Integer
|
|
|
|
Shadows Menu As ContextMenuStripEx
|
|
|
|
Sub New()
|
|
InitializeComponent()
|
|
RestoreClientSize(53, 36)
|
|
|
|
Dim enabledFunc = Function() TabControl.SelectedTab IsNot Nothing
|
|
Menu = New ContextMenuStripEx With {
|
|
.Form = Me
|
|
}
|
|
|
|
AllowDrop = True
|
|
KeyPreview = True
|
|
bnMenu.ContextMenuStrip = Menu
|
|
bnMenu.TabStop = False
|
|
TabControl.AllowDrop = True
|
|
TabControl.ContextMenuStrip = Menu
|
|
TabControl.ShowToolTips = True
|
|
TrackBar.NoMouseWheelEvent = True
|
|
tlpMain.AllowDrop = True
|
|
|
|
Menu.Add("Add files to compare...", AddressOf Add, Keys.O, "Video files to compare, the file browser has multiselect enabled.")
|
|
Menu.Add("Close selected tab", AddressOf Remove, Keys.Delete, enabledFunc)
|
|
Menu.Add("Select next tab", AddressOf NextTab, Keys.Space, enabledFunc)
|
|
Menu.Add("Save PNGs at current position", AddressOf Save, Keys.S, enabledFunc, "Saves a PNG image for every file/tab at the current position in the directory of the source file.")
|
|
Menu.Add("Crop and Zoom...", AddressOf CropZoom, Keys.C)
|
|
Menu.Add("Go To Frame...", AddressOf GoToFrame, Keys.F, enabledFunc)
|
|
Menu.Add("Go To Time...", AddressOf GoToTime, Keys.T, enabledFunc)
|
|
Menu.Add("Navigate | 1 frame backward", Sub() TrackBar.Value -= 1, Keys.Left, enabledFunc)
|
|
Menu.Add("Navigate | 1 frame forward", Sub() TrackBar.Value += 1, Keys.Right, enabledFunc)
|
|
Menu.Add("Navigate | 100 frame backward", Sub() TrackBar.Value -= 100, Keys.Left Or Keys.Control, enabledFunc)
|
|
Menu.Add("Navigate | 100 frame forward", Sub() TrackBar.Value += 100, Keys.Right Or Keys.Control, enabledFunc)
|
|
Menu.Add("Reload all tabs", AddressOf Reload, Keys.R, enabledFunc)
|
|
Menu.Add("Help", AddressOf Help, Keys.F1)
|
|
|
|
Menu.ApplyMarginFix()
|
|
|
|
AddHandler tlpMain.DragOver, AddressOf TabControlOnDragOver
|
|
AddHandler tlpMain.DragDrop, AddressOf TabControlOnDragDrop
|
|
AddHandler TabControl.DragOver, AddressOf TabControlOnDragOver
|
|
AddHandler TabControl.DragDrop, AddressOf TabControlOnDragDrop
|
|
AddHandler TabControl.Selected, AddressOf TabControlOnSelected
|
|
|
|
ApplyTheme()
|
|
AddHandler ThemeManager.CurrentThemeChanged, AddressOf OnThemeChanged
|
|
End Sub
|
|
|
|
Protected Overrides Sub Dispose(disposing As Boolean)
|
|
RemoveHandler ThemeManager.CurrentThemeChanged, AddressOf OnThemeChanged
|
|
components?.Dispose()
|
|
MyBase.Dispose(disposing)
|
|
End Sub
|
|
|
|
Sub OnThemeChanged(theme As Theme)
|
|
ApplyTheme(theme)
|
|
End Sub
|
|
|
|
Sub ApplyTheme()
|
|
ApplyTheme(ThemeManager.CurrentTheme)
|
|
End Sub
|
|
|
|
Sub ApplyTheme(theme As Theme)
|
|
If DesignHelp.IsDesignMode Then
|
|
Exit Sub
|
|
End If
|
|
|
|
BackColor = theme.VideoComparisonForm.BackColor
|
|
TabBackColor = theme.VideoComparisonForm.TabBackColor
|
|
|
|
End Sub
|
|
|
|
Protected Overrides Sub OnDragEnter(e As DragEventArgs)
|
|
MyBase.OnDragEnter(e)
|
|
|
|
Dim files = TryCast(e.Data.GetData(DataFormats.FileDrop), String())
|
|
|
|
If Not files.NothingOrEmpty Then
|
|
e.Effect = DragDropEffects.Copy
|
|
End If
|
|
End Sub
|
|
|
|
Protected Overrides Sub OnDragDrop(e As DragEventArgs)
|
|
MyBase.OnDragDrop(e)
|
|
|
|
Dim files = TryCast(e.Data.GetData(DataFormats.FileDrop), String())
|
|
|
|
If Not files.NothingOrEmpty Then
|
|
BeginInvoke(Sub() Add(files))
|
|
End If
|
|
End Sub
|
|
|
|
Sub TabControlOnDragOver(sender As Object, e As DragEventArgs)
|
|
Dim files = TryCast(e.Data.GetData(DataFormats.FileDrop), String())
|
|
|
|
If Not files.NothingOrEmpty Then
|
|
e.Effect = DragDropEffects.Copy
|
|
End If
|
|
End Sub
|
|
|
|
Sub TabControlOnDragDrop(sender As Object, e As DragEventArgs)
|
|
Dim files = TryCast(e.Data.GetData(DataFormats.FileDrop), String())
|
|
|
|
If Not files.NothingOrEmpty Then
|
|
BeginInvoke(Sub() Add(files))
|
|
End If
|
|
End Sub
|
|
|
|
Sub TabControlOnSelected(sender As Object, e As TabControlEventArgs)
|
|
Dim tab = DirectCast(e.TabPage, VideoTab)
|
|
|
|
If tab IsNot Nothing
|
|
laFilePath.Text = tab.SourceFilePath
|
|
End If
|
|
End Sub
|
|
|
|
Sub Add()
|
|
If Not Package.AviSynth.VerifyOK(True) Then Exit Sub
|
|
|
|
Dim sourcePath = p.SourceFile
|
|
Dim sourceAlreadyOpen = If(TabControl.TabPages.Cast(Of VideoTab)?.Where(Function(x) x.SourceFilePath.Equals(sourcePath, StringComparison.InvariantCultureIgnoreCase))?.Any(), False)
|
|
|
|
If Not sourceAlreadyOpen AndAlso File.Exists(sourcePath) Then
|
|
Add(sourcePath)
|
|
If File.Exists(p.TargetFile) Then Add(p.TargetFile)
|
|
Else
|
|
Using dialog As New OpenFileDialog
|
|
dialog.SetFilter(FileTypes.VideoComparisonInput)
|
|
dialog.Multiselect = True
|
|
dialog.SetInitDir(s.Storage.GetString("video comparison folder"))
|
|
|
|
If dialog.ShowDialog() = DialogResult.OK Then
|
|
s.Storage.SetString("video comparison folder", dialog.FileName.Dir)
|
|
Add(dialog.FileNames)
|
|
End If
|
|
End Using
|
|
End If
|
|
|
|
End Sub
|
|
|
|
Sub Add(sourcePath As String)
|
|
Dim tab = New VideoTab With {
|
|
.AllowDrop = True,
|
|
.Form = Me,
|
|
.BackColor = TabBackColor,
|
|
.ToolTipText = sourcePath
|
|
}
|
|
tab.VideoPanel.ContextMenuStrip = TabControl.ContextMenuStrip
|
|
|
|
If tab.Open(sourcePath) Then
|
|
TabControl.TabPages.Add(tab)
|
|
|
|
AddHandler tab.DragOver, AddressOf TabControlOnDragOver
|
|
AddHandler tab.DragDrop, AddressOf TabControlOnDragDrop
|
|
|
|
Dim page = DirectCast(TabControl.SelectedTab, VideoTab)
|
|
page.DoLayout()
|
|
page.TrackBarValueChanged()
|
|
Else
|
|
tab.Dispose()
|
|
End If
|
|
|
|
Dim vt = DirectCast(TabControl.SelectedTab, VideoTab)
|
|
laFilePath.Text = vt?.SourceFilePath
|
|
End Sub
|
|
|
|
Sub Add(sourcePaths As String())
|
|
For Each path In sourcePaths
|
|
If File.Exists(path) Then
|
|
Add(path)
|
|
End If
|
|
Next
|
|
End Sub
|
|
|
|
Sub Remove()
|
|
If TabControl.SelectedTab IsNot Nothing Then
|
|
Dim tab = TabControl.SelectedTab
|
|
TabControl.TabPages.Remove(tab)
|
|
tab.Dispose()
|
|
End If
|
|
End Sub
|
|
|
|
Sub Save()
|
|
For Each tab As VideoTab In TabControl.TabPages
|
|
Dim outputPath = ""
|
|
|
|
Select Case s.SaveImageVideoComparisonFrameNumberPosition
|
|
Case ImageFrameNumberPosition.Prefix
|
|
outputPath = Path.Combine(tab.SourceFilePath.Dir, $"{Pos:00000}_{tab.SourceFilePath.Base}.png")
|
|
Case ImageFrameNumberPosition.Suffix
|
|
outputPath = Path.Combine(tab.SourceFilePath.Dir, $"{tab.SourceFilePath.Base}_{Pos:00000}.png")
|
|
Case Else
|
|
Throw New NotSupportedException("VideoComparisonForm.Save()")
|
|
End Select
|
|
|
|
Using bmp = tab.GetBitmap
|
|
bmp.Save(outputPath, ImageFormat.Png)
|
|
End Using
|
|
Next
|
|
|
|
If ShowMessageSavedPngs Then
|
|
Using td As New TaskDialog(Of String)
|
|
td.Title = "Images were saved in the source file directory."
|
|
td.AddCommand("OK")
|
|
td.AddCommand("Dismiss this message for this session", "Dismiss")
|
|
|
|
Select Case td.Show
|
|
Case "OK"
|
|
Case "Dismiss"
|
|
ShowMessageSavedPngs = False
|
|
End Select
|
|
End Using
|
|
End If
|
|
End Sub
|
|
|
|
Sub TrackBar_ValueChanged(sender As Object, e As EventArgs) Handles TrackBar.ValueChanged
|
|
TrackBarValueChanged()
|
|
End Sub
|
|
|
|
Sub TrackBarValueChanged()
|
|
If TabControl.TabPages.Count > 0 Then
|
|
DirectCast(TabControl.SelectedTab, VideoTab).TrackBarValueChanged()
|
|
End If
|
|
End Sub
|
|
|
|
Sub Help()
|
|
Dim form As New HelpForm()
|
|
form.Doc.WriteStart(Text)
|
|
form.Doc.WriteParagraph("In the statistic tab of the x265 dialog select Log Level Frame and enable CSV log file creation, the video comparison tool can displays containing frame info.")
|
|
form.Doc.WriteTips(Menu.GetTips)
|
|
form.Doc.WriteTable("Shortcut Keys", Menu.GetKeys, False)
|
|
form.Show()
|
|
End Sub
|
|
|
|
Sub NextTab()
|
|
Dim index = TabControl.SelectedIndex + 1
|
|
|
|
If index >= TabControl.TabPages.Count Then
|
|
index = 0
|
|
End If
|
|
|
|
If index <> TabControl.SelectedIndex Then
|
|
TabControl.SelectedIndex = index
|
|
End If
|
|
End Sub
|
|
|
|
Sub Reload()
|
|
For Each tab As VideoTab In TabControl.TabPages
|
|
tab.Reload()
|
|
Next
|
|
End Sub
|
|
|
|
Protected Overrides Sub OnMouseWheel(e As MouseEventArgs)
|
|
MyBase.OnMouseWheel(e)
|
|
|
|
Dim value = 100
|
|
|
|
If e.Delta < 0 Then
|
|
value *= -1
|
|
End If
|
|
|
|
If s.ReverseVideoScrollDirection Then
|
|
value *= -1
|
|
End If
|
|
|
|
TrackBar.Value += value
|
|
End Sub
|
|
|
|
Protected Overrides Sub OnFormClosed(e As FormClosedEventArgs)
|
|
MyBase.OnFormClosed(e)
|
|
Dispose()
|
|
End Sub
|
|
|
|
Protected Overrides Sub OnShown(e As EventArgs)
|
|
MyBase.OnShown(e)
|
|
Add()
|
|
End Sub
|
|
|
|
Sub CropZoom()
|
|
Using form As New SimpleSettingsForm("Crop and Zoom")
|
|
form.Height = CInt(form.Height * 0.6)
|
|
form.Width = CInt(form.Width * 0.6)
|
|
Dim ui = form.SimpleUI
|
|
Dim page = ui.CreateFlowPage("main page")
|
|
page.SuspendLayout()
|
|
|
|
Dim nb = ui.AddNum(page)
|
|
nb.Label.Text = "Crop Left:"
|
|
nb.NumEdit.Config = {0, 10000, 10}
|
|
nb.NumEdit.Value = CropLeft
|
|
nb.NumEdit.SaveAction = Sub(value) CropLeft = CInt(value)
|
|
|
|
nb = ui.AddNum(page)
|
|
nb.Label.Text = "Crop Top:"
|
|
nb.NumEdit.Config = {0, 10000, 10}
|
|
nb.NumEdit.Value = CropTop
|
|
nb.NumEdit.SaveAction = Sub(value) CropTop = CInt(value)
|
|
|
|
nb = ui.AddNum(page)
|
|
nb.Label.Text = "Crop Right:"
|
|
nb.NumEdit.Config = {0, 10000, 10}
|
|
nb.NumEdit.Value = CropRight
|
|
nb.NumEdit.SaveAction = Sub(value) CropRight = CInt(value)
|
|
|
|
nb = ui.AddNum(page)
|
|
nb.Label.Text = "Crop Bottom:"
|
|
nb.NumEdit.Config = {0, 10000, 10}
|
|
nb.NumEdit.Value = CropBottom
|
|
nb.NumEdit.SaveAction = Sub(value) CropBottom = CInt(value)
|
|
|
|
page.ResumeLayout()
|
|
|
|
If form.ShowDialog() = DialogResult.OK Then
|
|
ui.Save()
|
|
Reload()
|
|
TrackBarValueChanged()
|
|
End If
|
|
End Using
|
|
End Sub
|
|
|
|
Sub GoToFrame()
|
|
Dim value = InputBox.Show("Go To Frame", TrackBar.Value.ToString)
|
|
Dim pos As Integer
|
|
|
|
If Integer.TryParse(value, pos) Then
|
|
TrackBar.Value = pos
|
|
End If
|
|
End Sub
|
|
|
|
Sub GoToTime()
|
|
Dim tab = DirectCast(TabControl.SelectedTab, VideoTab)
|
|
Dim d As Date
|
|
d = d.AddSeconds(Pos / tab.Server.FrameRate)
|
|
Dim value = InputBox.Show("Go To Time", d.ToString("HH:mm:ss.fff"))
|
|
Dim time As TimeSpan
|
|
|
|
If value <> "" AndAlso TimeSpan.TryParse(value, time) Then
|
|
TrackBar.Value = CInt(time.TotalMilliseconds / 1000 * tab.Server.FrameRate)
|
|
End If
|
|
End Sub
|
|
|
|
Public Class VideoTab
|
|
Inherits TabPage
|
|
|
|
Property Server As IFrameServer
|
|
Property Form As VideoComparisonForm
|
|
Property FileType As VideoComparisonFileType = VideoComparisonFileType.Video
|
|
Property TempFilePath As String
|
|
Property SourceFilePath As String
|
|
Property VideoPanel As PanelEx
|
|
|
|
Private Renderer As VideoRenderer
|
|
Private FrameInfo As String()
|
|
|
|
Sub New()
|
|
VideoPanel = New PanelEx
|
|
AddHandler VideoPanel.Paint, Sub() Draw()
|
|
Controls.Add(VideoPanel)
|
|
End Sub
|
|
|
|
Private Function AdjustName(name As String, Optional lengthLimit As Integer = 50) As String
|
|
If String.IsNullOrWhiteSpace(name) Then Return "<empty>"
|
|
|
|
Const replacement = "....."
|
|
|
|
If name.Length > lengthLimit Then
|
|
Dim firstHalfLength = lengthLimit \ 2
|
|
Dim secondHalfLength = lengthLimit - firstHalfLength
|
|
Return $"{name.Substring(0, firstHalfLength)}{replacement}{name.Substring(name.Length - secondHalfLength)}"
|
|
End If
|
|
|
|
Return name
|
|
End Function
|
|
|
|
Sub Reload()
|
|
Renderer.Dispose()
|
|
Server.Dispose()
|
|
Open(SourceFilePath)
|
|
End Sub
|
|
|
|
Function Open(sourcePath As String) As Boolean
|
|
Text = AdjustName(sourcePath.Base)
|
|
ToolTipText = sourcePath
|
|
SourceFilePath = sourcePath
|
|
|
|
Select Case sourcePath.Ext()
|
|
Case "avs"
|
|
FileType = VideoComparisonFileType.AviSynthScript
|
|
TempFilePath = sourcePath.DirAndBase + "_compare" + sourcePath.ExtFull
|
|
Case "vpy"
|
|
FileType = VideoComparisonFileType.VapourSynthScript
|
|
TempFilePath = sourcePath.DirAndBase + "_compare" + sourcePath.ExtFull
|
|
Case "png"
|
|
FileType = VideoComparisonFileType.Picture
|
|
TempFilePath = Path.Combine(Folder.Temp, Guid.NewGuid.ToString + ".avs")
|
|
Case Else
|
|
FileType = VideoComparisonFileType.Video
|
|
TempFilePath = Path.Combine(Folder.Temp, Guid.NewGuid.ToString + ".avs")
|
|
End Select
|
|
|
|
Dim script As New VideoScript With {
|
|
.Engine = If(FileType = VideoComparisonFileType.VapourSynthScript, ScriptEngine.VapourSynth, ScriptEngine.AviSynth),
|
|
.Path = TempFilePath
|
|
}
|
|
|
|
AddHandler Disposed, Sub() FileHelp.Delete(script.Path, RecycleOption.DeletePermanently)
|
|
|
|
Select Case FileType
|
|
Case VideoComparisonFileType.AviSynthScript
|
|
script.Filters.Add(New VideoFilter("Source", "Source", File.ReadAllText(sourcePath)))
|
|
Case VideoComparisonFileType.VapourSynthScript
|
|
script.Filters.Add(New VideoFilter("Source", "Source", File.ReadAllText(sourcePath)))
|
|
Case VideoComparisonFileType.Video
|
|
If sourcePath.EndsWith("mp4") Then
|
|
script.Filters.Add(New VideoFilter("Source", "Source", "LSMASHVideoSource(""" + sourcePath + "" + """, format = ""YUV420P12"")"))
|
|
Else
|
|
script.Filters.Add(New VideoFilter("Source", "Source", "FFVideoSource(""" + sourcePath + "" + """, colorspace = ""YV12"")"))
|
|
End If
|
|
script.Filters.Add(New VideoFilter("SetMemoryMax(512)"))
|
|
Case VideoComparisonFileType.Picture
|
|
script.Filters.Add(New VideoFilter("ImageSource(""" + sourcePath + """, end = 0)"))
|
|
script.Filters.Add(New VideoFilter("SetMemoryMax(512)"))
|
|
Case Else
|
|
Throw New NotSupportedException("VideoComparisonFileType unhandled!")
|
|
End Select
|
|
|
|
Select Case FileType
|
|
Case VideoComparisonFileType.Picture
|
|
If (Form.CropLeft Or Form.CropTop Or Form.CropRight Or Form.CropBottom) <> 0 Then
|
|
script.Filters.Add(New VideoFilter("Crop(" & Form.CropLeft & ", " & Form.CropTop & ", -" & Form.CropRight & ", -" & Form.CropBottom & ")"))
|
|
End If
|
|
Case VideoComparisonFileType.Video
|
|
If (Form.CropLeft Or Form.CropTop Or Form.CropRight Or Form.CropBottom) <> 0 Then
|
|
script.Filters.Add(New VideoFilter("Crop(" & Form.CropLeft & ", " & Form.CropTop & ", -" & Form.CropRight & ", -" & Form.CropBottom & ")"))
|
|
End If
|
|
Case VideoComparisonFileType.AviSynthScript
|
|
Case VideoComparisonFileType.VapourSynthScript
|
|
Case Else
|
|
Throw New NotSupportedException("VideoComparisonFileType unhandled!")
|
|
End Select
|
|
|
|
Indexing(sourcePath, script)
|
|
script.Synchronize(True, True, True)
|
|
|
|
Server = FrameServerFactory.Create(script.Path)
|
|
Renderer = New VideoRenderer(VideoPanel, Server)
|
|
Dim maximum = Server.Info.FrameCount - 1
|
|
Form.TrackBar.Maximum = If(Form.TrackBar.Maximum < maximum, maximum, Form.TrackBar.Maximum)
|
|
|
|
If Server.Error <> "" Then MsgError(Server.Error)
|
|
|
|
Dim csvFile = sourcePath.DirAndBase + ".csv"
|
|
|
|
If File.Exists(csvFile) Then
|
|
Dim len = Form.TrackBar.Maximum
|
|
Dim lines = File.ReadAllLines(csvFile)
|
|
|
|
If lines.Length > len Then
|
|
FrameInfo = New String(len) {}
|
|
Dim headers = lines(0).Split({","c})
|
|
|
|
For x = 1 To len + 1
|
|
Dim values = lines(x).Split({","c})
|
|
|
|
For x2 = 0 To headers.Length - 1
|
|
Dim value = values(x2).Trim
|
|
|
|
If value <> "" AndAlso value <> "-" Then
|
|
FrameInfo(x - 1) += headers(x2).Trim + ": " + value + ", "
|
|
End If
|
|
Next
|
|
|
|
FrameInfo(x - 1) = FrameInfo(x - 1).TrimEnd(" ,".ToCharArray)
|
|
Next
|
|
End If
|
|
End If
|
|
Return True
|
|
End Function
|
|
|
|
Sub Indexing(sourcePath As String, script As VideoScript)
|
|
If String.IsNullOrWhiteSpace(sourcePath) Then Exit Sub
|
|
If Not File.Exists(sourcePath) Then Exit Sub
|
|
If script Is Nothing Then Exit Sub
|
|
|
|
Dim sourceFilter = script.GetFilter("Source")
|
|
If sourceFilter Is Nothing Then Exit Sub
|
|
|
|
Dim codeLower = script.GetFilter("Source").Script.ToLowerInvariant
|
|
|
|
If codeLower.Contains("ffvideosource(") OrElse codeLower.Contains("ffms2.source") Then
|
|
If codeLower.Contains("cachefile") AndAlso p.TempDir <> "" AndAlso New DirectoryInfo(p.TempDir)?.Name?.EndsWithEx("_temp") Then
|
|
g.ffmsindex(sourcePath, Path.Combine(p.TempDir, g.GetSourceBase + ".ffindex"))
|
|
Else
|
|
g.ffmsindex(sourcePath, sourcePath + ".ffindex")
|
|
End If
|
|
ElseIf codeLower.Contains("lwlibavvideosource(") OrElse codeLower.Contains("lwlibavsource(") Then
|
|
If Not File.Exists(sourcePath + ".lwi") AndAlso
|
|
Not File.Exists(Path.Combine(p.TempDir, g.GetSourceBase + ".lwi")) AndAlso
|
|
File.Exists(script.Path) AndAlso Not FileTypes.VideoText.Contains(sourcePath.Ext) Then
|
|
Using proc As New Proc
|
|
proc.Header = "Index LWLibav"
|
|
proc.Encoding = Encoding.UTF8
|
|
proc.SkipString = "Creating lwi"
|
|
If script.IsAviSynth Then
|
|
proc.File = Package.ffmpeg.Path
|
|
proc.Arguments = "-i " + script.Path.Escape + " -hide_banner"
|
|
Else
|
|
proc.File = Package.vspipe.Path
|
|
proc.Arguments = script.Path.Escape + " NUL -i"
|
|
End If
|
|
|
|
proc.AllowedExitCodes = {0, 1}
|
|
proc.Start()
|
|
End Using
|
|
End If
|
|
End If
|
|
End Sub
|
|
|
|
Sub Draw()
|
|
Renderer.Position = Pos
|
|
Renderer.Draw()
|
|
End Sub
|
|
|
|
Function GetBitmap() As Bitmap
|
|
Return BitmapUtil.CreateBitmap(Server, Pos)
|
|
End Function
|
|
|
|
Sub TrackBarValueChanged()
|
|
Try
|
|
Pos = Form.TrackBar.Value
|
|
Draw()
|
|
|
|
If FrameInfo IsNot Nothing Then
|
|
Form.laInfo.Text = FrameInfo(Form.TrackBar.Value)
|
|
Else
|
|
Dim frameRate = If(Calc.IsValidFrameRate(Server.FrameRate), Server.FrameRate, 25)
|
|
Dim dt = DateTime.Today.AddSeconds(Pos / frameRate)
|
|
Form.laInfo.Text = $"Position: {Pos,5}, Time: {dt:HH:mm:ss.fff}, Size: {Server.Info.Width} x {Server.Info.Height}"
|
|
End If
|
|
|
|
Form.laInfo.Refresh()
|
|
Catch ex As Exception
|
|
g.ShowException(ex)
|
|
End Try
|
|
End Sub
|
|
|
|
Sub DoLayout()
|
|
If Server Is Nothing Then
|
|
Exit Sub
|
|
End If
|
|
|
|
Dim sizeToFit = New Size(Server.Info.Width, Server.Info.Height)
|
|
|
|
If sizeToFit.IsEmpty Then
|
|
Exit Sub
|
|
End If
|
|
|
|
Dim padding As Padding
|
|
|
|
Dim rect As New Rectangle(
|
|
padding.Left, padding.Top,
|
|
Width - padding.Horizontal,
|
|
Height - padding.Vertical)
|
|
|
|
Dim targetPoint As Point
|
|
Dim targetSize As Size
|
|
Dim ar1 = rect.Width / rect.Height
|
|
Dim ar2 = sizeToFit.Width / sizeToFit.Height
|
|
|
|
If ar2 < ar1 Then
|
|
targetSize.Height = rect.Height
|
|
targetSize.Width = CInt(sizeToFit.Width / (sizeToFit.Height / rect.Height))
|
|
targetPoint.X = CInt((rect.Width - targetSize.Width) / 2) + padding.Left
|
|
targetPoint.Y = padding.Top
|
|
Else
|
|
targetSize.Width = rect.Width
|
|
targetSize.Height = CInt(sizeToFit.Height / (sizeToFit.Width / rect.Width))
|
|
targetPoint.Y = CInt((rect.Height - targetSize.Height) / 2) + padding.Top
|
|
targetPoint.X = padding.Left
|
|
End If
|
|
|
|
Dim targetRect = New Rectangle(targetPoint, targetSize)
|
|
Dim reg As New Region(ClientRectangle)
|
|
reg.Exclude(targetRect)
|
|
|
|
VideoPanel.Left = targetRect.Left
|
|
VideoPanel.Top = targetRect.Top
|
|
VideoPanel.Width = targetRect.Width
|
|
VideoPanel.Height = targetRect.Height
|
|
End Sub
|
|
|
|
Protected Overrides Sub Dispose(disposing As Boolean)
|
|
Server?.Dispose()
|
|
|
|
MyBase.Dispose(disposing)
|
|
End Sub
|
|
|
|
Sub VideoTab_Resize(sender As Object, e As EventArgs) Handles Me.Resize
|
|
DoLayout()
|
|
End Sub
|
|
End Class
|
|
End Class
|