【C#】画像をグレースケールに変換する

# はじめに

以前に[画像の差分を得る](https://qiita.com/nkojima/items/1fb901c13f9707808bc0)プログラムを作成しましたが、今回は既存のカラー画像をグレースケールに変換するコードを作ってみました。

# 作成したコード


* 今回は「0～255で表されるR/G/Bの値の平均値を使って画像をグレースケールにする」という最も単純な方法（というよりも独自の方法？）にしました。
* [カラーをグレースケールに変換する](https://ja.wikipedia.org/wiki/%E3%82%B0%E3%83%AC%E3%83%BC%E3%82%B9%E3%82%B1%E3%83%BC%E3%83%AB#%E3%82%AB%E3%83%A9%E3%83%BC%E3%82%92%E3%82%B0%E3%83%AC%E3%83%BC%E3%82%B9%E3%82%B1%E3%83%BC%E3%83%AB%E3%81%AB%E5%A4%89%E6%8F%9B%E3%81%99%E3%82%8B)には本来複雑な計算式が必要なのですが、今回は便宜的にR/G/Bの平均値を用いました。
 * 何となくグレーになっていればOK...ということにしておきました。

```csharp:GrayConverter.cs
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CSharpStudy.Image
{
    /// <summary>
    /// 画像をグレースケールに変換するクラス。
    /// </summary>
    public class GrayConverter
    {
        /// <summary>
        /// 指定した画像をグレースケールに変換する。
        /// </summary>
        /// <param name="bmpPath">変換する画像のファイルパス。</param>
        /// <param name="path">グレースケール画像の保存先となるファイルパス。</param>
        public void ToGrayScale(string bmpPath, string path = @".\gray_image.png")
        {
            // 画像を比較する際に「大きい方の画像」のサイズに合わせて比較する。
            Bitmap bmp = new Bitmap(bmpPath);
            int width = bmp.Width;
            int height = bmp.Height;

            Bitmap grayBmp = new Bitmap(width, height);         // グレースケールの画像。

            // 全ピクセルを1つずつグレースケールに変換する。
            for (int i = 0; i < width; i++)
            {
                for (int j = 0; j < height; j++)
                {
                    try
                    {
                        // NTSC規格などに準拠せず、RGB値の平均値をグレースケールに変える。
                        // https://dobon.net/vb/dotnet/graphics/grayscale.html
                        Color pixelColor = bmp.GetPixel(i, j);
                        byte grayScale = Convert.ToByte((pixelColor.R + pixelColor.G + pixelColor.B) / 3);
                        // RGBだけでなく、アルファ値もセットする。
                        Color grayColor = Color.FromArgb(pixelColor.A, grayScale, grayScale, grayScale);
                        grayBmp.SetPixel(i, j, grayColor);
                    }
                    catch
                    {
                        System.Console.Error.WriteLine("(" + i + "," + j + ")ピクセルでエラーが発生しました。");
                    }
                }
            }
            grayBmp.Save(path, ImageFormat.Png);
            return;
        }
    }
}
```

# 実行用のテストコード

```csharp:GrayConverterTest.cs
using System;
using System.Text;
using System.Collections.Generic;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using CSharpStudy.Image;

namespace CSharpStudyTest
{
    /// <summary>
    /// GrayConverterクラスのテストコード
    /// </summary>
    [TestClass]
    public class GrayConverterTest
    {
        private const string BITMAP1_PATH = @"C:\Users\NKOJIMA\source\repos\CSharpStudy\CSharpStudy\Image\cat1.png";
        private const string GRAY_IMG_PATH = @"C:\Users\NKOJIMA\source\repos\CSharpStudy\CSharpStudy\Image\gray_image.png";

        [TestMethod]
        public void TestMethod1()
        {
            GrayConverter gConverter = new GrayConverter();
            gConverter.ToGrayScale(BITMAP1_PATH, GRAY_IMG_PATH);
        }
    }
}
```

# 処理結果

* 入力画像を一応グレースケールで出力させることには成功しました。

|処理に使った画像|処理結果の画像|
|---|---|
|![cat1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/312166/eb9a7ce5-e623-89eb-ad19-f25f57502f82.png)|![gray_image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/312166/8502445b-1349-12e1-81fc-8ef5fa45923c.png)|

# 参考URL

* [【C#】2つの画像の差分を得る（Bitmap）](https://qiita.com/nkojima/items/1fb901c13f9707808bc0)
* [画像をグレースケールに変換して表示する](https://dobon.net/vb/dotnet/graphics/grayscale.html)