Skip to content

HDR displays: icon/name scanning fails (capture is SDR-only via GDI CopyFromScreen) #62

Description

@DysektAI

Summary

On displays with HDR enabled, item scanning does not work reliably — the capture path is SDR-only, so icon scans (and name scans) read an SDR-tonemapped/clipped view of an HDR desktop and fail to match. The only existing "handling" is an upstream FAQ note telling users to disable HDR (FAQ.md, commit e98a276). There is no code-level HDR support today.

Impact

  • Item icon scanning fails/misidentifies when Windows HDR is on.
  • Forces HDR users to disable HDR to use RatScanner.
  • One user also reported the screen flashing during a scan attempt, as if HDR was being disabled/re-enabled (unconfirmed; another user reports no such effect). Needs investigation during local testing.

Root cause (current capture path)

Both name scans and icon scans funnel through a single GDI+ capture in src/App/RatScannerMain.cs:

// Returns the ruff screenshot
private static Bitmap GetScreenshot(Vector2 vector2, Size size)
{
    Bitmap bmp = new(size.Width, size.Height, PixelFormat.Format24bppRgb);

    try
    {
        using Graphics gfx = Graphics.FromImage(bmp);
        gfx.CopyFromScreen(vector2.X, vector2.Y, 0, 0, size, CopyPixelOperation.SourceCopy);
    }
    catch (Exception e)
    {
        Logger.LogWarning("Unable to capture screenshot", e);
    }

    return bmp;
}

Graphics.CopyFromScreen is legacy GDI+ capture. When HDR is enabled, Windows composes the desktop in FP16 linear scRGB (1.0 = 80 nits, values go far above that); GDI-based capture reads an 8-bit clipped SDR view of that buffer, so highlights blow out and colors are washed out/dimmed. The resulting Format24bppRgb bitmap is exactly what the SDR pipeline would see — there is no HDR capture, no tone mapping, no HDR-mode detection anywhere.

Known solutions to investigate (ShareX and others)

ShareX (and most GDI-based tools) had the same problem. The fix approaches proven in the ShareX ecosystem:

  • DXGI Desktop Duplication with R16G16B16A16_FLOAT — captures the full HDR signal, then tone maps to SDR with the BT.2390 EETF evaluated in the PQ domain, anchored to the monitor's SDR reference white ("SDR content brightness" slider) so UI/text keep exact brightness and only highlights compress.
  • Windows.Graphics.Capture (WinRT) also supports HDR capture and is the modern API.
  • Reference implementations: shuakami/ShareX-HDR (FP16 DXGI capture + BT.2390 tone mapping; per-display handling for mixed HDR/SDR multi-monitor setups; falls back to GDI capture if the path fails). Stock ShareX PRs/discussions on HDR capture are also worth mining.
  • HDR-mode detection: DXGI IDXGIOutput6::GetDesc1 (ColorSpace, MaxLuminance) or DISPLAYCONFIG SDR white level — only engage the HDR capture path when a display is actually in HDR mode, so SDR users keep the current fast path untouched.

The scan pipeline (RatEye → OpenCvSharp/Tesseract) can stay unchanged if the HDR capture path tone-maps to an SDR 8-bit bitmap before handing off — the fix can be contained in the capture layer.

Plan

  1. Test locally on an HDR setup: reproduce icon-scan failure, check the flashing symptom (HDR toggling) and whether it's capture-related.
  2. Evaluate DXGI Desktop Duplication / Windows.Graphics.Capture + tone mapping as a drop-in replacement for GetScreenshot when HDR is detected.
  3. Keep SDR behavior byte-for-byte identical (detection-gated, with GDI fallback).
  4. Verify accuracy on icon + name scans in HDR and SDR, and no display-mode flapping.

Acceptance criteria

  • Icon scanning works with HDR enabled at accuracy comparable to SDR.
  • No screen flashing / display-mode switching during scans.
  • SDR users see zero behavior change; mixed HDR/SDR multi-monitor setups handled per display.

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions