# SVG → multi-size .ico mittels WPF (Bordmittel, kein extra Tool nötig) # Generiert logo.ico mit 16, 32, 48, 64, 128, 256 Pixeln Add-Type -AssemblyName PresentationCore, PresentationFramework, WindowsBase $ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path $IcoPath = Join-Path $ScriptDir 'logo.ico' function New-LogoBitmap { param([int]$Size) $dv = [System.Windows.Media.DrawingVisual]::new() $dc = $dv.RenderOpen() $scale = $Size / 256.0 # Hintergrund $bgRect = [System.Windows.Rect]::new(8 * $scale, 8 * $scale, 240 * $scale, 240 * $scale) $bgBrush = [System.Windows.Media.SolidColorBrush]::new( [System.Windows.Media.Color]::FromRgb(0x1A, 0x1A, 0x1A)) $dc.DrawRoundedRectangle($bgBrush, $null, $bgRect, 40 * $scale, 40 * $scale) # Blauer Gradient $gradStart = [System.Windows.Media.Color]::FromRgb(0x00, 0x78, 0xD4) $gradEnd = [System.Windows.Media.Color]::FromRgb(0x00, 0x5A, 0x9E) $grad = [System.Windows.Media.LinearGradientBrush]::new($gradStart, $gradEnd, 90) $grad.Freeze() # Bildschirm-Rahmen $screenRect = [System.Windows.Rect]::new(40 * $scale, 56 * $scale, 176 * $scale, 120 * $scale) $screenPen = [System.Windows.Media.Pen]::new($grad, 6 * $scale) $dc.DrawRoundedRectangle($null, $screenPen, $screenRect, 10 * $scale, 10 * $scale) # Streaming-Wellen $wavePen = [System.Windows.Media.Pen]::new($grad, 5 * $scale) $wavePen.StartLineCap = 'Round' $wavePen.EndLineCap = 'Round' foreach ($wave in @(@(70, 140, 90, 110, 120, 110), @(70, 140, 100, 90, 145, 90), @(70, 140, 110, 70, 170, 70))) { $geom = [System.Windows.Media.StreamGeometry]::new() $ctx = $geom.Open() $ctx.BeginFigure([System.Windows.Point]::new($wave[0] * $scale, $wave[1] * $scale), $false, $false) $ctx.QuadraticBezierTo( [System.Windows.Point]::new($wave[2] * $scale, $wave[3] * $scale), [System.Windows.Point]::new($wave[4] * $scale, $wave[5] * $scale), $true, $false) $ctx.Close() $geom.Freeze() $dc.DrawGeometry($null, $wavePen, $geom) } # Punkt am Ursprung $dc.DrawEllipse($grad, $null, [System.Windows.Point]::new(70 * $scale, 140 * $scale), 6 * $scale, 6 * $scale) # Standfuß $foot1 = [System.Windows.Rect]::new(100 * $scale, 184 * $scale, 56 * $scale, 8 * $scale) $foot2 = [System.Windows.Rect]::new( 80 * $scale, 196 * $scale, 96 * $scale, 8 * $scale) $dc.DrawRoundedRectangle($grad, $null, $foot1, 2 * $scale, 2 * $scale) $dc.DrawRoundedRectangle($grad, $null, $foot2, 3 * $scale, 3 * $scale) $dc.Close() $rtb = [System.Windows.Media.Imaging.RenderTargetBitmap]::new( $Size, $Size, 96, 96, [System.Windows.Media.PixelFormats]::Pbgra32) $rtb.Render($dv) return $rtb } function Get-PngBytes { param($bitmap) $encoder = [System.Windows.Media.Imaging.PngBitmapEncoder]::new() $encoder.Frames.Add([System.Windows.Media.Imaging.BitmapFrame]::Create($bitmap)) $ms = [System.IO.MemoryStream]::new() $encoder.Save($ms) $bytes = $ms.ToArray() $ms.Dispose() return ,$bytes } # Generierung mit ArrayList damit Wrapping vorhersehbar ist $sizes = @(16, 32, 48, 64, 128, 256) $pngList = New-Object System.Collections.ArrayList foreach ($size in $sizes) { Write-Host " Rendere ${size}x${size}..." $bmp = New-LogoBitmap -Size $size $bytes = Get-PngBytes $bmp [void]$pngList.Add($bytes) Write-Host " PNG: $($bytes.Length) bytes" } # ICO bauen $out = [System.IO.MemoryStream]::new() $bw = [System.IO.BinaryWriter]::new($out) $bw.Write([UInt16]0) # reserved $bw.Write([UInt16]1) # type = ICO $bw.Write([UInt16]$pngList.Count) # count $dataOffset = 6 + ($pngList.Count * 16) for ($i = 0; $i -lt $pngList.Count; $i++) { $size = $sizes[$i] $w = if ($size -eq 256) { 0 } else { $size } $h = if ($size -eq 256) { 0 } else { $size } $len = $pngList[$i].Length $bw.Write([byte]$w) $bw.Write([byte]$h) $bw.Write([byte]0) $bw.Write([byte]0) $bw.Write([UInt16]1) $bw.Write([UInt16]32) $bw.Write([UInt32]$len) $bw.Write([UInt32]$dataOffset) $dataOffset += $len } for ($i = 0; $i -lt $pngList.Count; $i++) { $bytes = $pngList[$i] $bw.Write($bytes, 0, $bytes.Length) } $bw.Flush() [System.IO.File]::WriteAllBytes($IcoPath, $out.ToArray()) $bw.Close() $out.Dispose() $icoSize = (Get-Item $IcoPath).Length Write-Host "`nFertig: $IcoPath ($icoSize Bytes, $($pngList.Count) Größen)"