95 lines
3.2 KiB
PowerShell
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"
|