SharpIco:用純C#打造零依賴的.ico圖示產生器,支援.NET9與AOT編譯

SharpIco:用純C#打造零依賴的.ico圖示產生器,支援.NET9與AOT編譯

網路上搜尋到的很多 ICO 製作工具都是針對 favicon 的,其他的要不太重,要不就是收費,於是我把目光重新放在了開源工具上

最後更新 2025/5/27 下午8:27
程序设计实验室
預計閱讀 19 分鐘
分類
.NET
專題
C# AOT
標籤
.NET C# 開源 AOT ICO

前言

最近一直在完善我今年的两款桌面软件:影片剪輯工具 ClipifyAI 文章創作工具 StarBlogPublisher

雖然介面已經大致完善,但圖示還是預設的,看起來很不專業

於是我打算幫這兩個軟體換個好看的圖示

早在 VB6.0 年代,我用過一套開源的 ICO 圖示製作工具,不過現在已經找不到了

網路上搜到的很多 ICO 製作工具都是針對 favicon 的

其他的要不太重,要不就是收費,於是我把目光重新放在開源工具上

找到一個基於 nodejs 實作且零依賴的(大部分都是依賴於 Magick 這個 C++ 實作的圖片庫),然而很遺憾,這個工具在我的電腦上並不能用……

目標

這時候我想起之前曾經用 C# 開發了一個圖片格式轉換工具,使用了 .Net8 的 AOT 功能,可以像 Go 語言那樣開發出跨平台的單執行檔

所以我決定繼續使用 C# 開發一個圖示產生工具,這個工具可以實現:

  • 純 C# 實作,沒有外部依賴,跨平台,單執行檔,AOT
  • 將 png 圖片分解為多張不同尺寸的小圖片(邊長 16, 32, 48, 64, 128, 256, 512),然後合成一張 ICO 圖示,實現不同尺寸螢幕的良好視覺體驗
  • 支援 Inspect 功能,可以讀取並分析 ICO 圖示
  • 方便的分發方式,支援 dotnet tool, scoop, brew 等工具一鍵安裝

目前已經完成了,並且也發佈到了 nuget 和 scoop,接下來再研究如何發佈到 brew

專案主頁:https://github.com/star-plan/sharp-ico

實作

在 SharpIco 中,.ico 檔案的產生完全不依賴 ImageMagick 或任何影像處理外部工具,而是透過純 C# 程式碼手工拼接符合規範的 ICO 二進位結構。

這部分的核心類別是 IcoGenerator,具體程式碼我就不貼了,在專案裡有,挑幾個要點介紹吧~

產生多尺寸影像

使用 ImageSharp 產生多尺寸影像

var clone = original.Clone(ctx => ctx.Resize(size, size));
clone.SaveAsPng(ms);
  • 使用 ImageSharp 的 Resize 與 Clone 功能,將原始高解析度 PNG 產生多個目標尺寸(如 16x16、32x32、256x256)
  • PNG 格式儲存到記憶體流中,用於後續寫入 .ico

💡 ICO 檔案支援嵌入 PNG 影像(從 Vista 開始),這樣可以保持更小體積與更佳透明度效果。

手動建構 ICO 檔頭

按照 ICO 檔案格式手動建構 ICONDIR 與 ICONDIRENTRY

ICO 檔案的頭部由 3 部分組成:

  • ICONDIR(6 位元組):固定結構
  • ICONDIRENTRY × N(每個 16 位元組):描述每一張嵌入影像的尺寸、偏移
  • Image Data × N:實際影像二進位資料
writer.Write((ushort)0); // Reserved
writer.Write((ushort)1); // Type = icon
writer.Write((ushort)images.Count); // Image count
  • 先寫入 ICO 檔頭 ICONDIR
  • 然後迴圈寫入每一張圖片的描述資訊(寬高、色深、資料偏移等)
writer.Write((byte)(img.Width == 256 ? 0 : img.Width)); // 256 用 0 表示
writer.Write((ushort)32); // bits per pixel
writer.Write(image.Length);
writer.Write(offset);

ICO 檔案中的寬度/高度欄位如果為 0,表示 256。這是 ICO 格式的一個特殊規定。

ICO 檔案格式在表示影像尺寸時有一個限制:寬度和高度欄位各只有一個位元組,值範圍是 0-255。當這些欄位為 0 時,按照規範表示 256 像素。對於大於 256 的尺寸(如 512×512 或 1024×1024),在檔頭中仍然會顯示為 0(即 256),但實際影像資料可以包含更大尺寸的影像。

