Private/ConvertTo-Win32ToolkitPngBytes.ps1
|
function ConvertTo-Win32ToolkitPngBytes { <# .SYNOPSIS Normalizes arbitrary image bytes to genuine PNG bytes (or $null if they are not a decodable image). .DESCRIPTION Intune's win32LobApp largeIcon is a mimeContent of type image/png — the bytes MUST actually be a PNG, not merely a file named .png. Two things in this toolkit can hand us non-PNG bytes in an AppIcon.png: * Get-AppIconFromWinget historically wrote the fetched bytes verbatim (a winget IconUrl can be ICO/JPEG/BMP/GIF), and * a manual -IconPath can be any image copied over AppIcon.png. This helper returns the input unchanged when it is already a PNG (cheap, no GDI needed), otherwise decodes it with System.Drawing and re-encodes as PNG. Returns $null when the bytes are empty or not a decodable image — callers treat that as "no usable icon" and skip it rather than uploading garbage. GDI (System.Drawing) is Windows-only; the decode is wrapped so a non-Windows / headless host simply yields $null instead of throwing. #> [CmdletBinding()] [OutputType([byte[]])] param( [byte[]]$Bytes ) if ($null -eq $Bytes -or $Bytes.Length -lt 4) { return $null } # Already a PNG? (89 50 4E 47) — pass straight through, no decode/re-encode. if ($Bytes[0] -eq 0x89 -and $Bytes[1] -eq 0x50 -and $Bytes[2] -eq 0x4E -and $Bytes[3] -eq 0x47) { return $Bytes } try { Add-Type -AssemblyName System.Drawing -ErrorAction Stop $inStream = New-Object System.IO.MemoryStream (, $Bytes) try { $img = [System.Drawing.Image]::FromStream($inStream) try { $outStream = New-Object System.IO.MemoryStream try { $img.Save($outStream, [System.Drawing.Imaging.ImageFormat]::Png) return $outStream.ToArray() } finally { $outStream.Dispose() } } finally { $img.Dispose() } } finally { $inStream.Dispose() } } catch { Write-Verbose "ConvertTo-Win32ToolkitPngBytes: not a decodable image ($($_.Exception.Message))." return $null } } |