feat: add autoZoom param to GIF/MP4 renderers

Adjusts camera distance multiplier from 1.5 to 1.25 when enabled,
reducing empty space around character while leaving room for cosmetics.
This commit is contained in:
devilreef 2026-01-23 01:51:07 +06:00
parent f8947fdcc4
commit fcc495c06f
7 changed files with 29 additions and 13 deletions

View file

@ -66,7 +66,7 @@ func (h *Handlers) HandlePNG(w http.ResponseWriter, r *http.Request) {
return
}
pngBytes, err := render.RenderPNG(result.GLBBytes, result.Atlas, req.Rotation, req.Background, req.Width, req.Height)
pngBytes, err := render.RenderPNG(result.GLBBytes, result.Atlas, req.Rotation, req.Background, req.Width, req.Height, true)
if err != nil {
writeError(w, http.StatusInternalServerError, "render failed: "+err.Error())
return
@ -103,7 +103,7 @@ func (h *Handlers) HandleGIF(w http.ResponseWriter, r *http.Request) {
return
}
gifBytes, err := render.RenderGIF(result.GLBBytes, result.Atlas, req.Background, req.Frames, req.Width, req.Height, req.Delay, *req.Dithering)
gifBytes, err := render.RenderGIF(result.GLBBytes, result.Atlas, req.Background, req.Frames, req.Width, req.Height, req.Delay, *req.Dithering, *req.AutoZoom)
if err != nil {
writeError(w, http.StatusInternalServerError, "render failed: "+err.Error())
return
@ -140,7 +140,7 @@ func (h *Handlers) HandleMP4(w http.ResponseWriter, r *http.Request) {
return
}
mp4Bytes, err := render.RenderMP4(result.GLBBytes, result.Atlas, req.Background, req.Frames, req.Width, req.Height, req.FPS)
mp4Bytes, err := render.RenderMP4(result.GLBBytes, result.Atlas, req.Background, req.Frames, req.Width, req.Height, req.FPS, *req.AutoZoom)
if err != nil {
writeError(w, http.StatusInternalServerError, "render failed: "+err.Error())
return

View file

@ -238,7 +238,8 @@ const OpenAPISpec = `{
"width": {"type": "integer", "default": 512, "description": "Image width in pixels"},
"height": {"type": "integer", "default": 512, "description": "Image height in pixels"},
"delay": {"type": "integer", "default": 5, "description": "Centiseconds between frames"},
"dithering": {"type": "boolean", "default": true, "description": "Enable Floyd-Steinberg dithering (disable for faster rendering)"}
"dithering": {"type": "boolean", "default": true, "description": "Enable Floyd-Steinberg dithering (disable for faster rendering)"},
"autoZoom": {"type": "boolean", "default": true, "description": "Auto-zoom camera to fit character tightly in frame"}
}
},
"MP4Request": {
@ -250,7 +251,8 @@ const OpenAPISpec = `{
"frames": {"type": "integer", "default": 36, "description": "Number of frames (36 = 10° per frame)"},
"width": {"type": "integer", "default": 512, "description": "Video width in pixels"},
"height": {"type": "integer", "default": 512, "description": "Video height in pixels"},
"fps": {"type": "integer", "default": 12, "description": "Frames per second"}
"fps": {"type": "integer", "default": 12, "description": "Frames per second"},
"autoZoom": {"type": "boolean", "default": true, "description": "Auto-zoom camera to fit character tightly in frame"}
}
},
"ErrorResponse": {

View file

@ -20,6 +20,7 @@ type GIFRequest struct {
Height int `json:"height"` // default 512
Delay int `json:"delay"` // centiseconds between frames, default 5
Dithering *bool `json:"dithering"` // Floyd-Steinberg dithering, default true
AutoZoom *bool `json:"autoZoom"` // auto-zoom to fit character, default true
}
// MP4Request represents a request to render a character as MP4 video
@ -30,6 +31,7 @@ type MP4Request struct {
Width int `json:"width"` // default 512
Height int `json:"height"` // default 512
FPS int `json:"fps"` // frames per second, default 12
AutoZoom *bool `json:"autoZoom"` // auto-zoom to fit character, default true
}
// ErrorResponse represents an error returned by the API
@ -71,6 +73,10 @@ func (r *GIFRequest) ApplyDefaults() {
defaultDithering := true
r.Dithering = &defaultDithering
}
if r.AutoZoom == nil {
defaultAutoZoom := true
r.AutoZoom = &defaultAutoZoom
}
}
// ApplyDefaults fills in default values for MP4Request
@ -90,4 +96,8 @@ func (r *MP4Request) ApplyDefaults() {
if r.Background == "" {
r.Background = "#FFFFFF"
}
if r.AutoZoom == nil {
defaultAutoZoom := true
r.AutoZoom = &defaultAutoZoom
}
}