mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-01 14:58:14 +00:00
Headless: force opaque PNG screenshots by default, add --screenshot-keep-alpha
Games often use the framebuffer alpha channel for non-visual purposes, so saved PNGs could look fully transparent in image viewers. Force alpha to 255 when writing PNG screenshots unless --screenshot-keep-alpha is passed. The MSE comparison ignores alpha either way.
This commit is contained in:
1 parent
032781e301
commit
8c9bf04add
7 files changed
+19
-4
No files matched your search
@@ -183,6 +183,7 @@ static const CommandLineParam g_autoParams[] = {
|
||||
{POFF(screenshotFilename), CmdParamType::String, "screenshot", '\0', "Compare rendered output against a reference screenshot FILE", CmdLineMode::Headless},
|
||||
{POFF(screenshotFilenameSave), CmdParamType::String, "screenshot-save", '\0', "Save rendered screenshot to specified path (PNG if the path ends in .png, BMP otherwise)", CmdLineMode::Headless},
|
||||
{POFF(screenshotFilenameDiff), CmdParamType::String, "screenshot-diff", '\0', "Save a visual comparison image to FILE when comparing screenshots", CmdLineMode::Headless},
|
||||
{POFF(screenshotSaveKeepAlpha), CmdParamType::Bool, "screenshot-keep-alpha", '\0', "Preserve the alpha channel when saving PNG screenshots (default: alpha is forced to 255)", CmdLineMode::Headless},
|
||||
{POFF(timeout), CmdParamType::Double, "timeout", '\0', "Set the timeout value", CmdLineMode::Headless},
|
||||
{POFF(maxScreenshotError), CmdParamType::Double, "max-mse", '\0', "Maximum allowed MSE error for screenshot comparison", CmdLineMode::Headless},
|
||||
{POFF(mountIso), CmdParamType::String, "mount", 'm', "Mount ISO/CSO on umd1:", CmdLineMode::Headless},
|
||||
|
||||
@@ -96,6 +96,8 @@ struct CommandLineOptions {
|
||||
std::optional<std::string> screenshotFilename;
|
||||
std::optional<std::string> screenshotFilenameSave;
|
||||
std::optional<std::string> screenshotFilenameDiff;
|
||||
// Headless: preserve the alpha channel when saving PNG screenshots.
|
||||
std::optional<bool> screenshotSaveKeepAlpha;
|
||||
|
||||
// Headless: mount an ISO/CSO on umd1:.
|
||||
std::optional<std::string> mountIso;
|
||||
|
||||
@@ -108,6 +108,10 @@ test is kept in `<outputRoot>/logs/`.
|
||||
- PNG, 512×272 (480×272 display in a 512-wide framebuffer), stored top-down
|
||||
(row 0 = top of screen). The BMP output format is bottom-up per the BMP
|
||||
spec; the flip is applied only when writing BMPs.
|
||||
- The alpha channel is forced to 255 when writing PNGs (games often use alpha
|
||||
for non-visual purposes, which would otherwise produce transparent-looking
|
||||
images); pass `--screenshot-keep-alpha` to the headless binary to preserve
|
||||
it (e.g. via a variant). The MSE comparison ignores alpha either way.
|
||||
- Generated with `--graphics=software` they are fully deterministic: a
|
||||
subsequent run produces byte-identical output, so `maxMse` can be 0.
|
||||
- If rendering code changes the output, existing references may need
|
||||
|
||||
@@ -459,7 +459,7 @@ bool ScreenshotComparer::SaveActualBitmap(const Path &resultFilename) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ScreenshotComparer::SaveActualPNG(const Path &resultFilename) {
|
||||
bool ScreenshotComparer::SaveActualPNG(const Path &resultFilename, bool keepAlpha) {
|
||||
std::vector<u8> rgba((size_t)stride_ * h_ * 4);
|
||||
const u32 *pixels = pixels_.data();
|
||||
for (size_t i = 0; i < (size_t)stride_ * h_; ++i) {
|
||||
@@ -467,7 +467,10 @@ bool ScreenshotComparer::SaveActualPNG(const Path &resultFilename) {
|
||||
rgba[i * 4 + 0] = (p >> 16) & 0xFF;
|
||||
rgba[i * 4 + 1] = (p >> 8) & 0xFF;
|
||||
rgba[i * 4 + 2] = p & 0xFF;
|
||||
rgba[i * 4 + 3] = (p >> 24) & 0xFF;
|
||||
// Games often use the alpha channel for non-visual purposes, which
|
||||
// results in fully transparent images in PNG viewers. By default,
|
||||
// force alpha to 255 when writing the image.
|
||||
rgba[i * 4 + 3] = keepAlpha ? ((p >> 24) & 0xFF) : 0xFF;
|
||||
}
|
||||
return pngSave(resultFilename, rgba.data(), stride_, h_, 4);
|
||||
}
|
||||
|
||||
+1
-1
@@ -47,7 +47,7 @@ public:
|
||||
}
|
||||
|
||||
bool SaveActualBitmap(const Path &filename);
|
||||
bool SaveActualPNG(const Path &filename);
|
||||
bool SaveActualPNG(const Path &filename, bool keepAlpha = false);
|
||||
bool SaveVisualComparisonPNG(const Path &filename);
|
||||
|
||||
protected:
|
||||
|
||||
@@ -71,6 +71,7 @@
|
||||
static Path g_comparisonScreenshot;
|
||||
static Path g_screenshotSavePath;
|
||||
static Path g_screenshotDiffPath;
|
||||
static bool g_screenshotSaveKeepAlpha = false;
|
||||
static double g_maxScreenshotError = 0.0;
|
||||
static bool g_screenshotFailed = false;
|
||||
static std::string g_debugOutputBuffer;
|
||||
@@ -202,7 +203,7 @@ void System_SendDebugScreenshot(const uint8_t *data, int width, int height) {
|
||||
// If a screenshot save path is set, save unconditionally.
|
||||
if (!g_screenshotSavePath.empty()) {
|
||||
ScreenshotComparer saver(pixels, FRAME_STRIDE, FRAME_WIDTH, FRAME_HEIGHT);
|
||||
bool saved = g_screenshotSavePath.GetFileExtension() == ".png" ? saver.SaveActualPNG(g_screenshotSavePath) : saver.SaveActualBitmap(g_screenshotSavePath);
|
||||
bool saved = g_screenshotSavePath.GetFileExtension() == ".png" ? saver.SaveActualPNG(g_screenshotSavePath, g_screenshotSaveKeepAlpha) : saver.SaveActualBitmap(g_screenshotSavePath);
|
||||
if (saved)
|
||||
SendAndCollectOutput("Screenshot saved to: " + g_screenshotSavePath.ToVisualString() + "\n");
|
||||
}
|
||||
@@ -782,6 +783,9 @@ int main(int argc, const char* argv[]) {
|
||||
if (cmdLineOptions.screenshotFilenameDiff.has_value()) {
|
||||
g_screenshotDiffPath = Path(std::string(cmdLineOptions.screenshotFilenameDiff.value()));
|
||||
}
|
||||
if (cmdLineOptions.screenshotSaveKeepAlpha.has_value()) {
|
||||
g_screenshotSaveKeepAlpha = cmdLineOptions.screenshotSaveKeepAlpha.value();
|
||||
}
|
||||
SetWriteFailureScreenshot(!getenv("GITHUB_ACTIONS") && !testOptions.bench);
|
||||
SetWriteDebugOutput(!testOptions.compare && !testOptions.bench);
|
||||
|
||||
|
||||
@@ -45,6 +45,7 @@ PPSSPPHeadless file.elf|file.prx|file.ppdmp [...] [options]
|
||||
| `--screenshot=<file>` | Compare the rendered output against a reference screenshot. |
|
||||
| `--screenshot-save=<file>` | Save the rendered output to a file (PNG if the path ends in `.png`, BMP otherwise). |
|
||||
| `--screenshot-diff=<file>` | When comparing screenshots, save a visual comparison image to this file (always, regardless of pass/fail). |
|
||||
| `--screenshot-keep-alpha` | Preserve the alpha channel when saving PNG screenshots (default: alpha is forced to 255, since games often use it for non-visual purposes). |
|
||||
| `--max-mse=<number>` | Maximum allowed Mean Squared Error for screenshot comparison (default: 0 = exact). |
|
||||
| `--compare` / `-c` | Compare test output with `.expected` text file and/or screenshot (see below). |
|
||||
| `--timeout=<seconds>` | Abort test if it takes longer than this. |
|
||||
|
||||
Reference in new issue
Block a user