0
2

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 3 years have passed since last update.

【C#】ネコのイラストを描く(Bitmap)

Posted at

はじめに

これまでにC#を使った画像処理の記事を3つほど書きましたが、画像の描画については「1ピクセルずつ描画する」「同じ図形を一定のパターンで描画し続ける」というレベルに留まっていました。

そこで今回はお絵かきソフトでイラストを作る時のように、「複数の図形を組み合わせて猫のイラストを描画する」という処理を作ってみました。

コード

  • 長方形、多角形、楕円、円弧、扇形を描く塗りつぶした図形を描くという記事を参考にして、猫の顔のパーツを1つずつ作って重ね合わせました。
  • 顔と目は楕円、耳は三角形(=ポリゴン)、口は円弧、髭は直線とそれぞれ異なる図形を使いました。
  • 顔と耳は塗りつぶしと
  • レイヤーが無く、「図形を描画する順番=図形の重ね合わせの順序」となるため、描画する順番を少し工夫しました。
  • 目、口、髭は最前面にならないといけないので、一番最後に描画しています。
  • コーディングよりも苦労したのは顔の各パーツのサイズや配置でした。
  • 絵心が無いので、顔のパーツとなる図形のサイズや位置を少しずつ変えて調整しました...
CatDrawer.cs
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CSharpStudy.Image
{
    public class CatDrawer
    {
        /// <summary>
        /// 猫のイラストを描画するBitmapオブジェクト。
        /// </summary>
        Bitmap bmp;

        /// <summary>
        /// コンストラクタ。
        /// </summary>
        public CatDrawer()
        {
            // キャンバスサイズは横500px、縦400px。
            this.bmp = new Bitmap(500, 400);
        }

        /// <summary>
        /// 猫のイラストを描画する。
        /// </summary>
        public void Draw(string filePath)
        {
            using (Graphics g = Graphics.FromImage(bmp))
            {
                // 顔の輪郭を描く。
                g.DrawEllipse(new Pen(GetFaceBorderColor(), 5), GetFacePosition());
                g.DrawPolygon(new Pen(GetFaceBorderColor(), 5), GetLeftEarPosition());
                g.DrawPolygon(new Pen(GetFaceBorderColor(), 5), GetRightEarPosition());

                // 顔の色を塗る。
                g.FillEllipse(new SolidBrush(GetFaceColor()), GetFacePosition());
                g.FillPolygon(new SolidBrush(GetFaceColor()), GetLeftEarPosition());
                g.FillPolygon(new SolidBrush(GetFaceColor()), GetRightEarPosition());

                // その他の顔のパーツを作る。
                g.FillEllipse(Brushes.Black, 190, 200, 15, 50);  // 右目
                g.FillEllipse(Brushes.Black, 295, 200, 15, 50);  // 左目
                g.DrawArc(new Pen(Color.Black, 5), new Rectangle(190, 270, 60, 60), 0, 180);    // 口(右側)
                g.DrawArc(new Pen(Color.Black, 5), new Rectangle(250, 270, 60, 60), 0, 180);    // 口(左側)
                g.DrawLine(new Pen(Color.Black, 5), new Point(5, 210), new Point(120, 225));    // ひげ1(右側)
                g.DrawLine(new Pen(Color.Black, 5), new Point(0, 250), new Point(120, 250));    // ひげ2(右側)
                g.DrawLine(new Pen(Color.Black, 5), new Point(5, 290), new Point(120, 275));    // ひげ3(右側)


                g.DrawLine(new Pen(Color.Black, 5), new Point(380, 225), new Point(495, 210));    // ひげ1(左側)
                g.DrawLine(new Pen(Color.Black, 5), new Point(380, 250), new Point(500, 250));    // ひげ2(左側)
                g.DrawLine(new Pen(Color.Black, 5), new Point(380, 275), new Point(495, 290));    // ひげ3(左側)

            }

            // 画像をPNG形式で保存する。
            bmp.Save(filePath, System.Drawing.Imaging.ImageFormat.Png);
        }

        /// <summary>
        /// 猫の顔の色を返す。
        /// </summary>
        /// <returns></returns>
        private Color GetFaceColor()
        {
            return Color.FromArgb(255, 221, 209, 174);
        }

        /// <summary>
        /// 猫の顔の枠線の色を返す。
        /// </summary>
        /// <returns></returns>
        private Color GetFaceBorderColor()
        {
            return Color.FromArgb(255, 182, 156, 78);
        }
        
        /// <summary>
        /// 顔を描画する座標(外接する長方形)を返す。
        /// </summary>
        /// <returns></returns>
        private Rectangle GetFacePosition()
        {
            return new Rectangle(50, 100, 400, 280);
        }

        /// <summary>
        /// 左耳を描画する座標を返す。
        /// </summary>
        /// <returns></returns>
        private Point[] GetLeftEarPosition()
        {
            return new Point[] {
                new Point(430, 30),
                new Point(430, 210),
                new Point(300, 110)
            };
        }

        /// <summary>
        /// 右耳を描画する座標を返す。
        /// </summary>
        /// <returns></returns>
        private Point[] GetRightEarPosition()
        {
            return new Point[] {
                new Point(70, 30),
                new Point(70, 210),
                new Point(200, 110)
            };
        }
    }
}

実行用のコード

CatDrawerTest.cs
using System;
using System.Text;
using System.Collections.Generic;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using CSharpStudy.Image;

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

        [TestMethod]
        public void TestMethod1()
        {
            CatDrawer drawer = new CatDrawer();
            drawer.Draw(BITMAP_PATH);
        }
    }
}

生成された画像

  • 茶トラが好きなので茶色にしました...というのは嘘で、体の模様が三毛猫や鉢割れだと描画するのが大変なので、茶色一色で仕上げました。
  • アンチエイリアスをどうやって入れるかが分からなかったので、線の周囲がギザギザになってしまったのが残念な点です。

generated_cat.png

参考URL

0
2
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
0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?