mirror of
https://github.com/staxrip/staxrip.git
synced 2026-10-18 06:31:02 +08:00
755 lines
27 KiB
VB.net
755 lines
27 KiB
VB.net
|
|
Imports System.ComponentModel
|
|
|
|
Imports StaxRip.UI
|
|
|
|
Public Class CropForm
|
|
Inherits DialogBase
|
|
|
|
#Region " Designer "
|
|
Private components As System.ComponentModel.IContainer
|
|
|
|
Friend WithEvents pnLeftActive As PanelEx
|
|
Friend WithEvents pnTopActive As PanelEx
|
|
Friend WithEvents pnBottomActive As PanelEx
|
|
Friend WithEvents pnRightActive As PanelEx
|
|
Friend WithEvents tbPosition As TrackBar
|
|
Friend WithEvents pnVideo As PanelEx
|
|
Friend WithEvents StatusStrip As System.Windows.Forms.StatusStrip
|
|
Friend WithEvents tsbMenu As System.Windows.Forms.ToolStripDropDownButton
|
|
Friend WithEvents laStatus As System.Windows.Forms.ToolStripStatusLabel
|
|
|
|
<System.Diagnostics.DebuggerStepThrough()> Sub InitializeComponent()
|
|
Me.pnLeftActive = New PanelEx()
|
|
Me.pnTopActive = New PanelEx()
|
|
Me.pnBottomActive = New PanelEx()
|
|
Me.pnRightActive = New PanelEx()
|
|
Me.pnVideo = New PanelEx()
|
|
Me.tbPosition = New System.Windows.Forms.TrackBar()
|
|
Me.StatusStrip = New System.Windows.Forms.StatusStrip()
|
|
Me.laStatus = New System.Windows.Forms.ToolStripStatusLabel()
|
|
Me.tsbMenu = New System.Windows.Forms.ToolStripDropDownButton()
|
|
CType(Me.tbPosition, System.ComponentModel.ISupportInitialize).BeginInit()
|
|
Me.StatusStrip.SuspendLayout()
|
|
Me.SuspendLayout()
|
|
'
|
|
'pnLeftActive
|
|
'
|
|
Me.pnLeftActive.BackColor = System.Drawing.SystemColors.InfoText
|
|
Me.pnLeftActive.Location = New System.Drawing.Point(24, 56)
|
|
Me.pnLeftActive.Name = "pnLeftActive"
|
|
Me.pnLeftActive.Size = New System.Drawing.Size(20, 81)
|
|
Me.pnLeftActive.TabIndex = 0
|
|
'
|
|
'pnTopActive
|
|
'
|
|
Me.pnTopActive.BackColor = System.Drawing.SystemColors.InfoText
|
|
Me.pnTopActive.Location = New System.Drawing.Point(64, 15)
|
|
Me.pnTopActive.Name = "pnTopActive"
|
|
Me.pnTopActive.Size = New System.Drawing.Size(152, 20)
|
|
Me.pnTopActive.TabIndex = 1
|
|
'
|
|
'pnBottomActive
|
|
'
|
|
Me.pnBottomActive.BackColor = System.Drawing.SystemColors.InfoText
|
|
Me.pnBottomActive.Location = New System.Drawing.Point(64, 184)
|
|
Me.pnBottomActive.Name = "pnBottomActive"
|
|
Me.pnBottomActive.Size = New System.Drawing.Size(152, 20)
|
|
Me.pnBottomActive.TabIndex = 3
|
|
'
|
|
'pnRightActive
|
|
'
|
|
Me.pnRightActive.BackColor = System.Drawing.SystemColors.InfoText
|
|
Me.pnRightActive.Location = New System.Drawing.Point(256, 56)
|
|
Me.pnRightActive.Name = "pnRightActive"
|
|
Me.pnRightActive.Size = New System.Drawing.Size(20, 88)
|
|
Me.pnRightActive.TabIndex = 4
|
|
'
|
|
'pVideo
|
|
'
|
|
Me.pnVideo.BackColor = System.Drawing.Color.Black
|
|
Me.pnVideo.Location = New System.Drawing.Point(64, 55)
|
|
Me.pnVideo.Name = "pVideo"
|
|
Me.pnVideo.Size = New System.Drawing.Size(149, 89)
|
|
Me.pnVideo.TabIndex = 2
|
|
'
|
|
'tbPosition
|
|
'
|
|
Me.tbPosition.Anchor = CType(((System.Windows.Forms.AnchorStyles.Bottom Or System.Windows.Forms.AnchorStyles.Left) _
|
|
Or System.Windows.Forms.AnchorStyles.Right), System.Windows.Forms.AnchorStyles)
|
|
Me.tbPosition.AutoSize = False
|
|
Me.tbPosition.Location = New System.Drawing.Point(12, 266)
|
|
Me.tbPosition.Name = "tbPosition"
|
|
Me.tbPosition.Size = New System.Drawing.Size(711, 61)
|
|
Me.tbPosition.TabIndex = 5
|
|
Me.tbPosition.TabStop = False
|
|
Me.tbPosition.TickStyle = System.Windows.Forms.TickStyle.None
|
|
'
|
|
'StatusStrip
|
|
'
|
|
Me.StatusStrip.ImageScalingSize = New System.Drawing.Size(48, 48)
|
|
Me.StatusStrip.Items.AddRange(New System.Windows.Forms.ToolStripItem() {Me.laStatus, Me.tsbMenu})
|
|
Me.StatusStrip.LayoutStyle = System.Windows.Forms.ToolStripLayoutStyle.HorizontalStackWithOverflow
|
|
Me.StatusStrip.Location = New System.Drawing.Point(0, 330)
|
|
Me.StatusStrip.Name = "StatusStrip"
|
|
Me.StatusStrip.Size = New System.Drawing.Size(735, 63)
|
|
Me.StatusStrip.TabIndex = 6
|
|
Me.StatusStrip.Text = "StatusStrip"
|
|
'
|
|
'laStatus
|
|
'
|
|
Me.laStatus.Name = "laStatus"
|
|
Me.laStatus.Size = New System.Drawing.Size(34, 48)
|
|
Me.laStatus.Text = "-"
|
|
'
|
|
'tsbMenu
|
|
'
|
|
Me.tsbMenu.Alignment = System.Windows.Forms.ToolStripItemAlignment.Right
|
|
Me.tsbMenu.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text
|
|
Me.tsbMenu.ImageTransparentColor = System.Drawing.Color.Magenta
|
|
Me.tsbMenu.Name = "tsbMenu"
|
|
Me.tsbMenu.Size = New System.Drawing.Size(142, 57)
|
|
Me.tsbMenu.Text = "Menu"
|
|
'
|
|
'CropForm
|
|
'
|
|
Me.AutoScaleDimensions = New System.Drawing.SizeF(288.0!, 288.0!)
|
|
Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi
|
|
Me.ClientSize = New System.Drawing.Size(735, 393)
|
|
Me.Controls.Add(Me.StatusStrip)
|
|
Me.Controls.Add(Me.tbPosition)
|
|
Me.Controls.Add(Me.pnVideo)
|
|
Me.Controls.Add(Me.pnRightActive)
|
|
Me.Controls.Add(Me.pnBottomActive)
|
|
Me.Controls.Add(Me.pnTopActive)
|
|
Me.Controls.Add(Me.pnLeftActive)
|
|
Me.Font = FontManager.GetDefaultFont()
|
|
Me.Margin = New System.Windows.Forms.Padding(6, 6, 6, 6)
|
|
Me.MinimumSize = New System.Drawing.Size(200, 200)
|
|
Me.Name = "CropForm"
|
|
Me.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Show
|
|
Me.Text = $"Crop - {g.DefaultCommands.GetApplicationDetails()}"
|
|
CType(Me.tbPosition, System.ComponentModel.ISupportInitialize).EndInit()
|
|
Me.StatusStrip.ResumeLayout(False)
|
|
Me.StatusStrip.PerformLayout()
|
|
Me.ResumeLayout(False)
|
|
Me.PerformLayout()
|
|
|
|
End Sub
|
|
|
|
#End Region
|
|
|
|
Private FrameServer As IFrameServer
|
|
Private Renderer As VideoRenderer
|
|
Private Side As AnchorStyles
|
|
Private ActiveCropSide As AnchorStyles
|
|
Private CommandManager As New CommandManager
|
|
Private WithEvents CustomMenu As CustomMenu
|
|
|
|
Public Property BorderColor As ColorHSL = Color.Empty
|
|
Public Property BorderSelectedColor As ColorHSL = Color.Empty
|
|
Public Property RendererBackColor As ColorHSL = Color.Empty
|
|
|
|
Sub New()
|
|
InitializeComponent()
|
|
IsComposited = False
|
|
|
|
MinimumSize = New Size(CInt(Font.Size * 60), CInt(Font.Size * 60))
|
|
|
|
CommandManager.AddCommandsFromObject(Me)
|
|
CommandManager.AddCommandsFromObject(g.DefaultCommands)
|
|
|
|
ContextMenuStrip = New ContextMenuStripEx
|
|
|
|
CustomMenu = New CustomMenu(AddressOf GetDefaultMenuCrop,
|
|
s.CustomMenuCrop, CommandManager, ContextMenuStrip)
|
|
|
|
CustomMenu.AddKeyDownHandler(Me)
|
|
CustomMenu.BuildMenu()
|
|
|
|
StatusStrip.Font = FontManager.GetDefaultFont()
|
|
|
|
Dim offset = CInt(FontHeight * 0.6)
|
|
|
|
pnVideo.Left = offset
|
|
pnVideo.Top = offset
|
|
pnVideo.Width = ClientSize.Width - offset * 2
|
|
pnVideo.Height = tbPosition.Top - offset * 2
|
|
pnVideo.Anchor = AnchorStyles.Left Or AnchorStyles.Top Or AnchorStyles.Right Or AnchorStyles.Bottom
|
|
|
|
pnLeftActive.Top = offset
|
|
pnLeftActive.Left = 0
|
|
pnLeftActive.Width = offset
|
|
pnLeftActive.Height = pnVideo.Height
|
|
pnLeftActive.Anchor = AnchorStyles.Bottom Or AnchorStyles.Left Or AnchorStyles.Top
|
|
|
|
pnTopActive.Left = offset
|
|
pnTopActive.Top = 0
|
|
pnTopActive.Width = pnVideo.Width
|
|
pnTopActive.Height = offset
|
|
pnTopActive.Anchor = AnchorStyles.Left Or AnchorStyles.Top Or AnchorStyles.Right
|
|
|
|
pnRightActive.Left = offset + pnVideo.Width
|
|
pnRightActive.Top = offset
|
|
pnRightActive.Width = offset
|
|
pnRightActive.Height = pnVideo.Height
|
|
pnRightActive.Anchor = AnchorStyles.Top Or AnchorStyles.Right Or AnchorStyles.Bottom
|
|
|
|
pnBottomActive.Left = offset
|
|
pnBottomActive.Top = offset + pnVideo.Height
|
|
pnBottomActive.Width = pnVideo.Width
|
|
pnBottomActive.Height = offset
|
|
pnBottomActive.Anchor = AnchorStyles.Right Or AnchorStyles.Bottom Or AnchorStyles.Left
|
|
|
|
FormBorderStyle = FormBorderStyle.Sizable
|
|
|
|
tbPosition.Maximum = p.SourceFrames
|
|
|
|
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.General.BackColor
|
|
|
|
BorderColor = theme.CropForm.BorderColor
|
|
BorderSelectedColor = theme.CropForm.BorderSelectedColor
|
|
|
|
StatusStrip.BackColor = theme.General.BackColor
|
|
StatusStrip.ForeColor = theme.General.ForeColor
|
|
End Sub
|
|
|
|
Protected Overrides Sub OnLoad(args As EventArgs)
|
|
MyBase.OnLoad(args)
|
|
|
|
Dim zoom = 0.0
|
|
Dim workingArea = Screen.FromControl(Me).WorkingArea
|
|
|
|
While p.SourceWidth * zoom < 0.77 * workingArea.Width AndAlso
|
|
p.SourceHeight * zoom < 0.77 * workingArea.Height
|
|
|
|
zoom += 0.01
|
|
End While
|
|
|
|
SetDialogSize(CInt(p.SourceWidth * zoom), CInt(p.SourceHeight * zoom))
|
|
|
|
Dim script As New VideoScript
|
|
script.Engine = p.Script.Engine
|
|
script.Path = Path.Combine(p.TempDir, p.TargetFile.Base + "_crop." + script.FileType)
|
|
script.Filters.Add(p.Script.GetFilter("Source").GetCopy())
|
|
|
|
If p.Script.GetFilter("Rotation") IsNot Nothing Then
|
|
script.Filters.Add(p.Script.GetFilter("Rotation").GetCopy())
|
|
End If
|
|
|
|
If p.CropWithTonemapping Then
|
|
If p.SourceVideoBitDepth > 8 AndAlso Not p.SourceVideoHdrFormat?.EqualsAny("", "SDR") Then
|
|
If p.Script.Engine = ScriptEngine.AviSynth AndAlso Package.AVSLibPlacebo.RequirementsFulfilled Then
|
|
script.Filters.Add(New VideoFilter("Color", "Tonemap", "ConvertBits(16)" + BR + "libplacebo_Tonemap()" + BR + "ConvertToYUV420()" + BR + "ConvertBits(8)"))
|
|
ElseIf p.Script.Engine = ScriptEngine.VapourSynth AndAlso Package.VSLibPlacebo.RequirementsFulfilled Then
|
|
script.Filters.Add(New VideoFilter("Color", "Tonemap", "clip = core.fmtc.bitdepth(clip, bits=16)" + BR + "clip = core.placebo.Tonemap(clip, src_csp=1, dst_csp=0, dynamic_peak_detection=0, tone_mapping_function=7)" + BR + $"clip = clip.resize.Bicubic(format = vs.YUV420P8)"))
|
|
End If
|
|
End If
|
|
End If
|
|
|
|
If p.CropWithHighContrast Then
|
|
If p.Script.Engine = ScriptEngine.AviSynth Then
|
|
script.Filters.Add(New VideoFilter("Levels", "Levels", "Levels(0, 2.2, 255, 0, 255, coring=true)"))
|
|
Else
|
|
script.Filters.Add(New VideoFilter("Levels", "Levels", "clip = adjust.Tweak(clip, hue=0, sat=1.75, bright=10, cont=1.75)"))
|
|
End If
|
|
End If
|
|
|
|
script.Synchronize(True, True, True)
|
|
|
|
FrameServer = FrameServerFactory.Create(script.Path)
|
|
Renderer = New VideoRenderer(pnVideo, FrameServer) With {
|
|
.Info = script.Info
|
|
}
|
|
|
|
If s.LastPosition < (FrameServer.Info.FrameCount - 1) Then
|
|
Renderer.Position = s.LastPosition
|
|
End If
|
|
|
|
tbPosition.Value = Renderer.Position
|
|
SelectBorder(AnchorStyles.Top)
|
|
UpdateAll()
|
|
|
|
If FrameServer.Error <> "" Then
|
|
MsgError("CROP", FrameServer.Error)
|
|
End If
|
|
End Sub
|
|
|
|
|
|
|
|
Protected Overrides Sub OnFormClosing(args As FormClosingEventArgs)
|
|
MyBase.OnFormClosing(args)
|
|
|
|
Dim err = p.Script.GetError
|
|
|
|
If err <> "" Then
|
|
Using td As New TaskDialog(Of String)
|
|
td.Title = "Script Error"
|
|
td.Icon = TaskIcon.Error
|
|
td.Content = err
|
|
td.AddButton("OK")
|
|
td.AddButton("Exit")
|
|
|
|
If td.Show() = "OK" Then
|
|
args.Cancel = True
|
|
Exit Sub
|
|
End If
|
|
End Using
|
|
End If
|
|
|
|
p.RemindToCrop = False
|
|
s.LastPosition = Renderer.Position
|
|
Renderer.Dispose()
|
|
FrameServer.Dispose()
|
|
End Sub
|
|
|
|
Sub TrackLength_Scroll() Handles tbPosition.Scroll
|
|
SetPos(tbPosition.Value)
|
|
End Sub
|
|
|
|
Sub SetPos(pos As Integer)
|
|
Try
|
|
Renderer.Position = pos
|
|
tbPosition.Value = Renderer.Position
|
|
Renderer.Draw()
|
|
UpdateAll()
|
|
Catch
|
|
End Try
|
|
End Sub
|
|
|
|
Protected Overrides Sub OnSizeChanged(args As EventArgs)
|
|
MyBase.OnSizeChanged(args)
|
|
Renderer?.Draw()
|
|
End Sub
|
|
|
|
Sub CropActiveSideInternal(x As Integer, opposite As Boolean)
|
|
Select Case Side
|
|
Case AnchorStyles.Left
|
|
p.CropLeft += x
|
|
|
|
If opposite Then
|
|
p.CropRight += x
|
|
End If
|
|
Case AnchorStyles.Top
|
|
p.CropTop += x
|
|
|
|
If opposite Then
|
|
p.CropBottom += x
|
|
End If
|
|
Case AnchorStyles.Right
|
|
p.CropRight += x
|
|
|
|
If opposite Then
|
|
p.CropLeft += x
|
|
End If
|
|
Case AnchorStyles.Bottom
|
|
p.CropBottom += x
|
|
|
|
If opposite Then
|
|
p.CropTop += x
|
|
End If
|
|
End Select
|
|
|
|
UpdateAll()
|
|
End Sub
|
|
|
|
Function GetSide(e As MouseEventArgs) As AnchorStyles
|
|
Dim factorX = p.SourceWidth / pnVideo.Width
|
|
Dim factorY = p.SourceHeight / pnVideo.Height
|
|
|
|
Dim leftSide = CInt(e.X * factorX)
|
|
Dim topSide = CInt(e.Y * factorY)
|
|
Dim rightSide = CInt((pnVideo.Width - e.X) * factorX)
|
|
Dim bottomSide = CInt((pnVideo.Height - e.Y) * factorY)
|
|
|
|
Dim sides As Integer() = {leftSide, topSide, rightSide, bottomSide}
|
|
Array.Sort(sides)
|
|
|
|
Select Case sides(0)
|
|
Case leftSide
|
|
Return AnchorStyles.Left
|
|
Case topSide
|
|
Return AnchorStyles.Top
|
|
Case rightSide
|
|
Return AnchorStyles.Right
|
|
Case bottomSide
|
|
Return AnchorStyles.Bottom
|
|
End Select
|
|
|
|
Return AnchorStyles.None
|
|
End Function
|
|
|
|
Sub MouseCrop(e As MouseEventArgs)
|
|
Dim scaleX = p.SourceWidth / pnVideo.Width
|
|
Dim scaleY = p.SourceHeight / pnVideo.Height
|
|
|
|
Dim leftSide = CInt(e.X * scaleX)
|
|
Dim topSide = CInt(e.Y * scaleY)
|
|
Dim rightSide = CInt((pnVideo.Width - e.X) * scaleX)
|
|
Dim bottomSide = CInt((pnVideo.Height - e.Y) * scaleY)
|
|
|
|
Select Case ActiveCropSide
|
|
Case AnchorStyles.Left
|
|
p.CropLeft = FixMod(leftSide)
|
|
Case AnchorStyles.Top
|
|
p.CropTop = FixMod(topSide)
|
|
Case AnchorStyles.Right
|
|
p.CropRight = FixMod(rightSide)
|
|
Case AnchorStyles.Bottom
|
|
p.CropBottom = FixMod(bottomSide)
|
|
End Select
|
|
|
|
UpdateAll()
|
|
End Sub
|
|
|
|
Sub MouseSelectBorder(e As MouseEventArgs)
|
|
SelectBorder(GetSide(e))
|
|
End Sub
|
|
|
|
Sub SelectBorder(borderSide As AnchorStyles)
|
|
Dim color = BorderSelectedColor
|
|
|
|
DeactivateActiveColor()
|
|
Select Case borderSide
|
|
Case AnchorStyles.Left
|
|
pnLeftActive.BackColor = color
|
|
Case AnchorStyles.Top
|
|
pnTopActive.BackColor = color
|
|
Case AnchorStyles.Right
|
|
pnRightActive.BackColor = color
|
|
Case AnchorStyles.Bottom
|
|
pnBottomActive.BackColor = color
|
|
End Select
|
|
Side = borderSide
|
|
End Sub
|
|
|
|
Sub DeactivateActiveColor()
|
|
Dim color = BorderColor
|
|
pnLeftActive.BackColor = color
|
|
pnTopActive.BackColor = color
|
|
pnRightActive.BackColor = color
|
|
pnBottomActive.BackColor = color
|
|
End Sub
|
|
|
|
|
|
Function FixMod(value As Integer) As Integer
|
|
If p.AutoCorrectCropValues AndAlso Not value Mod 2 = 0 Then
|
|
value += 1
|
|
End If
|
|
|
|
Return value
|
|
End Function
|
|
|
|
Sub UpdateAll()
|
|
Dim maxWidth = CInt(p.SourceWidth * 0.8)
|
|
Dim maxHeight = CInt(p.SourceHeight * 0.8)
|
|
|
|
If p.CropLeft > maxWidth Then
|
|
p.CropLeft = FixMod(maxWidth)
|
|
End If
|
|
|
|
If p.CropTop > maxHeight Then
|
|
p.CropTop = FixMod(maxHeight)
|
|
End If
|
|
|
|
If p.CropRight > maxWidth Then
|
|
p.CropRight = FixMod(maxWidth)
|
|
End If
|
|
|
|
If p.CropBottom > maxHeight Then
|
|
p.CropBottom = FixMod(maxHeight)
|
|
End If
|
|
|
|
Renderer.CropLeft = p.CropLeft
|
|
Renderer.CropTop = p.CropTop
|
|
Renderer.CropRight = p.CropRight
|
|
Renderer.CropBottom = p.CropBottom
|
|
Renderer.Draw()
|
|
|
|
Dim cropw = p.SourceWidth - p.CropLeft - p.CropRight
|
|
Dim croph = p.SourceHeight - p.CropTop - p.CropBottom
|
|
|
|
Dim time = "n/a"
|
|
If Renderer.Info.FrameRate > 0 Then
|
|
Dim lengthDate = Date.Today.AddSeconds(Renderer.Position / Renderer.Info.FrameRate)
|
|
time = lengthDate.ToString(If(lengthDate.Hour = 0, "mm:ss.fff", "HH:mm:ss.fff"))
|
|
End If
|
|
|
|
Dim isResized = p.Script.IsFilterActive("Resize")
|
|
Dim isValidAnamorphicSize = (p.TargetWidth = 1440 AndAlso p.TargetHeight = 1080) OrElse (p.TargetWidth = 960 AndAlso p.TargetHeight = 720)
|
|
Dim err = If(isResized AndAlso Not isValidAnamorphicSize, Calc.GetAspectRatioError.ToString("f2") + "%", "n/a")
|
|
|
|
laStatus.Text =
|
|
" Frame: " & Renderer.Position.ToString().PadLeft(6) &
|
|
" | Time: " & time &
|
|
" | Size: " & cropw & "/" & croph &
|
|
" | X: " & p.CropLeft & "/" & p.CropRight &
|
|
" | Y: " & p.CropTop & "/" & p.CropBottom &
|
|
" | Mod: " + Calc.GetMod(cropw, croph, False) +
|
|
" | Error: " + err +
|
|
" | DAR: " + Calc.GetTargetDAR().ToString("f6")
|
|
End Sub
|
|
|
|
Sub pVideo_MouseMove(sender As Object, e As MouseEventArgs) Handles pnVideo.MouseMove
|
|
If Control.MouseButtons = Windows.Forms.MouseButtons.Left Then
|
|
MouseCrop(e)
|
|
Else
|
|
MouseSelectBorder(e)
|
|
End If
|
|
End Sub
|
|
|
|
Sub pVideo_MouseDown(sender As Object, e As MouseEventArgs) Handles pnVideo.MouseDown
|
|
If Control.MouseButtons = Windows.Forms.MouseButtons.Left Then
|
|
ActiveCropSide = GetSide(e)
|
|
MouseCrop(e)
|
|
End If
|
|
End Sub
|
|
|
|
Sub pVideo_Paint(sender As Object, e As PaintEventArgs) Handles pnVideo.Paint
|
|
Renderer?.Draw()
|
|
End Sub
|
|
|
|
Sub tbPosition_Enter() Handles tbPosition.Enter
|
|
ActiveControl = Nothing
|
|
End Sub
|
|
|
|
Sub SetDialogSize(w As Integer, h As Integer)
|
|
ClientSize = New Size(ClientSize.Width + w - pnVideo.Width, ClientSize.Height + h - pnVideo.Height)
|
|
Renderer?.Draw()
|
|
End Sub
|
|
|
|
Protected Overrides Function IsInputKey(keyData As Keys) As Boolean
|
|
Select Case keyData
|
|
Case Keys.Left, Keys.Up, Keys.Right, Keys.Down
|
|
Return True
|
|
Case Else
|
|
Return MyBase.IsInputKey(keyData)
|
|
End Select
|
|
End Function
|
|
|
|
Shared Function GetDefaultMenuCrop() As CustomMenuItem
|
|
Dim ret As New CustomMenuItem("Root")
|
|
Dim minusKey = If(Not KeysHelp.IsNumPadInstalled, Keys.Subtract, Keys.OemMinus)
|
|
Dim plusKey = If(Not KeysHelp.IsNumPadInstalled, Keys.Add, Keys.Oemplus)
|
|
|
|
ret.Add("No Crop", NameOf(SetCropValues), Keys.N, {0, 0, 0, 0})
|
|
ret.Add("Auto Crop", NameOf(RunAutoCrop), Keys.A)
|
|
ret.Add("Smart Crop", NameOf(RunSmartCrop), Keys.S)
|
|
ret.Add("-")
|
|
ret.Add("Increase Active Side", NameOf(CropActiveSide), plusKey, {2, 2})
|
|
ret.Add("Decrease Active Side", NameOf(CropActiveSide), minusKey, {-2, -2})
|
|
ret.Add("-")
|
|
ret.Add("Increase Active Side Large", NameOf(CropActiveSide), plusKey Or Keys.Shift, {8, 8})
|
|
ret.Add("Decrease Active Side Large", NameOf(CropActiveSide), minusKey Or Keys.Shift, {-8, -8})
|
|
ret.Add("-")
|
|
ret.Add("Increase Active And Opposite Side", NameOf(CropActiveAndOppositeSide), plusKey Or Keys.Control, {2, 2})
|
|
ret.Add("Decrease Active And Opposite Side", NameOf(CropActiveAndOppositeSide), minusKey Or Keys.Control, {-2, -2})
|
|
ret.Add("-")
|
|
ret.Add("Increase Active And Opposite Side Large", NameOf(CropActiveAndOppositeSide), plusKey Or Keys.Control Or Keys.Shift, {8, 8})
|
|
ret.Add("Decrease Active And Opposite Side Large", NameOf(CropActiveAndOppositeSide), minusKey Or Keys.Control Or Keys.Shift, {-8, -8})
|
|
ret.Add("-")
|
|
ret.Add("Navigation|Go To Frame...", NameOf(GoToFrame), Keys.F)
|
|
ret.Add("Navigation|Go To Time...", NameOf(GoToTime), Keys.T)
|
|
ret.Add("Navigation|-")
|
|
ret.Add("Navigation|Go To Start", NameOf(SetAbsolutePosition), Keys.Control Or Keys.Left, {0})
|
|
ret.Add("Navigation|100 Frames Backward", NameOf(SetRelativePosition), Keys.PageUp, {-100})
|
|
ret.Add("Navigation|1000 Frames Backward", NameOf(SetRelativePosition), Keys.PageUp Or Keys.Control, {-1000})
|
|
ret.Add("Navigation|-")
|
|
ret.Add("Navigation|100 Frames Forward", NameOf(SetRelativePosition), Keys.PageDown, {100})
|
|
ret.Add("Navigation|1000 Frames Forward", NameOf(SetRelativePosition), Keys.PageDown Or Keys.Control, {1000})
|
|
ret.Add("Navigation|Go To End", NameOf(SetAbsolutePosition), Keys.Control Or Keys.Right, {1000000000})
|
|
ret.Add("-")
|
|
ret.Add("Crop Color | Theme", NameOf(SetCropColor), {Color.Empty})
|
|
ret.Add("Crop Color | White", NameOf(SetCropColor), {Color.White})
|
|
ret.Add("Crop Color | Black", NameOf(SetCropColor), {Color.Black})
|
|
ret.Add("Crop Color | Light Gray", NameOf(SetCropColor), {Color.LightGray})
|
|
ret.Add("Crop Options...", NameOf(ShowOptions), Keys.O, Symbol.Settings)
|
|
ret.Add("Edit Menu...", NameOf(ShowMenuEditor), Keys.M)
|
|
ret.Add("Help...", NameOf(ShowHelpDialog), Keys.F1, Symbol.Help)
|
|
ret.Add("Exit", NameOf(CloseDialog), Keys.Escape)
|
|
|
|
Return ret
|
|
End Function
|
|
|
|
<Command("Sets the four crop values.")>
|
|
Sub SetCropValues(
|
|
left As Integer,
|
|
top As Integer,
|
|
right As Integer,
|
|
bottom As Integer)
|
|
|
|
p.CropLeft = left
|
|
p.CropTop = top
|
|
p.CropRight = right
|
|
p.CropBottom = bottom
|
|
|
|
UpdateAll()
|
|
End Sub
|
|
|
|
<Command("Crops the active side.")>
|
|
Sub CropActiveSide(
|
|
<DispName("Pixel (corrected)"),
|
|
Description("Pixels to crop when 'Auto correct crop values' is enabled.")>
|
|
valueSafe As Integer,
|
|
<DispName("Pixel (uncorrected)"),
|
|
Description("Pixels to crop when 'Auto correct crop values' is disabled.")>
|
|
valueUnsafe As Integer)
|
|
|
|
CropActiveSideInternal(FixMod(If(p.AutoCorrectCropValues, valueSafe, valueUnsafe)), False)
|
|
End Sub
|
|
|
|
<Command("Crops the active and the opposite side of the active side")>
|
|
Sub CropActiveAndOppositeSide(
|
|
<DispName("Pixel (corrected)"),
|
|
Description("Pixels to crop when 'Auto correct crop values' is enabled.")>
|
|
valueSafe As Integer,
|
|
<DispName("Pixel (uncorrected)"),
|
|
Description("Pixels to crop when 'Auto correct crop values' is disabled.")>
|
|
valueUnsafe As Integer)
|
|
|
|
CropActiveSideInternal(FixMod(If(p.AutoCorrectCropValues, valueSafe, valueUnsafe)), True)
|
|
End Sub
|
|
|
|
<Command("Detects the crop values automatically.")>
|
|
Sub RunAutoCrop()
|
|
Dim isDV = p.HdrDolbyVisionMetadataFile IsNot Nothing AndAlso p.VideoEncoder.IsDolbyVisionSet
|
|
|
|
If Not isDV Then
|
|
p.CropLeft = 0
|
|
p.CropTop = 0
|
|
p.CropRight = 0
|
|
p.CropBottom = 0
|
|
UpdateAll()
|
|
End If
|
|
|
|
g.RunAutoCrop(Sub(progress As Double)
|
|
tbPosition.Value = CInt(tbPosition.Maximum / 100 * progress)
|
|
TrackLength_Scroll()
|
|
Application.DoEvents()
|
|
End Sub)
|
|
UpdateAll()
|
|
|
|
If Not isDV Then
|
|
tbPosition.Value = 0
|
|
TrackLength_Scroll()
|
|
End If
|
|
End Sub
|
|
|
|
<Command("Crops until the proper aspect ratio is found.")>
|
|
Sub RunSmartCrop()
|
|
g.SmartCrop()
|
|
UpdateAll()
|
|
End Sub
|
|
|
|
<Command("Dialog to configure the menu.")>
|
|
Sub ShowMenuEditor()
|
|
s.CustomMenuCrop = CustomMenu.Edit()
|
|
g.SaveSettings()
|
|
End Sub
|
|
|
|
<Command("Exits the dialog.")>
|
|
Sub CloseDialog()
|
|
Close()
|
|
End Sub
|
|
|
|
<Command("Shows a dialog with crop options.")>
|
|
Sub ShowOptions()
|
|
g.MainForm.ShowOptionsDialog("Image | Crop")
|
|
UpdateAll()
|
|
End Sub
|
|
|
|
<Command("Sets the color used for cropping.")>
|
|
Sub SetCropColor(Color As Color)
|
|
s.CropColor = Color
|
|
Renderer.ApplyTheme()
|
|
Renderer.Draw()
|
|
End Sub
|
|
|
|
<Command("Dialog to jump to a specific time.")>
|
|
Sub GoToTime()
|
|
Dim d As Date
|
|
d = d.AddSeconds(Renderer.Position / FrameServer.FrameRate)
|
|
Dim value = InputBox.Show("Go To Time", d.ToString("HH:mm:ss.fff"))
|
|
|
|
If value <> "" Then
|
|
SetPos(CInt((TimeSpan.Parse(value).TotalMilliseconds / 1000) * FrameServer.FrameRate))
|
|
End If
|
|
End Sub
|
|
|
|
<Command("Dialog to jump to a specific frame.")>
|
|
Sub GoToFrame()
|
|
Dim value = InputBox.Show("Go To Frame", Renderer.Position.ToString)
|
|
Dim pos As Integer
|
|
|
|
If Integer.TryParse(value, pos) Then
|
|
SetPos(pos)
|
|
End If
|
|
End Sub
|
|
|
|
<Command("Jumps to a given frame.")>
|
|
Sub SetAbsolutePosition(<DispName("Position")> pos As Integer)
|
|
SetPos(pos)
|
|
End Sub
|
|
|
|
<Command("Jumps a given frame count.")>
|
|
Sub SetRelativePosition(<DispName("Offset"), Description("Frames to jump, negative values jump backward.")> offset As Integer)
|
|
Renderer.Position += offset
|
|
tbPosition.Value = Renderer.Position
|
|
Renderer.Draw()
|
|
UpdateAll()
|
|
End Sub
|
|
|
|
<Command("Opens the help of the crop dialog.")>
|
|
Sub ShowHelpDialog()
|
|
Dim form As New HelpForm()
|
|
form.Doc.WriteStart("Crop Dialog")
|
|
form.Doc.WriteParagraph("The crop dialog allows to crop borders. Right-click to show a '''context menu''' with available features. By default StaxRip detects the crop values automatically. It's recommended to check the detected values visually. A crop value can be changed roughly by moving the mouse while the left mouse button is pressed. Alternative methods are using the '''mousewheel''' or keyboard shortcuts. The Ctrl key crops the active and opposite side, the Shift key crops 8 instead of 2 pixel.")
|
|
form.Doc.WriteTips(CustomMenu.GetTips)
|
|
form.Doc.WriteTable("Shortcut Keys", CustomMenu.GetKeys, False)
|
|
form.Show()
|
|
End Sub
|
|
|
|
Protected Overrides Sub OnHelpButtonClicked(e As CancelEventArgs)
|
|
e.Cancel = True
|
|
ShowHelpDialog()
|
|
End Sub
|
|
|
|
Protected Overrides Sub OnMouseWheel(args As MouseEventArgs)
|
|
MyBase.OnMouseWheel(args)
|
|
|
|
Dim value = 2
|
|
value = If((Control.ModifierKeys And Keys.Shift) = Keys.Shift, 8, value)
|
|
value = If(args.Delta > 0, value, value * -1)
|
|
CropActiveSideInternal(value, (Control.ModifierKeys And Keys.Control) = Keys.Control)
|
|
End Sub
|
|
|
|
Sub tsbMenu_Click(sender As Object, e As EventArgs) Handles tsbMenu.Click
|
|
ContextMenuStrip.Show(MousePosition)
|
|
End Sub
|
|
|
|
End Class
|