feat: screen capture scaling / downsampling
Add a Scale option (1.0 native, 0.5 half, etc.) that downsamples the captured BGRA frame with bilinear interpolation before JPEG encoding. Config carries the scale factor; the GUI exposes a Scale dropdown (100%/75%/50%/25%) that applies live via SetConfig. Verified: OBS displays the image at the reduced resolution matching the selected scale, without restarting the stream.
This commit is contained in:
@@ -36,6 +36,34 @@ func itoa(v int) string { return strconv.Itoa(v) }
|
||||
|
||||
func atoi(s string) (int, error) { return strconv.Atoi(s) }
|
||||
|
||||
// scaleLabel renders a scale factor as a percentage option.
|
||||
func scaleLabel(scale float64) string {
|
||||
switch {
|
||||
case scale >= 0.95:
|
||||
return "100%"
|
||||
case scale >= 0.7:
|
||||
return "75%"
|
||||
case scale >= 0.45:
|
||||
return "50%"
|
||||
default:
|
||||
return "25%"
|
||||
}
|
||||
}
|
||||
|
||||
// parseScale converts a scale option label back to a factor.
|
||||
func parseScale(label string) float64 {
|
||||
switch label {
|
||||
case "75%":
|
||||
return 0.75
|
||||
case "50%":
|
||||
return 0.5
|
||||
case "25%":
|
||||
return 0.25
|
||||
default:
|
||||
return 1.0
|
||||
}
|
||||
}
|
||||
|
||||
// appID is the Fyne application ID used for preferences/settings storage.
|
||||
const appID = "io.teleportfling"
|
||||
|
||||
@@ -62,6 +90,7 @@ type App struct {
|
||||
qualitySel *widget.Select
|
||||
fpsSel *widget.Select
|
||||
presetSel *widget.Select
|
||||
scaleSel *widget.Select
|
||||
nameEnt *widget.Entry
|
||||
audioChk *widget.Check
|
||||
announceChk *widget.Check
|
||||
@@ -148,6 +177,10 @@ func (g *App) buildUI() {
|
||||
g.fpsSel = widget.NewSelect([]string{"15", "30", "60"}, g.applyLiveSettings)
|
||||
g.fpsSel.SetSelected(itoa(g.cfg.FPS))
|
||||
|
||||
// Scale: downsampling factor (1.0 = native, 0.5 = half, etc).
|
||||
g.scaleSel = widget.NewSelect([]string{"100%", "75%", "50%", "25%"}, g.applyLiveSettings)
|
||||
g.scaleSel.SetSelected(scaleLabel(g.cfg.Scale))
|
||||
|
||||
// Preset: one-click quality/fps combos. Choosing one sets the Quality and
|
||||
// Frame rate selectors and applies them (live if running). Created after
|
||||
// the quality/fps selects so applyPreset's references are valid.
|
||||
@@ -183,6 +216,7 @@ func (g *App) buildUI() {
|
||||
{Text: "Preset", Widget: g.presetSel},
|
||||
{Text: "Quality", Widget: g.qualitySel},
|
||||
{Text: "Frame rate", Widget: g.fpsSel},
|
||||
{Text: "Scale", Widget: g.scaleSel},
|
||||
{Text: "", Widget: g.audioChk},
|
||||
{Text: "", Widget: g.announceChk},
|
||||
},
|
||||
@@ -287,6 +321,7 @@ func (g *App) applyLiveSettings(string) {
|
||||
Source: g.cfg.Source,
|
||||
Audio: g.audioChk.Checked,
|
||||
StreamIndex: g.cfg.StreamIndex,
|
||||
Scale: parseScale(g.scaleSel.Selected),
|
||||
Announce: announce,
|
||||
}
|
||||
if err := g.eng.SetConfig(cfg); err != nil {
|
||||
@@ -298,6 +333,7 @@ func (g *App) applyLiveSettings(string) {
|
||||
g.cfg.FPS = fps
|
||||
g.cfg.Audio = cfg.Audio
|
||||
g.cfg.Name = cfg.Name
|
||||
g.cfg.Scale = cfg.Scale
|
||||
ann := announce
|
||||
g.cfg.Announce = &ann
|
||||
}
|
||||
@@ -329,6 +365,7 @@ func (g *App) start() {
|
||||
Source: g.srcSel.Selected,
|
||||
Audio: g.audioChk.Checked,
|
||||
StreamIndex: g.selectedMonitorIndex(),
|
||||
Scale: parseScale(g.scaleSel.Selected),
|
||||
Announce: &announce,
|
||||
}
|
||||
if g.configPath != "" {
|
||||
|
||||
Reference in New Issue
Block a user