【C#.NET解説】Bitmapクラスの機能と画像処理への応用を徹底解説 ピクセル単位の画像操作に強い基本クラスの使い方

2025年6月27日金曜日

描画

t f B! P L

【C#.NET解説】Bitmapクラスの機能と画像処理への応用を徹底解説 ピクセル単位の画像操作に強い基本クラスの使い方

ホルス

名前空間 System.Drawing

Bitmapクラスは、C#.NETにおける画像処理の中核的存在であり、ピクセル単位での精密な操作が可能な重要クラスです。

自己紹介

Bitmapクラスは、System.Drawing名前空間に属する、Imageクラスを継承したクラスです。 画像の読み込み・生成から、色の変更や描画などの処理を担うことができます。

基本機能

主な基本機能には以下があります。

  • 画像ファイルからの読み込み
  • 指定サイズの新規画像生成
  • ピクセル単位での色の取得・設定
  • Graphicsオブジェクトとの連携による描画処理
C#

using System.Drawing;

// ファイルからBitmapを生成
Bitmap bmp = new Bitmap("sample.jpg");

// 新しいBitmapの生成
Bitmap newBmp = new Bitmap(200, 100);

よく使う場面と注意点

Bitmapクラスは、画像編集、キャプチャ保存、画像比較など、視覚処理のあらゆる場面で使われます。

ただし以下の点に注意が必要です:

  • Disposeを明示的に呼び出してリソース解放を行う
  • SetPixel/GetPixelは大量処理に不向き
  • ファイルアクセス時に例外が発生しやすいためtry-catchが望ましい
C#

using (Bitmap bmp = new Bitmap("image.jpg"))
{
    // ピクセルの色を取得
    Color color = bmp.GetPixel(10, 20);

    // ピクセルの色を変更
    bmp.SetPixel(10, 20, Color.Red);

    // ファイルに保存
    bmp.Save("modified.jpg");
}

高速処理と特殊機能の活用

大量のピクセルを処理したい場合は、GetPixelSetPixel よりも、 LockBits を使った方法が圧倒的に高速です。これは、Bitmap全体のビットマップデータを直接メモリ領域として確保し、 unsafeコードやポインタを通じて処理できるためです。

以下の例では、画像全体を明るくする処理を LockBits を使って行います。 このように、「高速かつ大量のピクセル処理」に適しています。

C#

using System.Drawing;
using System.Drawing.Imaging;
using System;

Bitmap bmp = new Bitmap("input.jpg");
Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
BitmapData data = bmp.LockBits(rect, ImageLockMode.ReadWrite, bmp.PixelFormat);

unsafe
{
    byte* ptr = (byte*)data.Scan0;

    int bytesPerPixel = Image.GetPixelFormatSize(data.PixelFormat) / 8;
    int height = data.Height;
    int width = data.Width;

    for (int y = 0; y < height; y++)
    {
        byte* row = ptr + (y * data.Stride);
        for (int x = 0; x < width; x++)
        {
            int idx = x * bytesPerPixel;

            // 明るくする処理(各色に+50、255を上限)
            row[idx] = (byte)Math.Min(row[idx] + 50, 255);       // B
            row[idx + 1] = (byte)Math.Min(row[idx + 1] + 50, 255); // G
            row[idx + 2] = (byte)Math.Min(row[idx + 2] + 50, 255); // R
        }
    }
}

bmp.UnlockBits(data);
bmp.Save("brightened.jpg");
bmp.Dispose();

出力結果として、「input.jpg」が全体的に明るく補正された画像「brightened.jpg」として保存されます。 この処理は、SetPixel を何万回も繰り返すより圧倒的に高速です。

一方、MakeTransparent を使うと、指定した色と一致するすべてのピクセルを透明に変換できます。 以下は白い背景の画像を透過PNGに変換する例です。

C#

using System.Drawing;
using System.Drawing.Imaging;

Bitmap bmp = new Bitmap("white_background.png");

// 白色部分を透明化
bmp.MakeTransparent(Color.White);

// PNG形式で保存(透過対応)
bmp.Save("transparent.png", ImageFormat.Png);
bmp.Dispose();

出力結果は、「white_background.png」の白い部分が透明になった「transparent.png」です。 これにより、画像を重ねたときに背景を透かして表示することが可能になります。

具体的な使い方

BitmapクラスはGraphicsと連携させることで、画像に対して文字や図形を直接描画することができます。 以下は、画像上に異なるフォント・色・位置で複数行のテキストを重ねて描画するサンプルです。

C#

using System.Drawing;
using System.Drawing.Imaging;

using (Bitmap bmp = new Bitmap(400, 200))
using (Graphics g = Graphics.FromImage(bmp))
{
    // 背景を白で塗りつぶす
    g.Clear(Color.White);

    // 大きな見出し
    using (Font titleFont = new Font("Segoe UI", 20, FontStyle.Bold))
    {
        g.DrawString("画像へのタイトル描画", titleFont, Brushes.DarkBlue, new PointF(10, 20));
    }

    // 小さな補足文字(別のフォントと色)
    using (Font captionFont = new Font("Segoe UI", 12, FontStyle.Italic))
    {
        g.DrawString("これはサンプルの説明です", captionFont, Brushes.Gray, new PointF(10, 60));
    }

    // 強調文字(赤・太字・重ねて表示)
    using (Font alertFont = new Font("Arial", 16, FontStyle.Bold))
    {
        g.DrawString("※重要:保存前に確認を!", alertFont, Brushes.Red, new PointF(10, 100));
    }

    // 保存(PNG形式なら文字もくっきり表示)
    bmp.Save("text_overlay.png", ImageFormat.Png);
}

このコードでは、g.DrawString を3回使って異なるスタイルの文字を同じ画像に描画しています。

  • タイトル(青色・大サイズ)
  • 補足説明(グレー・小さめ・イタリック)
  • 警告(赤・太字)

出力結果の text_overlay.png には、情報が視覚的に整理された状態で文字が重ねられています。 業務アプリケーションや帳票出力などにも応用しやすい使い方です。

その他の便利なメソッド一覧

  • RotateFlip:回転や反転処理
  • MakeTransparent:特定色を透明化
  • Clone:画像の一部を切り抜いて複製
  • Dispose:リソース解放
C#

Bitmap bmp = new Bitmap("sample.png");

// 回転と反転
bmp.RotateFlip(RotateFlipType.Rotate180FlipY);

// 白色を透明に
bmp.MakeTransparent(Color.White);

// 一部を切り抜いて保存
Bitmap part = bmp.Clone(new Rectangle(50, 50, 100, 100), bmp.PixelFormat);
part.Save("partial.png");

// リソース解放
bmp.Dispose();
part.Dispose();

このブログを検索

QooQ