拼接影像

拼接所有 PNG 影像資料

foreach (var image in images) {
    writer.Write(image);
}
  • 所有描述資訊寫完後,緊接著寫入影像資料本體
  • 由於提前計算了偏移量,確保每張影像資料可以被系統正確辨識和讀取

擴充

支援自訂尺寸

public static void GenerateIcon(string sourcePng, string outputIco, int[] sizes)
  • 預設支援 16~512 的常見尺寸
  • 可透過傳參靈活指定尺寸組合(比如只打包 32/256)

Inspect 功能

除了圖示產生,SharpIco 還內建了一個圖示內容分析工具 IcoInspector,可以幫助開發者深入理解 .ico 檔案內部結構,並驗證實際包含的圖層影像尺寸與色深資訊,解決市面上不少圖示工具產生不規範 .ico 檔案的問題。

這裡簡單介紹一下實作思路~

讀取 ICO 檔頭

手動讀取 ICONDIR + ICONDIRENTRY 結構

ICO 檔案的頭部結構由三個部分組成:

  • ICONDIR(6 位元組):標記為圖示、記錄影像數量
  • ICONDIRENTRY × N(每個 16 位元組):記錄每張圖片的元資訊(寬、高、色深、資料偏移等)
  • 影像資料區塊:實際的 PNG 或 BMP 影像
ushort reserved = reader.ReadUInt16(); // 必須為0
ushort type = reader.ReadUInt16();     // 1表示圖示
ushort count = reader.ReadUInt16();    // 影像數量

隨後逐個讀取影像條目,儲存到記憶體中用於後續處理。

byte width = reader.ReadByte();
byte height = reader.ReadByte();
ushort bitCount = reader.ReadUInt16();
int sizeInBytes = reader.ReadInt32();
int imageOffset = reader.ReadInt32();

對了,前面介紹過,ICO 頭部的空間有限,只能存 8 位,所以如果 width/height 欄位為 0,根據規範表示 256,或者是超過 256

提取 & 解析影像資料

提取影像資料,驗證真實解析度

ICO 檔案中記錄的寬高未必真實,尤其是嵌入 PNG 格式的情況。因此,使用 ImageSharp 對每張影像進行真正解析。

fs.Seek(entry.ImageOffset, SeekOrigin.Begin);
fs.Read(imageData, 0, dataSize);
Image.Load(imageData) → 獲取真實 Width 和 Height
  • 透過 GetImageDimensions() 方法判斷是否為 PNG,並用 ImageSharp 載入
  • 如果格式錯誤或讀取失敗,回退為頭部宣告的尺寸

這一點可用於檢測某些「偽造 ICO」的問題(比如尺寸與影像內容不一致)

補全並輸出分析結果

所有條目都讀取並解析後,將內容輸出為結構化資訊:

正在檢查ICO檔案: logo.ico
圖示數量: 7
- 第1張影像: 16x16, 32bpp, 大小: 840位元組, 偏移: 118
- 第2張影像: 32x32, 32bpp, 大小: 1939位元組, 偏移: 958
- 第3張影像: 48x48, 32bpp, 大小: 3375位元組, 偏移: 2897
- 第4張影像: 64x64, 32bpp, 大小: 4951位元組, 偏移: 6272
- 第5張影像: 128x128, 32bpp, 大小: 13782位元組, 偏移: 11223
- 第6張影像: 256x256, 32bpp, 大小: 37823位元組, 偏移: 25005
- 第7張影像: 512x512, 32bpp, 大小: 114655位元組, 偏移: 62828
  注意: 檔頭中指定的尺寸為256x256,但實際影像尺寸為512x512

這樣能夠快速確認:

  • 一個 .ico 檔案中包含多少圖層
  • 每層的真實尺寸與色深
  • 是否存在格式問題(尺寸對不上、大小異常等)

命令列介面設計

SharpIco 不只是一個程式碼庫,同時也提供了完整的命令列工具,方便在任意開發場景中快速呼叫,無論是手動使用還是整合進建置腳本都毫無壓力。

這一部分使用了 .NET 的現代 CLI 建置庫 System.CommandLine,實現了兩個主命令:

  • generate:將 PNG 影像轉換為 ICO 圖示
  • inspect:檢查 ICO 檔案的結構與圖層資訊

命令列使用方法:

