実行環境構築
プロジェクトの作成
mkdir BmpToCsicon
cd BmpToCsicon
dotnet new console
dotnet add package System.Drawing.Common
ソースプログラム
using System;
using System.IO;
using System.Drawing;
using System.Drawing.Imaging;
public class BmpToCs
{
static public void Main(string[] args)
{
if (!OperatingSystem.IsWindows() || args.Length == 0)
{
return;
}
var path = args[0];
using var fs = new FileStream(path, FileMode.Open, FileAccess.Read);
using var bmp = new Bitmap(fs);
var bmpData = bmp.LockBits(
new Rectangle(0, 0, bmp.Width, bmp.Height),
ImageLockMode.ReadOnly,
bmp.PixelFormat);
var col = Math.Abs(bmpData.Stride);
byte[] bytes = new byte[col * bmp.Height];
System.Runtime.InteropServices.Marshal.Copy(
bmpData.Scan0,
bytes, 0, bytes.Length);
string srcCode = "";
srcCode += "using System.Drawing;\n";
srcCode += "using System.Drawing.Imaging;\n";
srcCode += "\n";
srcCode += "public class IconBin\n";
srcCode += "{\n";
srcCode += String.Format("\tstatic public int Height = {0};\n", bmp.Height);
srcCode += String.Format("\tstatic public int Width = {0};\n", bmp.Width);
srcCode += String.Format("\tstatic public int PFormat = {0};\n", (int)bmp.PixelFormat);
srcCode += "\tstatic public byte[] Bytes = new byte[]\n";
srcCode += "\t{\n";
for (var i = 0; i < bytes.Length; i++)
{
if ((i % 64) == 0) srcCode += "\n\t\t";
srcCode += String.Format("0x{0:X},", bytes[i]);
}
srcCode += "\n\t};//bins\n";
srcCode += @"
static public Icon GetIcon()
{
var dst = new Bitmap(Width, Height, (System.Drawing.Imaging.PixelFormat)PFormat);
var bmpData = dst.LockBits(
new Rectangle(0, 0, dst.Width, dst.Height),
ImageLockMode.ReadWrite,
dst.PixelFormat);
System.Runtime.InteropServices.Marshal.Copy(
Bytes,
0, bmpData.Scan0,
Bytes.Length);
dst.UnlockBits(bmpData);
return Icon.FromHandle(dst.GetHicon());
}
";
srcCode += "}//class\n";
bmp.UnlockBits(bmpData);
using (var sw = new StreamWriter("icon.cs", false))
{
sw.Write(srcCode);
}
}
}
実行
PS<BmpToCsicon.exe <ビットマップファイルのパス>
成功すると”icon.cs”が出来上がります。
icon.csを使ってみる
適当なWinFormsのプロジェクトフォルダにicon.csをコピーします。
Form1.csでicon.cs内のクラスメソッドIconBin.GetIcon()を呼び出しフォームのIconプロパティに割り当てます。
namespace TestForm;
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
this.Icon = IconBin.GetIcon();
}
}
実行してみるとフォームにアイコンが割り当てられたことが確認出来ます。
感想
dotnet sdk環境でアイコンなどのリソースを.exeに埋め込む方法が見つけられなかったので、ビットマップをbyte配列にしてC#のソースコードに埋め込むという苦肉の策を思いつき試してみました。
無圧縮のビットマップのバイナリをテキストとしてソースコードに書き込みますので、ソースファイルのサイズは大きくなります。ちなみに32×32のビットマップファイルから生成したicon.csのファイルサイズは約16KBほどでした。
コメント