2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

C#でアイコンファイルを保存する(手抜き)

Posted at

 C#でアプリケーションを作っていて、アイコンを設定したかったが、アイコンファイルを作成するのに少し手間取った。例えばWindowsに付属するペイントや、あるいは普段使用しているpaint.netではICOファイルを保存できない。
 C#ではImage.SaveにImageFormatオプションでIconを指定できるが、この場合はPNGで保存されてしまう。

 ICOファイルは結構簡単なフォーマットらしいので、C#でICOファイルを保存してみた。

 流れとしては、外部のソフトウェア(適当なペイントソフトやドローソフト)で作成したアイコンの画像をC#で読み込み、それをICOのフォーマットに従って保存している。

static void ImagesToIcon(Image[] images, Stream dst)
{
    if (dst.Length != 0 ||
        images.Length < 1 ||
        short.MaxValue < images.Length ||
        images.Any(a => a.PixelFormat != System.Drawing.Imaging.PixelFormat.Format32bppArgb))
    {
        throw new InvalidOperationException();
    }

    ; void WriteInt(int x)
     => dst.Write(MemoryMarshal.Cast<int, byte>(new(ref x)));

    WriteInt(0x0001_0000);
    dst.Write(BitConverter.GetBytes((ushort)images.Length));

    dst.Write(new byte[images.Length * 16]);

    foreach (var (i, image) in images.Select((a, i) => (i, a)))
    {
        var offset = dst.Position;
        image.Save(dst, System.Drawing.Imaging.ImageFormat.Png);
        var size = dst.Position - offset;

        dst.Position = 6 + i * 16 + 8;
        WriteInt((int)size);
        WriteInt((int)offset);
        dst.Position = dst.Length;
    }
}

 一部のパラメーター(解像度とかビット深度とか)は0を設定している。一応動作していることを確認しているが、すべての環境で動作するとは限らない(今回は自分用に作ったツールを識別する目的なので、自分のPCで動けばOKとした)。

 ICOファイルにはいくつかのフォーマットで画像を埋め込むことができるらしいが、今回はPNGを埋め込んでいる。24bitPNGはだめらしく、32bitPNGが必要。読み込んだ画像が24bitだった場合はusing var bmp = tmp.Clone(new() { Size = tmp.Size }, PixelFormat.Format32bppArgb)のような感じでフォーマットを変換しておく。もちろん透過を含む画像も扱える。

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?