Windowsのエクスプローラーの「送る」からカラー画像をグレースケールに変換するプログラムです。
実行環境構築
プロジェクトの作成
mkdir プロジェクト名
cd プロジェクト名
dotnet new console
dotnet add package System.Drawing.Common
ソースプログラム
using System.Drawing;
using System.Drawing.Imaging;
public class Program1
{
// グレースケールへ変換
public static Bitmap? ToGray(Bitmap bmp)
{
if (!System.OperatingSystem.IsWindows()) return null;
var width = bmp.Width;
var height = bmp.Height;
var dst = new Bitmap(width, height, PixelFormat.Format8bppIndexed);
var dstData = dst.LockBits(
new Rectangle(0, 0, width, height),
ImageLockMode.ReadWrite,
dst.PixelFormat
);
var dstStride = Math.Abs(dstData.Stride);
var dstPicData = new byte[dstStride * dstData.Height];
System.Runtime.InteropServices.Marshal.Copy(
dstData.Scan0,
dstPicData,
0,
dstStride * dstData.Height
);
var bmpData = bmp.LockBits(
new Rectangle(0,0,width, height),
ImageLockMode.ReadWrite,
bmp.PixelFormat
);
var stride = Math.Abs(bmpData.Stride);
int channel = Bitmap.GetPixelFormatSize(bmp.PixelFormat) / 8;
var picData = new byte[stride * bmpData.Height];
System.Runtime.InteropServices.Marshal.Copy(
bmpData.Scan0,
picData,
0,
stride * bmpData.Height
);
Parallel.For(0, height, y =>
{
int lineIndex = stride * y;
int dstIndex = dstStride * y;
for (int x = 0; x < width; x++)
{
var value = picData[lineIndex + x * channel] * 0.299;
value += picData[lineIndex + x * channel + 1] * 0.587;
value += picData[lineIndex + x * channel + 2] * 0.114;
dstPicData[dstIndex + x] = (byte)value;
}
});
System.Runtime.InteropServices.Marshal.Copy(
dstPicData,
0,
dstData.Scan0,
dstStride * dstData.Height
);
bmp.UnlockBits(bmpData);
dst.UnlockBits(dstData);
var pallet = dst.Palette;
for(int i = 0; i < 255; i++)
{
pallet.Entries[i] = Color.FromArgb(i, i, i);
}
dst.Palette = pallet;
return dst;
}
public static void Main(string[] args)
{
if (!OperatingSystem.IsWindows()) return;
foreach(var srcFile in args)
{
Bitmap? src = null;
Bitmap? dst = null;
using (var fs = new FileStream(srcFile, FileMode.Open))
{
src = new Bitmap(fs);
}
if (src is not null)
{
dst = ToGray(src);
if (dst is not null)
{
var dir = Path.GetDirectoryName(srcFile);
var file = Path.GetFileNameWithoutExtension(srcFile);
var dstFile = Path.Join(dir, file+".png");
dst.Save(dstFile, System.Drawing.Imaging.ImageFormat.Png);
}
}
src?.Dispose();
}
}
}
ビルド
dotnet build -c Release
使い方
ビルドで作成された実行ファイルをエクスプローラーの「送る」にショートカットを作成
試したところ複数のファイルを「送る」処理にも対応していました。
コメント