sharpico generate -i logo.png -o icon.ico --sizes 16 32 48 256
sharpico inspect icon.ico

🛠️ 產生命令 generate

這個命令支援透過參數控制輸入、輸出路徑和產生圖示的尺寸:

sharpico generate --input logo.png --output app.ico --sizes 16 32 64 256

參數說明:

參數 簡寫 說明
--input -i 來源 PNG 影像路徑(必須)
--output -o 輸出 ICO 檔案路徑(必須)
--sizes -s 要產生的圖示尺寸列表,支援多個(預設為常見七種尺寸)

支援多個尺寸同時產生,內部呼叫 IcoGenerator.GenerateIcon() 實現多圖層 .ico 檔案建立。

舉個例子:

sharpico generate -i logo.png -o icon.ico -s 32 64 256

輸出將包含三種解析度圖層。

🔍 檢查命令 inspect

可以對任意 .ico 檔案進行結構檢查與驗證:

sharpico inspect icon.ico

這會輸出圖示中每一張圖層的:

  • 寬高(宣告與實際尺寸)
  • 色深(bpp)
  • 資料偏移與大小
  • 是否存在頭部與實際影像尺寸不一致的潛在問題

範例輸出:

正在檢查ICO檔案: logo.ico
圖示數量: 7
- 第1張影像: 16x16, 32bpp, 大小: 840位元組, 偏移: 118
- 第2張影像: 32x32, 32bpp, 大小: 1939位元組, 偏移: 958
- 第3張影像: 48x48, 32bpp, 大小: 3375位元組, 偏移: 2897
- 第4張影像: 64x64, 32bpp, 大小: 4951位元組, 偏移: 6272
- 第5張影像: 128x128, 32bpp, 大小: 13782位元組, 偏移: 11223
- 第6張影像: 256x256, 32bpp, 大小: 37823位元組, 偏移: 25005
- 第7張影像: 512x512, 32bpp, 大小: 114655位元組, 偏移: 62828
  注意: 檔頭中指定的尺寸為256x256,但實際影像尺寸為512x512

發佈

SharpIco 不只是一個函式庫,也不只是一個只能原始碼使用的小工具,而是一個可以 透過 dotnet tool 全平台安裝執行支援 AOT 編譯優化效能和體積 的專業圖示工具。

這次需要同時支援 AOT 和傳統發佈,所以對專案檔做了一些配置

<Project Sdk="Microsoft.NET.Sdk">

    <PropertyGroup>
        <OutputType>Exe</OutputType>
        <TargetFramework>net9.0</TargetFramework>
        <ImplicitUsings>enable</ImplicitUsings>
        <Nullable>enable</Nullable>
        <!-- AOT編譯設定移至條件屬性組 -->
        <InvariantGlobalization>true</InvariantGlobalization>

        <!-- .NET Tool 配置 -->
        <PackAsTool>true</PackAsTool>
        <ToolCommandName>sharpico</ToolCommandName>
        <PackageOutputPath>./nupkg</PackageOutputPath>

        <!-- 套件資訊 -->
        <PackageId>SharpIco</PackageId>
        <Version>1.0.0</Version>
        <Authors>StarPlan</Authors>
        <Description>SharpIco是一個純 C# AOT 實作的輕量級圖示產生工具,用於產生和檢查ICO圖示檔案。可將一張高解析度 PNG 圖片一鍵產生標準的 Windows .ico 圖示檔案,內含多種尺寸(16x16 到 512x512),還可以自訂尺寸。除了圖示產生,SharpIco 還內建圖示結構分析功能,助你輕鬆驗證 .ico 檔案中包含的圖層與尺寸。</Description>
        <PackageTags>icon;ico;png;converter,DealiAxy,cli,tool,dotnet-tool,imagesharp</PackageTags>
        <PackageProjectUrl>https://github.com/star-plan/sharp-ico</PackageProjectUrl>
        <RepositoryUrl>https://github.com/star-plan/sharp-ico</RepositoryUrl>
        <PackageLicenseExpression>MIT</PackageLicenseExpression>
        <PackageReadmeFile>README.md</PackageReadmeFile>
    </PropertyGroup>

    <!-- AOT發佈專用設定 -->
    <PropertyGroup Condition="'$(PublishAot)' == 'true'">
        <PublishAot>true</PublishAot>
        <TrimMode>full</TrimMode>
        <InvariantGlobalization>true</InvariantGlobalization>
        <IlcGenerateStackTraceData>false</IlcGenerateStackTraceData>
        <IlcOptimizationPreference>Size</IlcOptimizationPreference>
        <IlcFoldIdenticalMethodBodies>true</IlcFoldIdenticalMethodBodies>
        <JsonSerializerIsReflectionEnabledByDefault>true</JsonSerializerIsReflectionEnabledByDefault>
    </PropertyGroup>

    <ItemGroup>
        <None Include="README.md" Pack="true" PackagePath="\" />
    </ItemGroup>

    <ItemGroup>
        <PackageReference Include="SixLabors.ImageSharp" Version="3.1.8" />
        <PackageReference Include="System.CommandLine" Version="2.0.0-beta4.22272.1" />
    </ItemGroup>

