より良いエンジニアを目指して

1日1つ。良くなる!上手くなる!

Macで256色のドット絵エディタを作ろうとしたが

カラーパレットを取得/保存する方法に難儀しそうでした。

(以下Microsoft copilotの回答になります)

Windowsだと標準ライブラリで解決できるが。。。。

C#で256色PNGのカラーパレットを取得するには、BitmapクラスのPaletteプロパティを活用する方法があります。以下の手順で取得できます:

方法1: Bitmap.Paletteを使用

  1. Bitmapオブジェクトを作成し、PixelFormat.Format8bppIndexedを指定。
  2. Paletteプロパティを取得し、各色を取得。
using System;
using System.Drawing;
using System.Drawing.Imaging;

class Program
{
    static void Main()
    {
        Bitmap bmp = new Bitmap("your_image.png");
        ColorPalette palette = bmp.Palette;

        for (int i = 0; i < palette.Entries.Length; i++)
        {
            Console.WriteLine($"Color {i}: {palette.Entries[i]}");
        }
    }
}

方法2: System.Windows.Media.Imaging.BitmapPalettesを使用

BitmapPalettesクラスを使うと、標準のパレットを取得できます](https://learn.microsoft.com/ja-jp/dotnet/api/system.windows.media.imaging.bitmappalettes?view=windowsdesktop-9.0)。

using System.Windows.Media.Imaging;

BitmapSource image = BitmapSource.Create(
    width, height, 96, 96, PixelFormats.Indexed8, BitmapPalettes.Halftone256, pixels, stride);

方法3: Format8bppIndexedのカラーパレット設定

カラーパレットを適切に設定するには、Paletteを取得して変更する必要があります。

Bitmap bmp = new Bitmap(256, 64, PixelFormat.Format8bppIndexed);
ColorPalette pal = bmp.Palette;

for (int i = 0; i < 256; i++)
{
    pal.Entries[i] = Color.FromArgb(i, i, i);
}

bmp.Palette = pal;

Macだと

Mac + .NET Core + Avaloniaの組み合わせで256色PNGのドット絵エディタを作るなら、カラーパレットの取得・編集・保存を適切に扱えるライブラリを選ぶ必要があります。以下の選択肢が考えられます:

1. ImageSharp

メリット: - クロスプラットフォーム対応Macでも動作) - パレットの取得・編集が可能 - 軽量で扱いやすい

実装例(カラーパレット取得):

using SixLabors.ImageSharp;
using SixLabors.ImageSharp.PixelFormats;

using var image = Image.Load<Rgba32>("your_image.png");
HashSet<Rgba32> palette = new HashSet<Rgba32>();

for (int y = 0; y < image.Height; y++)
{
    for (int x = 0; x < image.Width; x++)
    {
        palette.Add(image[x, y]);
    }
}

foreach (var color in palette)
{
    Console.WriteLine($"Color: {color}");
}

注意点: - Indexed8の画像を扱う場合、パレットの管理を自前で行う必要がある。


2. SkiaSharp

メリット: - Google製の高速グラフィックスライブラリ - Avaloniaと相性が良い - カラーパレットの取得・編集が可能

実装例(カラーパレット取得):

using SkiaSharp;

using var bitmap = SKBitmap.Decode("your_image.png");
SKColor[] palette = bitmap.ColorTable;

foreach (var color in palette)
{
    Console.WriteLine($"Color: {color}");
}

注意点: - Indexed8の画像を扱う場合、パレットの編集には追加の処理が必要。


3. libpng(P/Invoke

メリット: - PNGのパレットを直接操作可能 - 細かい制御ができる

注意点: - C言語のライブラリをP/Invokeで呼び出す必要がある - 導入の手間がかかる


どれを選ぶべきか?

  • 手軽に使いたいなら → ImageSharp
  • Avaloniaとの相性を重視するなら → SkiaSharp
  • 細かい制御が必要なら → libpng(P/Invoke

どの方法が一番しっくりきそうですか?もし具体的な実装で悩んでいるなら、さらに掘り下げて考えられますよ!

Indexed8の画像とは、インデックスカラーを使用した8ビットの画像フォーマットのことです。各ピクセルの色を直接RGB値で保持するのではなく、カラーパレット(最大256色)を参照する形で色を指定します。


画像から色をHashSetにしてパレットにしてしまうと、パレット情報がロストしてしまいますからね。。。

使われていない色はもちろん、順番も変わってしまいますから。

Indexed8の特徴

  • 色数制限: 最大256色までのカラーパレットを使用。
  • 軽量: フルカラー画像(24ビット)よりもファイルサイズが小さく、メモリ消費が少ない。
  • パレット管理: 色の変更はパレットを編集することで可能。
  • ドット絵向き: 限られた色数で表現するドット絵やレトロゲームのグラフィックに適している。

Indexed8の仕組み

ピクセル0〜255のインデックス値を持ち、その値に対応する色がパレット内に定義されています。例えば:

ピクセルデータ: [0, 1, 2, 3, 4, 5, ...]
カラーパレット:
  0 → 赤 (#FF0000)
  1 → 緑 (#00FF00)
  2 → 青 (#0000FF)
  3 → 黄色 (#FFFF00)
  4 → 黒 (#000000)
  5 → 白 (#FFFFFF)

このように、ピクセルデータは単なるインデックス値の配列であり、実際の色はパレットを参照して決定されます。

Indexed8の用途

  • ドット絵エディタ(例えば、レトロゲームのスプライト作成)
  • GIF画像(GIFもインデックスカラーを使用)
  • レトロゲームのグラフィック
  • メモリ制約のある環境(組み込みシステムなど)

Mac + .NET Core + Avaloniaでドット絵エディタを作るなら、Indexed8のカラーパレットを適切に管理できるライブラリ(ImageSharpやSkiaSharpなど)を選ぶのが重要ですね。

この説明でイメージ湧きましたか?もう少し掘り下げてもいいですよ!