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:
2026-09-19 20:33:40 +01:00
parent 583274d9e6
commit aab2006e78
4 changed files with 184 additions and 8 deletions
+37
View File
@@ -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 != "" {