</Project>

幾個要點:

定義為 CLI 工具(dotnet tool)

<PackAsTool>true</PackAsTool>
<ToolCommandName>sharpico</ToolCommandName>

這使得 SharpIco 可以像任何其他 .NET CLI 工具 一樣被全域安裝:

dotnet tool install -g SharpIco --add-source ./nupkg

安裝後,只需執行:

sharpico generate -i logo.png -o icon.ico

支援 AOT 編譯發佈(.NET 9 原生支援)

<PublishAot>true</PublishAot>
<IlcOptimizationPreference>Size</IlcOptimizationPreference>
<TrimMode>full</TrimMode>

透過設定 PublishAot=true,SharpIco 支援編譯為原生執行檔

無需 .NET 執行時期支援,啟動速度極快,適合建置工具鏈或整合環境使用

AOT 建置命令範例:

dotnet publish -c Release -r win-x64 /p:PublishAot=true

產生的 sharpico.exe 是一個純原生的 Windows 執行檔,無需安裝 .NET!

除 Windows 外,也可發佈為 linux-x64, osx-arm64 等跨平台目標。

自動發佈 nuget

SharpIco 採用了完整的 GitHub Actions CI/CD 流水線,做到一次打 tag,全平台建置自動完成

只需推送一個符合語意化格式的標籤(如 v1.0.0),系統將自動:

  1. 建置並發佈 NuGet 工具套件
  2. 針對 Windows / Linux / macOS 編譯原生 AOT 執行檔
  3. 自動上傳所有成品到 GitHub Release 頁面

我之前已經寫過關於如何發佈 nuget 的文章了,詳見:

這部分問題不大

不過這次還有些不一樣,之前發佈的是類別庫和專案範本,這次是 dotnet tool

這類似於 npx 腳本、pip 工具之類的概念

可以使用 dotnet tool 命令安裝和呼叫

不過這種方式就不能使用 AOT,只能使用 framework dependant 方式發佈

nuget 發佈比較簡單,也是使用 dotnet 命令

dotnet pack -c Release

不過關鍵在於我要用 GitHub Action 來自動化建置和發佈,這個流程和之前差不多

name: 發佈SharpIco
run-name: ${{ github.actor }} 正在發佈SharpIco 🚀

on:
  push:
    tags:
      - "v*.*.*"  # 更明確的版本格式匹配

# 為整個工作流程設定權限
permissions:
  contents: write
  id-token: write
  issues: write

