Lumi/companion/scripts/generate-companion-icon.ps1
2026-07-24 14:44:27 +02:00

95 lines
3.2 KiB
PowerShell

param(
[string]$OutputPath = ""
)
$ErrorActionPreference = "Stop"
$repoRoot = (Resolve-Path (Join-Path $PSScriptRoot "..\..")).Path
if ([string]::IsNullOrWhiteSpace($OutputPath)) {
$OutputPath = Join-Path $repoRoot "companion\src\Lumi.Companion.App\Assets\Lumi.Companion.ico"
}
$OutputPath = [System.IO.Path]::GetFullPath($OutputPath)
$sizes = @(16, 32, 48, 256)
function New-LumiIconFrame {
param([int]$Size)
$radius = [Math]::Max(3, [Math]::Round($Size * 0.22))
$center = ($Size - 1) / 2.0
$diamondRadius = $Size * 0.36
$maskStride = [Math]::Ceiling($Size / 32.0) * 4
$pixels = New-Object byte[] ($Size * $Size * 4)
for ($y = 0; $y -lt $Size; $y++) {
for ($x = 0; $x -lt $Size; $x++) {
$inside = $true
if (!(($x -ge $radius -and $x -lt $Size - $radius) -or ($y -ge $radius -and $y -lt $Size - $radius))) {
$cornerX = if ($x -lt $radius) { $radius } else { $Size - $radius - 1 }
$cornerY = if ($y -lt $radius) { $radius } else { $Size - $radius - 1 }
$dx = $x - $cornerX
$dy = $y - $cornerY
$inside = (($dx * $dx) + ($dy * $dy)) -le ($radius * $radius)
}
$diamond = (([Math]::Abs($x - $center) / $diamondRadius) + ([Math]::Abs($y - $center) / $diamondRadius)) -le 1
$target = ((($Size - 1 - $y) * $Size) + $x) * 4
$pixels[$target] = if ($diamond -and $inside) { 255 } else { 200 }
$pixels[$target + 1] = if ($diamond -and $inside) { 255 } else { 183 }
$pixels[$target + 2] = if ($diamond -and $inside) { 255 } else { 40 }
$pixels[$target + 3] = if ($inside) { 255 } else { 0 }
}
}
$stream = [System.IO.MemoryStream]::new()
$writer = [System.IO.BinaryWriter]::new($stream)
$writer.Write([int]40)
$writer.Write([int]$Size)
$writer.Write([int]($Size * 2))
$writer.Write([uint16]1)
$writer.Write([uint16]32)
$writer.Write([int]0)
$writer.Write([int]$pixels.Length)
$writer.Write([int]0)
$writer.Write([int]0)
$writer.Write([int]0)
$writer.Write([int]0)
$writer.Write($pixels)
$writer.Write((New-Object byte[] ($maskStride * $Size)))
$writer.Flush()
$result = $stream.ToArray()
$writer.Dispose()
$stream.Dispose()
return ,$result
}
[byte[][]]$frames = @($sizes | ForEach-Object { ,(New-LumiIconFrame -Size $_) })
$directorySize = 6 + ($frames.Count * 16)
$offset = $directorySize
$output = [System.IO.MemoryStream]::new()
$binary = [System.IO.BinaryWriter]::new($output)
$binary.Write([uint16]0)
$binary.Write([uint16]1)
$binary.Write([uint16]$frames.Count)
for ($index = 0; $index -lt $frames.Count; $index++) {
$size = $sizes[$index]
$frame = $frames[$index]
$encodedSize = if ($size -eq 256) { 0 } else { $size }
$binary.Write([byte]$encodedSize)
$binary.Write([byte]$encodedSize)
$binary.Write([byte]0)
$binary.Write([byte]0)
$binary.Write([uint16]1)
$binary.Write([uint16]32)
$binary.Write([int]$frame.Length)
$binary.Write([int]$offset)
$offset += $frame.Length
}
foreach ($frame in $frames) { $binary.Write($frame) }
$binary.Flush()
$directory = Split-Path -Parent $OutputPath
[System.IO.Directory]::CreateDirectory($directory) | Out-Null
[System.IO.File]::WriteAllBytes($OutputPath, $output.ToArray())
$binary.Dispose()
$output.Dispose()
Write-Host "Generated Lumi Companion icon: $OutputPath"