HDR Screenshot False Bloom When Downscaling to Steam Store Captures - October 2026 Art Pass
You capture 4K HDR gameplay on your best monitor. The bloom looks cinematic. Then you export a Steam-ready PNG downscaled to store dimensions, upload the gallery, and your HUD text looks like it is underwater.
Players do not care that your HDR looks beautiful in-engine. They only see one thing: your downscaled PNG where highlights bloom into UI edges and contrast collapses.
This Art & Design pass is an October 2026 fix for false bloom caused by mismatched tone mapping, gamma drift, and “bloom re-appearance” during downscaling. It pairs with the layout work in Steam Store Screenshot Composition Safe Zones - Five Gates Before October Next Fest and the store truth checklist in 18 Free Store Page QA and Localization Checklist Resources for Indie Launches so your visuals survive both render and marketing crop.
If you want receipts, this post also shows a screenshot_tone_receipt_v1.json template and a proof table you can drop into release-evidence/marketing-and-demo/. If you are new to “receipt thinking”, see Lesson 214 - crash minidump symbolicate and build label correlation receipt.
Non-repetition note: this post is about tone mapping and highlight/bloom behavior during HDR->SDR downscale. The safe-zones article owns composition and crop readability gates. Do both; do not merge them into one workflow.
Why this matters now (October 2026)
- HDR capture is the default in 2026 pipelines for many indies: more teams use HDR monitors and HDR-capable capture tools for “more drama”.
- Steam store captures are still “SDR-friendly” in practice: even when you upload HDR content, your final store image is still evaluated as an SDR-styled PNG by most player viewing paths.
- Downscaling reinterprets colors: gamma chunks, tone curves, and bloom threshold logic can shift when you resize and re-encode.
- UI readability is the refund predictor: if your HUD looks washed out, support tickets rise. Evidence culture matters: route your fix through receipts and proof, not “it looked fine on my screen”.
- October Next Fest time pressure: teams iterate 10 times and only upload the last one. If the last one fails tone verification, you lose the wishlist window.
Direct answer: Export an SDR proof frame from your render pipeline, then apply a gamma-correct downscale and verify HUD legibility at store-scale widths before you commit the final PNG set. Record the proof in screenshot_tone_receipt_v1.json.
What you will have after this art pass
- A repeatable HDR->SDR->Downscale recipe (with working command examples).
- A false bloom checklist you can run per screenshot slot (1-5).
- A
screenshot_tone_receipt_v1.jsonyou can attach to your release evidence folder. - A verification method that a teammate can follow without your monitor.
Time: ~2 hours first pass; 20-30 minutes per iteration once your pipeline is stable.
Who this is for
- Beginner artist/producer: you know what bloom is, but you are tired of “it looks different after resize”.
- Working developer: you need evidence-ready pipelines and clear failure modes for tone mapping drift.
- Small team in October 2026: you do not have a color science specialist, but you can still follow a proof table.
Beginner path (45-60 minute proof pass)
This path gets you from “HDR looks gorgeous” to “Steam PNGs survive highlight bloom”.
Prerequisites
- One HDR-capable capture method (in-engine capture, replay tool, or capture card).
- An editor that can save PNGs reliably.
- One command-line tool (pick one):
ffmpeg(recommended)- ImageMagick (optional ladder)
Step 1: Capture an HDR reference frame
Capture at your highest “truth” resolution. Keep this file as your ground truth reference.
Name it like:
proof_hdr_reference_3840x2160.png
Avoid re-exporting this reference after you notice bloom drift. You want a stable “before”.
Step 2: Export an SDR proof frame (controlled tone mapping)
Before downscaling, create an SDR proof with your engine’s intended tone mapping curve (the one you would normally use for screenshots).
If you do not have an SDR export toggle, do this two-lane:
- Export SDR using your engine’s screenshot/tonemap path.
- Export SDR by applying a “manual” HDR->SDR conversion in post. Use it only if it matches the engine’s intended curve.
Your rule:
- The SDR proof must match your in-game “what it should look like on a monitor” preview, not the HDR look.
Step 3: Downscale using a gamma-correct chain
Pick a target Steam capture size (most teams use 1920x1080 or other store-friendly dimensions).
Then apply downscale with a filter that does not “invent glow”.
ffmpeg example (PNG SDR input, gamma-correct downscale):
ffmpeg -i proof_sdr.png -vf "scale=1920:1080:flags=lanczos,format=rgba" -y steam_sdr_downscaled.png
If your pipeline is known to embed gamma inconsistently, add explicit gamma handling by re-encoding with an sRGB-like assumption:
ffmpeg -i proof_sdr.png -vf "scale=1920:1080:flags=lanczos,format=rgba" -color_primaries bt709 -color_trc iec61966-2-1 -colorspace bt709 -y steam_sdr_downscaled.png
Do not blindly apply this second command unless your team understands the color metadata you have in proof_sdr.png.
Step 4: Run the HUD readability check at store scale
Open the downscaled PNG and zoom out until it matches player viewing scale.
If you have no time for manual checks, use this quick test:
- Resize the image until the HUD text is “phone readable”.
- If text edges look fuzzy or glow-separated, you have false bloom.
- If text is still readable but background highlights are overpowering, you need bloom clamp or highlight roll-off tuning.
Step 5: Fix loop (what you change)
False bloom usually means one of these:
- Tone mapping curve is applied twice (engine + post).
- Gamma chunk got changed and highlights “lift” during downscale.
- Bloom threshold / intensity is too aggressive for store scale.
Fix by adjusting your SDR export curve, then re-run Step 3 and Step 4.
Developer path (evidence + receipts + gates)
This section is for the “I need to ship this without guessing” version.
Failure mode model: why false bloom happens
False bloom is not “your bloom math is wrong”. It is often:
- Gamma drift: highlights are treated as brighter than they should be after resize.
- Tone curve mismatch: HDR tone mapping is baked into one stage, then tone mapping happens again during conversion/resave.
- Highlight expansion: bloom peaks expand proportionally with resolution and sampling; downscaling changes the sampling pattern, so the perceived glow edge can worsen.
- Metadata mismatch: PNG gamma/ICC chunks can differ depending on capture/export tool.
You can treat this like a pipeline mismatch problem:
- Capture lane (HDR) has one truth.
- Proof lane (SDR) must lock tone mapping.
- Resize lane must not interpret the frame differently.
The proof receipt: screenshot_tone_receipt_v1.json
Create (or paste) this template and fill the fields per screenshot set:
{
"schema": "screenshot_tone_receipt_v1",
"screenshot_set": "october-2026-steam-gallery-01",
"proof_hdr_reference_path": "release-evidence/marketing-and-demo/proof_hdr_reference_3840x2160.png",
"proof_sdr_frame_path": "release-evidence/marketing-and-demo/proof_sdr_tonemap_1920x1080.png",
"output_downscaled_path": "release-evidence/marketing-and-demo/steam_sdr_downscaled_1920x1080.png",
"tonemap_method": "engine_intended_or_aces_like",
"color_space_assumption": "sRGB-like",
"bloom_profile": {
"intensity": 1.0,
"threshold": 1.0,
"bloom_clamp_enabled": true
},
"downscale": {
"tool": "ffmpeg",
"filter": "lanczos",
"input_gamma_in_png": "unknown_or_described",
"target_width": 1920,
"target_height": 1080
},
"verification": {
"hud_text_readable_at_360px_width": true,
"highlight_edge_separation_visible": false,
"ui_contrast_drop_percent": 12
}
}
Even if you do not have perfect numbers (you probably do not), the “boolean proofs” keep decisions honest. The goal is that a teammate can reproduce your pass with your paths and assumptions.
Evidence folder placement
Use the repo evidence taxonomy:
release-evidence/marketing-and-demo/is the closest lane for “store promises and capture truth”.
Recommended file layout for this pass:
release-evidence/
marketing-and-demo/
hdr-false-bloom/
screenshot_set_name/
proof_hdr_reference_3840x2160.png
proof_sdr_tonemap.png
steam_sdr_downscaled.png
screenshot_tone_receipt_v1.json
If you do not use tags/subfolders yet, you can still put the receipt and the proof PNGs directly under marketing-and-demo/ as long as the paths in the JSON match your actual folder.
Gate ladder: block promotion when false bloom is likely
Use these gates for each screenshot slot:
| Gate | Question | Pass criteria |
|---|---|---|
| A1 | Are HUD edges separated from glow? | HUD text and UI outlines are crisp |
| A2 | Does highlight roll-off look “flat” not “milky”? | Bloom halo does not eat the UI |
| A3 | Does downscaling lift midtones? | Background does not brighten unexpectedly |
| A4 | Does phone-width check survive? | Text remains readable at 360px width |
| A5 | Is safe-zone composition OK? | Essentials inside safe zones per the five-gates pass |
A1 and A4 are your minimum for shipping PNGs.
The tone mapping and downscale recipe (practical)
Option 1: Engine tonemap produces SDR, then you downscale once
This is the recommended approach:
- Tone map HDR to SDR inside the engine (or use your engine’s screenshot output).
- Treat the SDR frame as “truth”.
- Downscale once with gamma-correct resizing.
This prevents “double tone mapping”.
Option 2: HDR capture first, then manual conversion to SDR
Only use this if your engine’s SDR export path is unavailable.
In practice, this option is where false bloom tends to happen because:
- You might apply a curve meant for a different HDR pipeline.
- You might convert and then still have engine tonemap baked.
If you do this:
- Always compare output against a known good SDR preview.
- Lock the conversion tool + parameters for the whole team.
ffmpeg ladder (working dev examples)
Command A: simple downscale with a safe filter
ffmpeg -i proof_sdr.png -vf "scale=1920:1080:flags=lanczos,format=rgba" -y steam_sdr_downscaled.png
Command B: produce a “proof overlay” diff image
You want visual proof of what changed between SDR proof and downscaled PNG.
ffmpeg -i proof_sdr.png -i steam_sdr_downscaled.png -filter_complex "[0:v][1:v]blend=all_mode=difference:all_opacity=1" -y diff_sdr_vs_downscaled.png
If you see a massive diff in HUD text areas, your downscale pipeline is likely interpreting gamma/metadata differently.
Command C: build a small comparison pack for standup
ffmpeg -i proof_hdr_reference.png -i proof_sdr.png -i steam_sdr_downscaled.png -filter_complex "vstack=inputs=3" -y tone_compare_pack.png
Put tone_compare_pack.png in your evidence folder so you can answer, “what changed, exactly?” in one message.
ImageMagick ladder (optional)
If your team prefers ImageMagick, you can still apply a consistent approach:
- Use one resize method.
- Avoid auto-gamma surprises.
Example:
magick convert proof_sdr.png -resize 1920x1080\! -define filter:blur=0.9 -colorspace sRGB steam_sdr_downscaled.png
Treat ImageMagick as a tool for consistency, not for creative color.
Verification: how to know your UI is safe
The fast human test
After downscale:
- Zoom until HUD text matches likely player viewing scale.
- Look for:
- fuzzy edges
- halo separation around letters
- “milky” highlight roll-off behind UI panels
If you cannot explain the failure in one sentence, you probably cannot fix it responsibly. Use receipts.
The semi-automated contrast check (optional but powerful)
You can compute a simple luminance contrast proxy for a HUD region versus a background region.
Example Python snippet (Pillow):
from PIL import Image
import numpy as np
img = Image.open("steam_sdr_downscaled.png").convert("RGB")
arr = np.array(img).astype(np.float32) / 255.0
def mean_luma(region):
r = arr[region[1]:region[3], region[0]:region[2], :]
# Rec.709 luma approximation
luma = 0.2126*r[:,:,0] + 0.7152*r[:,:,1] + 0.0722*r[:,:,2]
return float(luma.mean())
hud_region = (200, 650, 560, 760) # example box
bg_region = (200, 520, 560, 600) # example box
hud_luma = mean_luma(hud_region)
bg_luma = mean_luma(bg_region)
contrast = (hud_luma + 1e-6) / (bg_luma + 1e-6)
print("hud_luma", hud_luma, "bg_luma", bg_luma, "contrast_ratio_proxy", contrast)
You are not doing scientific colorimetry here. You are building a repeatable proxy that catches obvious false bloom.
Set a team threshold:
- If the contrast proxy drops more than your agreed tolerance between SDR proof and final downscaled output, fix the pipeline before uploading.
Safe-zone cross-check (do not skip)
Even perfect tone mapping can fail store readability if the UI falls into a crop risk zone.
Run the safe-zone gates in:
Steam Store Screenshot Composition Safe Zones - Five Gates Before October Next Fest
In practice, do this order:
- Fix tone/bloom until HUD is crisp.
- Then check safe zones and composition.
If you do safe zones first, you may chase layout tweaks while the real issue is gamma drift.
PNG gamma and ICC metadata checklist (hidden culprit)
Even when the visuals “look right” on your machine, PNG metadata can quietly change how highlights and bloom appear after you re-encode or upload.
When you export and downscale, sanity-check that your proof and final PNGs are carrying the same assumptions:
- Gamma / gAMA chunk consistency
- Your SDR proof should not suddenly have a different gamma value than your final downscaled PNG.
- If a tool strips or rewrites the
gAMAchunk, browsers and gallery viewers may apply a different correction.
- ICC profile presence (or absence)
- If one export includes an ICC profile and the other does not, you can get palette and highlight-rolloff differences that read as “false bloom”.
- Colorspace expectation
- Decide what your team means by “SDR proof” (usually an sRGB-like expectation for store viewing).
- Lock it as the rule: proof lane and output lane must share the same colorspace assumption.
- Bit depth and alpha handling
- Some pipelines convert HDR or intermediate frames to 8-bit earlier than you expect.
- If your UI edges are semi-transparent and pre-multiplication changes, you can see halo separation amplify.
Working commands to inspect (ImageMagick):
magick identify -verbose steam_sdr_downscaled.png | more
Look for clues like:
Gamma:linesColorspace:/Profile:fields- whether an ICC profile is embedded
Working commands to standardize (ffmpeg re-encode lane):
ffmpeg -i steam_sdr_downscaled.png -vf "format=rgba" -color_primaries bt709 -color_trc iec61966-2-1 -colorspace bt709 -y steam_sdr_downscaled_standardized.png
If standardized output fixes the glow edge but the image “looked fine” before, your issue was metadata interpretation, not bloom tuning. Record the metadata checks into your screenshot_tone_receipt_v1.json assumptions so the next iteration does not repeat the same mystery.
Common mistakes (quick reject list)
- Resizing an HDR frame directly and expecting “the format will handle it”.
- Applying tone mapping twice (engine tonemap + post conversion).
- Ignoring PNG gamma/ICC metadata: one export tool can embed a different assumption.
- Using a “pretty” filter chain that smooths edges and makes glow worse.
- Evaluating only on your monitor: use at least one teammate review at store-scale.
- Uploading without a proof pack: you need
tone_compare_pack.pngor equivalent. - Treating this as a one-off: false bloom repeats. Lock the pipeline for the sprint.
Troubleshooting ladder (decision table)
| Symptom | Most likely cause | Fix |
|---|---|---|
| HUD text edges glow more after downscale | Gamma drift or metadata mismatch | Lock SDR proof lane and use consistent downscale filter |
| Background highlights are washed out behind UI | Bloom threshold too low for store scale | Raise threshold or enable bloom clamp for screenshot mode |
| Colors shift (overall palette looks different) | Tone curve mismatch | Use the engine’s intended SDR export curve as truth |
| Diff images show huge changes everywhere | Wrong input type or repeated conversion | Compare SDR proof to output and remove extra conversion stages |
| Looks fine on HDR monitor but not in gallery | Verification scale mismatch | Run phone-width check and semi-automated contrast proxy |
CI integration sketch (optional)
Teams that already run receipts and gates can also automate “obvious false bloom” checks.
Pseudo gate:
- Require that
steam_sdr_downscaled.pngis produced by a locked command. - Require a
screenshot_tone_receipt_v1.jsonwith filled assumptions. - Optionally require contrast proxy threshold.
Example pseudo:
name: screenshot-tone-proof
on: [workflow_dispatch]
jobs:
proof:
steps:
- run: test -f release-evidence/marketing-and-demo/hdr-false-bloom/screenshot_set_name/screenshot_tone_receipt_v1.json
- run: echo "Optional: run contrast proxy script"
Do not overfit automation. Let humans approve the first passes, then tighten thresholds once stable.
FAQ
Do I need to export true HDR for Steam?
For most teams, no. Your store image is evaluated as an SDR-friendly PNG. The more important step is that your SDR proof and downscale output match your intended tone curve and UI readability.
Why does bloom look worse after resizing?
Downscaling changes sampling and perceived highlight spread. If gamma or tone mapping differs between your SDR proof and the final PNG, bloom and halo edges can expand around UI elements.
Should I disable bloom entirely for screenshots?
Usually no. You want bloom for the “game feel”. Instead, create a screenshot mode that keeps bloom aesthetically correct but clamps highlight behavior for HUD readability.
What if my capture tool embeds weird PNG metadata?
Treat metadata as a pipeline input. Standardize your export tool for the proof lane. If needed, re-encode using a locked command so everyone produces the same assumptions.
How do I prove I fixed it to a teammate?
Upload the proof pack:
proof_sdr_tonemap.pngsteam_sdr_downscaled.pngdiff_sdr_vs_downscaled.pngscreenshot_tone_receipt_v1.json
That is the evidence bundle that turns “subjective taste” into “repeatable gate”.
Key takeaways
- False bloom on Steam is usually a tone mapping + gamma mismatch problem, not a “bad artist screenshot” problem.
- Export an SDR proof frame first, then downscale once using consistent filters.
- Use a receipt template (
screenshot_tone_receipt_v1.json) to lock assumptions and make the fix auditable. - Verify HUD readability at store-scale widths (phone-width check) before you upload final gallery PNGs.
- Run safe zones after tone is correct, not before.
- Build a proof pack so you can answer “what changed?” instantly in standup.
- Standardize tools and parameters for the whole team during October 2026.
- Optional contrast proxy automation can catch obvious regressions early.
- This is October 2026 Next Fest reality: iteration speed requires evidence discipline.
- Pair your tone fix with [Steam store screenshot composition gates] so marketing crop does not undo your work.
Related reading
- Steam Store Screenshot Composition Safe Zones - Five Gates Before October Next Fest
- 18 Free Store Page QA and Localization Checklist Resources for Indie Launches
- Steam GIF capsule readability safe-zone pass
Outbound reference: