fix(tools): preserve opaque framebuffer RGB in captures
Docs Deploy / Build and Deploy MkDocs (push) Successful in 36s
Docs Deploy / Build and Deploy MkDocs (push) Successful in 36s
This commit is contained in:
4 files changed
+40
-12
No files matched your search
@@ -117,6 +117,12 @@ the verified value for the run above, not a universal surface format. The
|
||||
converter uses the installed `System.Drawing` PNG encoder and adds no package
|
||||
dependency.
|
||||
|
||||
PNG exports treat the captured frame as opaque and preserve its stored RGB.
|
||||
Framebuffer alpha is a rendering result, not image transparency; applying it
|
||||
again when displaying the PNG would darken surfaces a second time. Raw files
|
||||
retain all four original channels. The comparison script also ignores alpha
|
||||
in older PNG exports, without changing the measured RGB values.
|
||||
|
||||
## Сравнение областей кадра
|
||||
|
||||
`compare-frames.ps1` собирает пару «оригинал / FParkan» без масштабирования и
|
||||
|
||||
@@ -41,7 +41,21 @@ if ($SelfTest) {
|
||||
try { Get-MeanRgb $test ([System.Drawing.Rectangle]::new(1, 0, 2, 1)) | Out-Null }
|
||||
catch { $rejected = $true }
|
||||
if (-not $rejected) { throw 'Out-of-bounds region was accepted.' }
|
||||
Write-Output 'self-test: exact region RGB means and bounds rejection OK'
|
||||
$test.SetPixel(0, 0, [System.Drawing.Color]::FromArgb(0, 31, 16, 24))
|
||||
$test.SetPixel(1, 0, [System.Drawing.Color]::FromArgb(64, 31, 16, 24))
|
||||
$opaque = $test.Clone([System.Drawing.Rectangle]::new(0, 0, 2, 1), [System.Drawing.Imaging.PixelFormat]::Format32bppRgb)
|
||||
$pair = [System.Drawing.Bitmap]::new(2, 1)
|
||||
$graphics = [System.Drawing.Graphics]::FromImage($pair)
|
||||
try {
|
||||
$graphics.Clear([System.Drawing.Color]::Black)
|
||||
$graphics.DrawImageUnscaled($opaque, 0, 0)
|
||||
foreach ($x in @(0, 1)) {
|
||||
if ($pair.GetPixel($x, 0).ToArgb() -ne [System.Drawing.Color]::FromArgb(31, 16, 24).ToArgb()) {
|
||||
throw 'Comparison applied framebuffer alpha to stored RGB.'
|
||||
}
|
||||
}
|
||||
} finally { $graphics.Dispose(); $pair.Dispose(); $opaque.Dispose() }
|
||||
Write-Output 'self-test: exact region RGB means, opaque presentation and bounds rejection OK'
|
||||
} finally { $test.Dispose() }
|
||||
return
|
||||
}
|
||||
@@ -63,19 +77,21 @@ foreach ($value in $viewport) {
|
||||
}
|
||||
$crop = [System.Drawing.Rectangle]::new($viewport[0], $viewport[1], $viewport[2] - $viewport[0], $viewport[3] - $viewport[1])
|
||||
$native = [System.Drawing.Bitmap]::new((Resolve-Path -LiteralPath $NativePng).Path)
|
||||
$viewer = $nativeCrop = $pair = $graphics = $null
|
||||
$viewer = $viewerOpaque = $nativeCrop = $pair = $graphics = $null
|
||||
try {
|
||||
$viewer = [System.Drawing.Bitmap]::new((Resolve-Path -LiteralPath $ViewerPng).Path)
|
||||
if ($crop.Width -le 0 -or $crop.Height -le 0 -or $crop.Right -gt $native.Width -or $crop.Bottom -gt $native.Height -or
|
||||
$viewer.Width -ne $crop.Width -or $viewer.Height -ne $crop.Height) {
|
||||
throw 'Native crop and viewer dimensions must match without scaling.'
|
||||
}
|
||||
$nativeCrop = $native.Clone($crop, [System.Drawing.Imaging.PixelFormat]::Format32bppArgb)
|
||||
# Captured frames are opaque presentations; framebuffer alpha is not PNG opacity.
|
||||
$nativeCrop = $native.Clone($crop, [System.Drawing.Imaging.PixelFormat]::Format32bppRgb)
|
||||
$viewerOpaque = $viewer.Clone([System.Drawing.Rectangle]::new(0, 0, $viewer.Width, $viewer.Height), [System.Drawing.Imaging.PixelFormat]::Format32bppRgb)
|
||||
$pair = [System.Drawing.Bitmap]::new($viewer.Width * 2, $viewer.Height + 24)
|
||||
$graphics = [System.Drawing.Graphics]::FromImage($pair)
|
||||
$graphics.Clear([System.Drawing.Color]::Black)
|
||||
$graphics.DrawImageUnscaled($nativeCrop, 0, 24)
|
||||
$graphics.DrawImageUnscaled($viewer, $viewer.Width, 24)
|
||||
$graphics.DrawImageUnscaled($viewerOpaque, $viewer.Width, 24)
|
||||
$font = [System.Drawing.SystemFonts]::DefaultFont
|
||||
$graphics.DrawString('Original', $font, [System.Drawing.Brushes]::White, 4, 4)
|
||||
$graphics.DrawString('FParkan', $font, [System.Drawing.Brushes]::White, $viewer.Width + 4, 4)
|
||||
@@ -100,7 +116,7 @@ try {
|
||||
ConvertTo-Json -Depth 6 | Set-Content -LiteralPath $jsonPath -Encoding UTF8
|
||||
Write-Output "Wrote $pngPath and $jsonPath"
|
||||
} finally {
|
||||
foreach ($resource in @($graphics, $pair, $nativeCrop, $viewer, $native)) {
|
||||
foreach ($resource in @($graphics, $pair, $nativeCrop, $viewerOpaque, $viewer, $native)) {
|
||||
if ($null -ne $resource) { $resource.Dispose() }
|
||||
}
|
||||
}
|
||||
@@ -118,7 +118,7 @@ function Save-BgraPngToStream {
|
||||
$bitmap = New-Object System.Drawing.Bitmap(
|
||||
$Width,
|
||||
$Height,
|
||||
[System.Drawing.Imaging.PixelFormat]::Format32bppArgb
|
||||
[System.Drawing.Imaging.PixelFormat]::Format32bppRgb
|
||||
)
|
||||
$rectangle = New-Object System.Drawing.Rectangle(0, 0, $Width, $Height)
|
||||
$bitmapData = $null
|
||||
@@ -126,7 +126,7 @@ function Save-BgraPngToStream {
|
||||
$bitmapData = $bitmap.LockBits(
|
||||
$rectangle,
|
||||
[System.Drawing.Imaging.ImageLockMode]::WriteOnly,
|
||||
[System.Drawing.Imaging.PixelFormat]::Format32bppArgb
|
||||
[System.Drawing.Imaging.PixelFormat]::Format32bppRgb
|
||||
)
|
||||
|
||||
$rowBytes = $Width * 4
|
||||
@@ -201,12 +201,12 @@ function Get-CameraExtent {
|
||||
|
||||
function Invoke-SelfTest {
|
||||
$rgba = [byte[]]@(
|
||||
255, 0, 0, 255, 0, 255, 0, 255,
|
||||
0, 0, 255, 255, 255, 255, 255, 255
|
||||
255, 0, 0, 0, 0, 255, 0, 64,
|
||||
0, 0, 255, 128, 255, 255, 255, 255
|
||||
)
|
||||
$expectedBgra = [byte[]]@(
|
||||
0, 0, 255, 255, 0, 255, 0, 255,
|
||||
255, 0, 0, 255, 255, 255, 255, 255
|
||||
0, 0, 255, 0, 0, 255, 0, 64,
|
||||
255, 0, 0, 128, 255, 255, 255, 255
|
||||
)
|
||||
|
||||
$rgbaResult = Convert-ReadbackToBgra -Source $rgba -Format 37 -Width 2 -Height 2
|
||||
@@ -303,7 +303,7 @@ function Invoke-SelfTest {
|
||||
$stream.Dispose()
|
||||
}
|
||||
|
||||
'Self-check passed (2x2 RGBA/BGRA PNG, byte-length/64 MiB limits, viewport-coordinate bounds, and cropped pixel_capture bounds).'
|
||||
'Self-check passed (opaque 2x2 RGBA/BGRA PNG, byte-length/64 MiB limits, viewport-coordinate bounds, and cropped pixel_capture bounds).'
|
||||
}
|
||||
|
||||
if ($SelfTest) {
|
||||
|
||||
Reference in new issue
Block a user