feat(chromium): allow to specify device scale ratio for screenshots (#1543)

This commit is contained in:
Heorhii Ovcharenko
2026-05-04 22:16:04 +03:00
committed by GitHub
parent fe1b0020b8
commit c1cdcbdaab
8 changed files with 43 additions and 23 deletions

View File

@@ -34,6 +34,7 @@ body:multipart-form {
~emulatedMediaType: screen ~emulatedMediaType: screen
~emulatedMediaFeatures: {"prefers-color-scheme":"dark"} ~emulatedMediaFeatures: {"prefers-color-scheme":"dark"}
~omitBackground: false ~omitBackground: false
~deviceScaleFactor: 1.0
} }
headers { headers {

View File

@@ -35,6 +35,7 @@ body:multipart-form {
~emulatedMediaType: screen ~emulatedMediaType: screen
~emulatedMediaFeatures: {"prefers-color-scheme":"dark"} ~emulatedMediaFeatures: {"prefers-color-scheme":"dark"}
~omitBackground: false ~omitBackground: false
~deviceScaleFactor: 1.0
} }
headers { headers {

View File

@@ -34,6 +34,7 @@ body:multipart-form {
~emulatedMediaType: screen ~emulatedMediaType: screen
~emulatedMediaFeatures: {"prefers-color-scheme":"dark"} ~emulatedMediaFeatures: {"prefers-color-scheme":"dark"}
~omitBackground: false ~omitBackground: false
~deviceScaleFactor: 1.0
} }
headers { headers {

View File

@@ -351,7 +351,7 @@ func (b *chromiumBrowser) screenshot(ctx context.Context, logger *slog.Logger, u
waitForSelectorVisibleBeforePrintActionFunc(logger, options.WaitForSelector), waitForSelectorVisibleBeforePrintActionFunc(logger, options.WaitForSelector),
waitDelayBeforePrintActionFunc(logger, b.arguments.disableJavaScript, options.WaitDelay), waitDelayBeforePrintActionFunc(logger, b.arguments.disableJavaScript, options.WaitDelay),
// Screenshot specific. // Screenshot specific.
setDeviceMetricsOverride(logger, options.Width, options.Height), setDeviceMetricsOverride(logger, options.Width, options.Height, options.DeviceScaleFactor),
captureScreenshotActionFunc(logger, outputPath, options), captureScreenshotActionFunc(logger, outputPath, options),
// Teardown. // Teardown.
page.Close(), page.Close(),

View File

@@ -350,18 +350,23 @@ type ScreenshotOptions struct {
// OptimizeForSpeed defines whether to optimize image encoding for speed, // OptimizeForSpeed defines whether to optimize image encoding for speed,
// not for resulting size. // not for resulting size.
OptimizeForSpeed bool OptimizeForSpeed bool
// DeviceScaleFactor is the ratio of the resolution in physical pixels to
// the resolution in CSS pixels for the current display device.
DeviceScaleFactor float64
} }
// DefaultScreenshotOptions returns the default values for ScreenshotOptions. // DefaultScreenshotOptions returns the default values for ScreenshotOptions.
func DefaultScreenshotOptions() ScreenshotOptions { func DefaultScreenshotOptions() ScreenshotOptions {
return ScreenshotOptions{ return ScreenshotOptions{
Options: DefaultOptions(), Options: DefaultOptions(),
Width: 800, Width: 800,
Height: 600, Height: 600,
Clip: false, Clip: false,
Format: "png", Format: "png",
Quality: 100, Quality: 100,
OptimizeForSpeed: false, OptimizeForSpeed: false,
DeviceScaleFactor: 1.0,
} }
} }

View File

@@ -341,11 +341,12 @@ func FormDataChromiumScreenshotOptions(ctx *api.Context) (*api.FormData, Screens
defaultScreenshotOptions := DefaultScreenshotOptions() defaultScreenshotOptions := DefaultScreenshotOptions()
var ( var (
width, height int width, height int
clip bool clip bool
format string format string
quality int quality int
optimizeForSpeed bool optimizeForSpeed bool
deviceScaleFactor float64
) )
form. form.
@@ -388,16 +389,18 @@ func FormDataChromiumScreenshotOptions(ctx *api.Context) (*api.FormData, Screens
quality = intValue quality = intValue
return nil return nil
}). }).
Bool("optimizeForSpeed", &optimizeForSpeed, defaultScreenshotOptions.OptimizeForSpeed) Bool("optimizeForSpeed", &optimizeForSpeed, defaultScreenshotOptions.OptimizeForSpeed).
Float64("deviceScaleFactor", &deviceScaleFactor, defaultScreenshotOptions.DeviceScaleFactor)
screenshotOptions := ScreenshotOptions{ screenshotOptions := ScreenshotOptions{
Options: options, Options: options,
Width: width, Width: width,
Height: height, Height: height,
Clip: clip, Clip: clip,
Format: format, Format: format,
Quality: quality, Quality: quality,
OptimizeForSpeed: optimizeForSpeed, OptimizeForSpeed: optimizeForSpeed,
DeviceScaleFactor: deviceScaleFactor,
} }
return form, screenshotOptions return form, screenshotOptions

View File

@@ -164,11 +164,11 @@ func captureScreenshotActionFunc(logger *slog.Logger, outputPath string, options
} }
} }
func setDeviceMetricsOverride(logger *slog.Logger, width, height int) chromedp.ActionFunc { func setDeviceMetricsOverride(logger *slog.Logger, width, height int, deviceScaleFactor float64) chromedp.ActionFunc {
return func(ctx context.Context) error { return func(ctx context.Context) error {
logger.DebugContext(ctx, "set device metrics override") logger.DebugContext(ctx, "set device metrics override")
err := emulation.SetDeviceMetricsOverride(int64(width), int64(height), 1.0, false).Do(ctx) err := emulation.SetDeviceMetricsOverride(int64(width), int64(height), deviceScaleFactor, false).Do(ctx)
if err == nil { if err == nil {
return nil return nil
} }

View File

@@ -72,6 +72,15 @@ Feature: /forms/chromium/screenshot/html
Then the response status code should be 200 Then the response status code should be 200
Then the response header "Content-Type" should be "image/png" Then the response header "Content-Type" should be "image/png"
Scenario: POST /forms/chromium/screenshot/html (Device Scale Factor)
Given I have a default Gotenberg container
When I make a "POST" request to Gotenberg at the "/forms/chromium/screenshot/html" endpoint with the following form data and header(s):
| files | testdata/page-1-html/index.html | file |
| deviceScaleFactor | 1.0 | field |
| Gotenberg-Output-Filename | foo | header |
Then the response status code should be 200
Then the response header "Content-Type" should be "image/png"
Scenario: POST /forms/chromium/screenshot/html (Omit Background) Scenario: POST /forms/chromium/screenshot/html (Omit Background)
Given I have a default Gotenberg container Given I have a default Gotenberg container
When I make a "POST" request to Gotenberg at the "/forms/chromium/screenshot/html" endpoint with the following form data and header(s): When I make a "POST" request to Gotenberg at the "/forms/chromium/screenshot/html" endpoint with the following form data and header(s):