# 年糕历险记 —— 程序图标生成(构建与发布.md §8:exe/窗口/快捷方式/安装器使用原版素材 logo) # 用法:pwsh -File scripts/make_icon.ps1 # 流程:素材包 pack.png → cmd/client/icon.png → go-winres 生成 icon.syso(嵌入游戏 exe) # → 同时生成多尺寸 cmd/client/icon.ico(供 NSIS 安装器 MUI_ICON / MUI_UNICON 使用) $ErrorActionPreference = "Stop" $root = Split-Path $PSScriptRoot -Parent # 1) 定位素材包 pack.png(原版 logo,高优先级包在前)→ 复制为 icon.png $png = $null foreach ($dir in Get-ChildItem (Join-Path $root "resourcepacks") -Directory -ErrorAction SilentlyContinue) { $cand = Join-Path $dir.FullName "pack.png" if (Test-Path $cand) { $png = $cand; break } } if (-not $png) { throw "未找到素材包 pack.png(resourcepacks/*/pack.png)" } Copy-Item $png (Join-Path $root "cmd\client\icon.png") -Force Write-Host "== 图标来源:$png ==" # 2) go-winres 生成 .syso(多尺寸图标组 + 版本资源;winres.json 引用 icon.png) $env:GOCACHE = Join-Path $root ".gocache" Push-Location (Join-Path $root "cmd\client") try { go run github.com/tc-hib/go-winres@latest make --in winres.json --out icon --arch amd64 --no-suffix if ($LASTEXITCODE -ne 0) { throw "go-winres 生成失败" } Move-Item -Force (Join-Path (Get-Location) "icon") (Join-Path (Get-Location) "icon.syso") } finally { Pop-Location } Write-Host "== 图标资源已嵌入:cmd/client/icon.syso ==" # 3) 生成多尺寸 icon.ico(16/24/32/48/64/128/256,PNG 压缩,供 NSIS 安装器/卸载器使用) Add-Type -AssemblyName System.Drawing $src = [System.Drawing.Image]::FromFile((Join-Path $root "cmd\client\icon.png")) $sizes = @(16, 24, 32, 48, 64, 128, 256) $ms = New-Object System.IO.MemoryStream $bw = New-Object System.IO.BinaryWriter($ms) # ICONDIR:reserved(2)=0, type(2)=1, count(2) $bw.Write([uint16]0); $bw.Write([uint16]1); $bw.Write([uint16]$sizes.Count) $offset = 6 + 16 * $sizes.Count $images = @() foreach ($s in $sizes) { $bmp = New-Object System.Drawing.Bitmap($s, $s) $g = [System.Drawing.Graphics]::FromImage($bmp) $g.InterpolationMode = [System.Drawing.Drawing2D.InterpolationMode]::HighQualityBicubic $g.DrawImage($src, 0, 0, $s, $s) $g.Dispose() $pngMs = New-Object System.IO.MemoryStream $bmp.Save($pngMs, [System.Drawing.Imaging.ImageFormat]::Png) $images += ,$pngMs.ToArray() $bmp.Dispose(); $pngMs.Dispose() } for ($i = 0; $i -lt $sizes.Count; $i++) { $s = $sizes[$i] $dim = if ($s -ge 256) { 0 } else { $s } # 256 用 0 表示 $bw.Write([byte]$dim); $bw.Write([byte]$dim) $bw.Write([byte]0); $bw.Write([byte]0) # colors / reserved $bw.Write([uint16]1); $bw.Write([uint16]32) # planes / bpp $bw.Write([uint32]$images[$i].Length) $bw.Write([uint32]$offset) $offset += $images[$i].Length } foreach ($d in $images) { $bw.Write($d) } $bw.Flush() [System.IO.File]::WriteAllBytes((Join-Path $root "cmd\client\icon.ico"), $ms.ToArray()) $src.Dispose() $bw.Close(); $ms.Dispose() Write-Host "== 安装器图标已生成:cmd/client/icon.ico($($sizes -join '/') px)=="