Files
Artemis-Plugins/plugins/open-computer-use/window-capture.ps1
T

60 lines
2.7 KiB
PowerShell

# ARTEMIS adapter for open-computer-use@1.1.0 (MIT).
# Never fall back to CopyFromScreen: an overlapping window is not test evidence.
function Capture-WindowPngBase64($bounds, [IntPtr]$hwnd) {
if ($hwnd -eq [IntPtr]::Zero) { return $null }
if (-not (Test-CapturableFrame $bounds)) {
return $null
}
$bitmap = $null
$graphics = $null
$stream = $null
$hdc = [IntPtr]::Zero
try {
$frame = Get-CapturableWindowFrame $hwnd
if ($null -eq $frame -or $frame.x -ne $bounds.x -or $frame.y -ne $bounds.y -or
$frame.width -ne $bounds.width -or $frame.height -ne $bounds.height) {
return $null
}
$bitmap = New-Object System.Drawing.Bitmap ([int][math]::Round($bounds.width)), ([int][math]::Round($bounds.height))
$graphics = [System.Drawing.Graphics]::FromImage($bitmap)
$graphics.Clear([System.Drawing.Color]::Black)
$hdc = $graphics.GetHdc()
# PW_RENDERFULLCONTENT also asks modern applications to render their surface.
# The upstream 30-second subprocess budget bounds an unresponsive WM_PRINT.
$captured = [OCUWin32]::PrintWindow($hwnd, $hdc, 2)
$graphics.ReleaseHdc($hdc)
$hdc = [IntPtr]::Zero
if (-not $captured) { return $null }
$after = Get-CapturableWindowFrame $hwnd
if ($null -eq $after -or $after.x -ne $frame.x -or $after.y -ne $frame.y -or
$after.width -ne $frame.width -or $after.height -ne $frame.height) {
return $null
}
# Some applications return success without rendering. Reject uniform frames;
# a usable UI tree remains available even when a window cannot be captured.
$first = $bitmap.GetPixel(0, 0).ToArgb()
$hasContent = $false
for ($row = 0; $row -lt 17 -and -not $hasContent; $row++) {
for ($column = 0; $column -lt 17; $column++) {
$x = [int][math]::Floor(($bitmap.Width - 1) * $column / 16)
$y = [int][math]::Floor(($bitmap.Height - 1) * $row / 16)
if ($bitmap.GetPixel($x, $y).ToArgb() -ne $first) {
$hasContent = $true
break
}
}
}
if (-not $hasContent) { return $null }
$stream = New-Object System.IO.MemoryStream
$bitmap.Save($stream, [System.Drawing.Imaging.ImageFormat]::Png)
return [Convert]::ToBase64String($stream.ToArray())
} catch {
return $null
} finally {
if ($hdc -ne [IntPtr]::Zero -and $null -ne $graphics) { $graphics.ReleaseHdc($hdc) }
if ($null -ne $graphics) { $graphics.Dispose() }
if ($null -ne $bitmap) { $bitmap.Dispose() }
if ($null -ne $stream) { $stream.Dispose() }
}
}