mono環境のC#で画像をグレースケール化

コンピュータ

フォームへ画像ファイルをドラッグアンドドロップするとグレースケールへ変換された画像が表示されます。

// ToGrayscale01.cs

using System;
using System.Drawing;
using System.Windows.Forms;
using System.IO;
using System.Threading.Tasks;
using System.Drawing.Imaging;
/*
ビルド
mcs ToGrayscale01.cs /r:System.Windows.Forms.dll /r:System.Drawing.dll
実行
mono ToGrayscale01.exe
*/

public partial class Form1 : Form
{
    // 画像をグレースケールへ変換
    static Bitmap InvertImage(Bitmap src)
    {
        // srcビットマップと同じ幅、高さ、深度のオブジェクトを作成
        Bitmap dst = new Bitmap(src.Width, src.Height, src.PixelFormat);

        BitmapData srcd = src.LockBits(
            new Rectangle(0, 0, src.Width, src.Height),
            ImageLockMode.ReadWrite,
            src.PixelFormat
        );
        BitmapData dstd = dst.LockBits(
            new Rectangle(0, 0, dst.Width, dst.Height),
            ImageLockMode.ReadWrite,
            dst.PixelFormat
        );

        int byteWidth = (int)(srcd.Stride / src.Width);

        byte[] srcPixels = new byte[srcd.Stride * src.Height];
        byte[] dstPixels = new byte[dstd.Stride * dst.Height];

        System.Runtime.InteropServices.Marshal.Copy(
            srcd.Scan0, srcPixels, 0, srcPixels.Length);
        
        for (int y = 0; y < src.Height; y++)
        {
            for (int x = 0; x < srcd.Width; x++)
            {
                int pos = y * srcd.Stride + x * byteWidth;
                
                for (int i = 0; i < byteWidth; i++)
                {
                    dstPixels[pos+i] = srcPixels[pos+i];
                }

                if (byteWidth >= 3)
                {
                    // double v = (double)srcPixels[pos]/3.0d + (double)srcPixels[pos+1]/3.0d + (double)srcPixels[pos+2]/3.0d;
                    double v = (double)srcPixels[pos]*0.114d + (double)srcPixels[pos+1]*0.587d + (double)srcPixels[pos+2]*0.299d;
                    byte vb = (byte)v;
                    dstPixels[pos] = vb;
                    dstPixels[pos+1] = vb;
                    dstPixels[pos+2] = vb;
                }
            }
        }
        System.Runtime.InteropServices.Marshal.Copy(
            dstPixels, 0, dstd.Scan0, dstPixels.Length);

        src.UnlockBits(srcd);
        dst.UnlockBits(dstd);
        return dst;
    }
    // パネル
    Panel panel1 = new Panel()
    {
        Dock = DockStyle.Fill, // クライアント領域全体に敷き詰める
        AllowDrop = true, // ドラグアンドドロップを受け入れる
        AutoScroll = true, // 自動スクロール
        BackColor = Color.Gray,
    };
    // ピクチャボックス
    PictureBox picbox1 = new PictureBox()
    {
        SizeMode = PictureBoxSizeMode.AutoSize, // 画像サイズに合わせてサイズ変更
    };
    // コンストラクタ
    public Form1()
    {
        picbox1.Parent = panel1;
        panel1.Parent = this;
        Size = new Size(800, 600);

        // ドラッグエンター
        panel1.DragEnter += (s, e) =>
        {
            e.Effect = e.Data.GetDataPresent(DataFormats.FileDrop) ? DragDropEffects.Copy : DragDropEffects.None;
        };
        // ドラッグドロップ
        panel1.DragDrop += async (s, e) =>
        {
            string path = ((string[])e.Data.GetData(DataFormats.FileDrop, false))[0];

            // ピクチャボックスに表示されているイメージオブジェクトを破棄
            if (picbox1.Image != null)
            {
                picbox1.Image.Dispose();
                picbox1.Image = null;
            }
            // ピクチャボックスへ画像ファイルからイメージオブジェクトをセット
            using (FileStream fs = File.OpenRead(path))
            {
                picbox1.Image = await Task.Run(() => {
                    using (Bitmap bmp = (Bitmap)Image.FromStream(fs))
                    {
                        // 色を反転
                        return InvertImage(bmp);
                    }
                });
            }
        };
    }
    static void Main()
    {
        Application.Run(new Form1());
    }
}

コメント