jobs:
  # 第一步:發佈NuGet套件
  publish-nuget:
    runs-on: ubuntu-latest
    
    steps:
      - uses: actions/checkout@v3
        with:
          fetch-depth: 0  # 獲取所有歷史記錄用於版本號計算
      
      - name: Setup .NET
        uses: actions/setup-dotnet@v3
        with:
          dotnet-version: 9.0.x
      
      - name: 快取NuGet套件
        uses: actions/cache@v3
        with:
          path: ~/.nuget/packages
          key: ${{ runner.os }}-nuget-${{ hashFiles('**/packages.lock.json') }}
          restore-keys: |
            ${{ runner.os }}-nuget-
      
      - name: 提取版本號
        id: get_version
        shell: bash
        run: echo "VERSION=${GITHUB_REF#refs/tags/v}" >> $GITHUB_OUTPUT
      
      - name: 還原依賴
        run: dotnet restore ./SharpIco/SharpIco.csproj
      
      - name: 執行測試
        run: dotnet test --no-restore

      - name: 建置專案
        run: dotnet build --no-restore -c Release --nologo ./SharpIco/SharpIco.csproj -p:Version=${{ steps.get_version.outputs.VERSION }}
      
      - name: 建立NuGet套件
        run: dotnet pack -c Release ./SharpIco/SharpIco.csproj -p:PackageVersion=${{ steps.get_version.outputs.VERSION }} --no-build --output ./nupkg
        
      - name: 發佈到NuGet Gallery
        run: dotnet nuget push ./nupkg/*.nupkg --api-key ${{ secrets.NUGET_GALLERY_TOKEN }} --source https://api.nuget.org/v3/index.json --skip-duplicate

自動發佈到 GitHub Release

這個是最折騰的,我反覆除錯了十幾次才成功😂

不得不說 GitHub Action 的除錯太不友善了

直接貼上我最後成功的配置吧

name: 發佈SharpIco
run-name: ${{ github.actor }} 正在發佈SharpIco 🚀

on:
  push:
    tags:
      - "v*.*.*"  # 更明確的版本格式匹配

# 為整個工作流程設定權限
permissions:
  contents: write
  id-token: write
  issues: write

jobs:
  # 第二步:編譯各平台執行檔
  build-executables:
    needs: publish-nuget  # 確保在NuGet套件發佈後執行
    strategy:
      fail-fast: false
      matrix:
        kind: ['windows', 'linux', 'macOS']
        include:
          - kind: windows
            os: windows-latest
            target: win-x64
            extension: '.zip'
          - kind: linux
            os: ubuntu-latest
            target: linux-x64
            extension: '.tar.gz'
          - kind: macOS
            os: macos-latest
            target: osx-x64
            extension: '.tar.gz'

    runs-on: ${{ matrix.os }}
    
    steps:
      - uses: actions/checkout@v3
        with:
          fetch-depth: 0  # 獲取所有歷史記錄用於版本號計算
      
      - name: 提取版本號
        id: get_version
        shell: bash
        run: echo "VERSION=${GITHUB_REF#refs/tags/v}" >> $GITHUB_OUTPUT
      
      - name: Setup .NET
        uses: actions/setup-dotnet@v3
        with:
          dotnet-version: 9.0.x
      
      - name: 快取NuGet套件
        uses: actions/cache@v3
        with:
          path: ~/.nuget/packages
          key: ${{ runner.os }}-nuget-${{ hashFiles('**/packages.lock.json') }}
          restore-keys: |
            ${{ runner.os }}-nuget-
      
      - name: 安裝Linux依賴
        if: matrix.kind == 'linux'
        run: |
          sudo apt-get update
          sudo apt-get install -y clang zlib1g-dev libkrb5-dev

      - name: 設定Windows環境
        if: matrix.kind == 'windows'
        shell: pwsh
        run: |
          Write-Host "設定Windows編譯環境..."
          # 確保有最新的開發者工具
          choco install visualstudio2022buildtools -y --no-progress
      
      - name: 還原依賴
        run: dotnet restore ./SharpIco/SharpIco.csproj
      
      - name: AOT編譯
        run: |
          echo "正在為 ${{ matrix.kind }} 平台進行AOT編譯..."
          dotnet publish ./SharpIco/SharpIco.csproj -c Release -r ${{ matrix.target }} --self-contained true -p:PublishAot=true -p:Version=${{ steps.get_version.outputs.VERSION }} -o ./publish/${{ matrix.kind }}
      
      - name: 打包Windows執行檔
        if: matrix.kind == 'windows'
        run: |
          cd ./publish/${{ matrix.kind }}
          7z a -tzip ../../SharpIco-${{ matrix.kind }}-${{ steps.get_version.outputs.VERSION }}${{ matrix.extension }} *
      
      - name: 打包Linux/macOS執行檔
        if: matrix.kind != 'windows'
        run: |
          cd ./publish/${{ matrix.kind }}
          tar -czvf ../../SharpIco-${{ matrix.kind }}-${{ steps.get_version.outputs.VERSION }}${{ matrix.extension }} *
      
      # 上傳建置成品作為工作流程構件(artifacts)
      - name: 上傳建置成品
        uses: actions/upload-artifact@v4
        with:
          name: SharpIco-${{ matrix.kind }}-${{ steps.get_version.outputs.VERSION }}
          path: ./SharpIco-${{ matrix.kind }}-${{ steps.get_version.outputs.VERSION }}${{ matrix.extension }}
          retention-days: 1

  # 第三步:統一出所有平台執行檔到GitHub Release
  upload-to-release:
    needs: build-executables
    runs-on: ubuntu-latest
    
    steps:
      - name: 提取版本號
        id: get_version
        shell: bash
        run: echo "VERSION=${GITHUB_REF#refs/tags/v}" >> $GITHUB_OUTPUT
      
      # 下載所有平台建置成品
      - name: 下載Windows建置成品
        uses: actions/download-artifact@v4
        with:
          name: SharpIco-windows-${{ steps.get_version.outputs.VERSION }}
          path: ./artifacts
      
      - name: 下載Linux建置成品
        uses: actions/download-artifact@v4
        with:
          name: SharpIco-linux-${{ steps.get_version.outputs.VERSION }}
          path: ./artifacts
      
      - name: 下載macOS建置成品
        uses: actions/download-artifact@v4
        with:
          name: SharpIco-macOS-${{ steps.get_version.outputs.VERSION }}
          path: ./artifacts
      
      # 列出下載的檔案以確認
      - name: 列出下載的檔案
        run: ls -la ./artifacts
      
      # 統一出到GitHub Release
      - name: 上傳所有檔案到GitHub Release
        uses: softprops/action-gh-release@v1
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          files: ./artifacts/*
          tag_name: ${{ github.ref }}
          fail_on_unmatched_files: false
          draft: false
          name: SharpIco 版本 ${{ steps.get_version.outputs.VERSION }}
          generate_release_notes: true 

工作流程總覽

整個工作流程由三大 Job 組成:

階段 描述
publish-nuget 編譯專案並發佈 .nupkg 套件到 NuGet.org
build-executables 為三大平台編譯 AOT 原生執行檔
upload-to-release 將所有成品上傳到目前 tag 對應的 GitHub Release

發佈 nuget 部分比較容易,這裡就不重複了

編譯三平台 AOT 執行檔(build-executables)

採用 GitHub Matrix 建置策略,分別針對:

  • win-x64(Windows 執行檔,ZIP 打包)
  • linux-x64(Linux ELF,執行檔,tar.gz 打包)
  • osx-x64(macOS 執行檔,tar.gz 打包)
dotnet publish -c Release -r ${{ matrix.target }} --self-contained true -p:PublishAot=true

每個平台產生對應壓縮包,打包後使用 upload-artifact 上傳中轉。

上傳至 GitHub Release(upload-to-release)

這一階段會自動下載之前建置的成品,並打包進目前版本的 Release 頁面:

uses: softprops/action-gh-release@v1

發佈頁面自動產生更新說明(generate_release_notes: true),方便使用者查看版本變更。

最終效果如下圖所示:

🔖 v1.0.0
├── SharpIco-windows-v1.0.0.zip
├── SharpIco-linux-v1.0.0.tar.gz
└── SharpIco-macOS-v1.0.0.tar.gz

這裡最大的坑就是原本使用 actions/upload-artifact@v3 一直報錯,後面查了 issue 發現是已經 deprecate 了

升級到 v4 問題解決

另外就是發佈 GitHub Release 時老是衝突,一直說已存在

設定了 append 也不行……

後面我改成先上傳中轉,後面一次性發佈,才終於成功了😂

小結

SharpIco 是我基於 .NET 9 和 AOT 編譯能力打造的一款純 C# 圖示工具,目標是取代繁瑣依賴、簡化圖示產生與驗證流程

ImageSharp 影像處理,到 BinaryWriter 手工拼裝 ICO 格式;從 System.CommandLine 打造命令列體驗,到 GitHub Actions 全流程自動化發佈;SharpIco 不僅是一個實用工具,也是一場小而美的工程探索。

它代表了我對工具理想的追求:輕量、純粹、易整合、跨平台、即開即用

  • 無需安裝 Python、Node 或 ImageMagick
  • 支援 AOT 編譯,產生原生執行檔
  • 同時具備圖示產生與結構分析功能
  • 一次發佈,自動產出全平台建置結果

歡迎 Star / Fork / Issue / PR,歡迎將它整合進你的建置系統中。

📦 GitHub 專案地址: 👉 https://github.com/star-plan/sharp-ico

繼續探索

延伸閱讀

更多文章
同分類 / 同專題 2026/2/7

AOT使用經驗總結

從專案建立伊始,就應養成良好的習慣,即只要添加了新功能或使用了較新的語法,就及時進行 AOT 發布測試。

繼續閱讀
同分類 / 同專題 2023/8/29

.NET 8.0 AOT DebugView

Debugview 是一個應用程式,支援你監視本機系統上或可透過 TCP/IP 存取的網路上任何電腦的偵錯輸出。

繼續閱讀