param( [Parameter(Mandatory=$true)][string]$InputPath, [Parameter(Mandatory=$true)][string]$OutputPath, [string]$BackupPath = "" ) if (!(Test-Path -LiteralPath $InputPath)) { throw "Input file not found: $InputPath" } if ($BackupPath -ne "") { Copy-Item -LiteralPath $InputPath -Destination $BackupPath -Force } Add-Type -AssemblyName System.Drawing # Load from a stream to avoid locking the input file (required if output overwrites input) $fs = [System.IO.File]::Open($InputPath, [System.IO.FileMode]::Open, [System.IO.FileAccess]::Read, [System.IO.FileShare]::ReadWrite) try { $bmp = New-Object System.Drawing.Bitmap($fs) } finally { $fs.Dispose() } $out = New-Object System.Drawing.Bitmap($bmp.Width, $bmp.Height, [System.Drawing.Imaging.PixelFormat]::Format32bppArgb) function IsBgPixel($c) { $r = [int]$c.R $g = [int]$c.G $b = [int]$c.B $nearGray = ([math]::Abs($r - $g) -le 10) -and ([math]::Abs($g - $b) -le 10) if (-not $nearGray) { return $false } # Typical checkerboard: very light gray and mid light gray $isLight = ($r -ge 235 -and $g -ge 235 -and $b -ge 235) $isMid = ($r -ge 205 -and $g -ge 205 -and $b -ge 205 -and $r -le 235) return ($isLight -or $isMid) } for ($y = 0; $y -lt $bmp.Height; $y++) { for ($x = 0; $x -lt $bmp.Width; $x++) { $c = $bmp.GetPixel($x, $y) if (IsBgPixel $c) { $out.SetPixel($x, $y, [System.Drawing.Color]::FromArgb(0, $c.R, $c.G, $c.B)) } else { $out.SetPixel($x, $y, [System.Drawing.Color]::FromArgb(255, $c.R, $c.G, $c.B)) } } } $tmp = "$OutputPath.tmp" try { $out.Save($tmp, [System.Drawing.Imaging.ImageFormat]::Png) } finally { $bmp.Dispose() $out.Dispose() } Move-Item -LiteralPath $tmp -Destination $OutputPath -Force