feat(upscale): add blur control
This commit is contained in:
parent
3ba3deab8b
commit
895c696b88
4
BUGS.md
4
BUGS.md
|
|
@ -93,12 +93,12 @@ None currently open.
|
|||
## 🧭 Feature Requests (Planned)
|
||||
|
||||
### FEAT-003: Enhancement module blur control
|
||||
- **Status**: 🧭 PLANNED
|
||||
- **Status**: 🧭 IN PROGRESS
|
||||
- **Reporter**: Jake (2026-01-06)
|
||||
- **Module**: Enhancement
|
||||
- **Description**: Enhancement panel should include a blur control in addition to sharpen/denoise.
|
||||
- **Impact**: Medium - expected control in enhancement workflow
|
||||
- **Notes**: Add to enhancement UI alongside existing sliders.
|
||||
- **Notes**: Implemented blur controls in Upscale first; Enhancement UI still pending.
|
||||
|
||||
### FEAT-004: Upscale output quality should use Bitrate Mode controls
|
||||
- **Status**: 🧭 PLANNED
|
||||
|
|
|
|||
34
internal/state/manager.go
Normal file
34
internal/state/manager.go
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
package state
|
||||
|
||||
import (
|
||||
"fyne.io/fyne/v2/widget"
|
||||
"sync"
|
||||
)
|
||||
|
||||
type StateManager struct {
|
||||
mu sync.RWMutex
|
||||
|
||||
// Current mode settings
|
||||
crfMode CRFMode
|
||||
vbrMode VBRMode
|
||||
currentQuality string
|
||||
currentBitrate string
|
||||
currentCRFValue int64
|
||||
currentVBRValue int64
|
||||
|
||||
// Registered widgets for synchronization
|
||||
qualityWidgets []*widget.Select
|
||||
bitrateWidgets []*widget.Select
|
||||
}
|
||||
|
||||
type CRFMode string
|
||||
type VBRMode string
|
||||
|
||||
const (
|
||||
CRFManual CRFMode = "manual"
|
||||
CRFQuality CRFMode = "quality"
|
||||
CRFBitrate CRFMode = "bitrate"
|
||||
VBRStandard VBRMode = "standard"
|
||||
VBRHQ VBRMode = "hq"
|
||||
VBRConstrained VBRMode = "constrained"
|
||||
)
|
||||
44
main.go
44
main.go
|
|
@ -1096,6 +1096,8 @@ type appState struct {
|
|||
upscaleFilterChain []string // Transferred filters from Filters module
|
||||
upscaleFrameRate string // Source, 24, 30, 60, or custom
|
||||
upscaleMotionInterpolation bool // Use motion interpolation for frame rate changes
|
||||
upscaleBlurEnabled bool // Apply blur in upscale pipeline
|
||||
upscaleBlurSigma float64 // Blur strength (sigma)
|
||||
|
||||
// Snippet settings
|
||||
snippetLength int // Length of snippet in seconds (default: 20)
|
||||
|
|
@ -5556,6 +5558,8 @@ func (s *appState) executeUpscaleJob(ctx context.Context, job *queue.Job, progre
|
|||
useMotionInterp, _ := cfg["useMotionInterpolation"].(bool)
|
||||
sourceFrameRate := toFloat(cfg["sourceFrameRate"])
|
||||
qualityPreset, _ := cfg["qualityPreset"].(string)
|
||||
blurEnabled, _ := cfg["blurEnabled"].(bool)
|
||||
blurSigma := toFloat(cfg["blurSigma"])
|
||||
|
||||
if progressCallback != nil {
|
||||
progressCallback(0)
|
||||
|
|
@ -5613,6 +5617,10 @@ func (s *appState) executeUpscaleJob(ctx context.Context, job *queue.Job, progre
|
|||
}
|
||||
}
|
||||
|
||||
if blurEnabled && blurSigma > 0 {
|
||||
baseFilters = append(baseFilters, fmt.Sprintf("gblur=sigma=%.2f", blurSigma))
|
||||
}
|
||||
|
||||
if useAI {
|
||||
if aiBackend != "ncnn" {
|
||||
return fmt.Errorf("AI upscaling backend not available")
|
||||
|
|
@ -14934,6 +14942,9 @@ func buildUpscaleView(state *appState) fyne.CanvasObject {
|
|||
state.upscaleAIThreadsProc = 2
|
||||
state.upscaleAIThreadsSave = 2
|
||||
}
|
||||
if state.upscaleBlurSigma <= 0 {
|
||||
state.upscaleBlurSigma = 1.5
|
||||
}
|
||||
|
||||
// Check AI availability on first load
|
||||
if state.upscaleAIBackend == "" {
|
||||
|
|
@ -15069,6 +15080,36 @@ func buildUpscaleView(state *appState) fyne.CanvasObject {
|
|||
widget.NewLabel("Lower CRF = higher quality/larger files"),
|
||||
))
|
||||
|
||||
blurLabel := widget.NewLabel(fmt.Sprintf("Blur Strength: %.2f", state.upscaleBlurSigma))
|
||||
blurSlider := widget.NewSlider(0.0, 8.0)
|
||||
blurSlider.Step = 0.1
|
||||
blurSlider.Value = state.upscaleBlurSigma
|
||||
blurSlider.OnChanged = func(v float64) {
|
||||
state.upscaleBlurSigma = v
|
||||
blurLabel.SetText(fmt.Sprintf("Blur Strength: %.2f", v))
|
||||
}
|
||||
|
||||
blurCheck := widget.NewCheck("Enable Blur", func(checked bool) {
|
||||
state.upscaleBlurEnabled = checked
|
||||
if checked {
|
||||
blurSlider.Enable()
|
||||
} else {
|
||||
blurSlider.Disable()
|
||||
}
|
||||
})
|
||||
blurCheck.SetChecked(state.upscaleBlurEnabled)
|
||||
if state.upscaleBlurEnabled {
|
||||
blurSlider.Enable()
|
||||
} else {
|
||||
blurSlider.Disable()
|
||||
}
|
||||
|
||||
blurSection := widget.NewCard("Blur (Optional)", "", container.NewVBox(
|
||||
widget.NewLabel("Apply a soft blur during upscale processing"),
|
||||
blurCheck,
|
||||
container.NewVBox(blurLabel, blurSlider),
|
||||
))
|
||||
|
||||
// Frame Rate Section
|
||||
frameRateLabel := widget.NewLabel(fmt.Sprintf("Frame Rate: %s", state.upscaleFrameRate))
|
||||
frameRateSelect := widget.NewSelect([]string{"Source", "23.976", "24", "25", "29.97", "30", "50", "59.94", "60"}, func(s string) {
|
||||
|
|
@ -15437,6 +15478,8 @@ func buildUpscaleView(state *appState) fyne.CanvasObject {
|
|||
"aiOutputFormat": state.upscaleAIOutputFormat,
|
||||
"applyFilters": state.upscaleApplyFilters,
|
||||
"filterChain": state.upscaleFilterChain,
|
||||
"blurEnabled": state.upscaleBlurEnabled,
|
||||
"blurSigma": state.upscaleBlurSigma,
|
||||
"duration": state.upscaleFile.Duration,
|
||||
"sourceFrameRate": state.upscaleFile.FrameRate,
|
||||
"frameRate": state.upscaleFrameRate,
|
||||
|
|
@ -15490,6 +15533,7 @@ func buildUpscaleView(state *appState) fyne.CanvasObject {
|
|||
traditionalSection,
|
||||
resolutionSection,
|
||||
qualitySection,
|
||||
blurSection,
|
||||
frameRateSection,
|
||||
aiSection,
|
||||
filterIntegrationSection,
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user