DOBON.NET プログラミング道: .NET Framework, VB.NET, C#, Visual Basic, Visual Studio, インストーラ, ...

画像をセピア調にして表示する

注意:画像の表示方法が分からないという方は、まず「コントロールやフォームに画像を表示する」をご覧ください。

画像をセピア調にする方法が、「.NET Matters: Sepia Tone, StringLogicalComparer, and More」で紹介されています。これによると、次のような色の変換でセピア調にできるということです。

新しいR = (R * .393) + (G * .769) + (B * .189)
新しいG = (R * .349) + (G * .686) + (B * .168)
新しいB = (R * .272) + (G * .534) + (B * .131)

この式によって、ColorMatrixクラスを使って画像をセピア調に変換する例を示します。PictureBoxコントロール(PictureBox1)をクリックすると、PictureBox1に画像(C:\test\1.png)をセピア調にして表示しています。なおColorMatrixクラスについて詳しくは、「画像のカラーバランスを補正して表示する」をご覧ください。

VB.NET
コードを隠すコードを選択
'Imports System.Drawing

''' <summary>
''' 指定した画像をセピア調にした画像を作成する
''' </summary>
''' <param name="img">基の画像</param>
''' <returns>作成されたセピア調の画像</returns>
Public Shared Function CreateSepiatoneImage(ByVal img As Image) As Image
    'セピア調の画像の描画先となるImageオブジェクトを作成
    Dim newImg As New Bitmap(img.Width, img.Height)
    'newImgのGraphicsオブジェクトを取得
    Dim g As Graphics = Graphics.FromImage(newImg)

    'ColorMatrixオブジェクトの作成
    'セピア調に変換するための行列を指定する
    Dim cm As New System.Drawing.Imaging.ColorMatrix( _
        New Single()() { _
            New Single() {0.393F, 0.349F, 0.272F, 0, 0}, _
            New Single() {0.769F, 0.686F, 0.534F, 0, 0}, _
            New Single() {0.189F, 0.168F, 0.131F, 0, 0}, _
            New Single() {0, 0, 0, 1, 0}, _
            New Single() {0, 0, 0, 0, 1}})
    'ImageAttributesオブジェクトの作成
    Dim ia As New System.Drawing.Imaging.ImageAttributes()
    'ColorMatrixを設定する
    ia.SetColorMatrix(cm)

    'ImageAttributesを使用してセピア調に描画
    g.DrawImage(img, New Rectangle(0, 0, img.Width, img.Height), _
                0, 0, img.Width, img.Height, GraphicsUnit.Pixel, ia)

    'リソースを解放する
    g.Dispose()

    Return newImg
End Function

'PictureBox1のClickイベントハンドラ
Private Sub PictureBox1_Click(ByVal sender As Object, ByVal e As EventArgs) _
        Handles PictureBox1.Click
    'セピア調にする画像
    Dim img As New Bitmap("C:\test\1.png")
    'セピア調に変換
    Dim sepiaImg As Image = CreateSepiatoneImage(img)
    img.Dispose()
    'PictureBox1に表示
    If Not PictureBox1.Image Is Nothing Then
        PictureBox1.Image.Dispose()
    End If
    PictureBox1.Image = sepiaImg
End Sub
C#
コードを隠すコードを選択
//using System.Drawing;

/// <summary>
/// 指定した画像をセピア調にした画像を作成する
/// </summary>
/// <param name="img">基の画像</param>
/// <returns>作成されたセピア調の画像</returns>
public static Image CreateSepiatoneImage(Image img)
{
    //セピア調の画像の描画先となるImageオブジェクトを作成
    Bitmap newImg = new Bitmap(img.Width, img.Height);
    //newImgのGraphicsオブジェクトを取得
    Graphics g = Graphics.FromImage(newImg);

    //ColorMatrixオブジェクトの作成
    //セピア調に変換するための行列を指定する
    System.Drawing.Imaging.ColorMatrix cm =
        new System.Drawing.Imaging.ColorMatrix(
            new float[][] {
                new float[] {.393f, .349f, .272f, 0, 0},
                new float[] {.769f, .686f, .534f, 0, 0},
                new float[] {.189f, .168f, .131f, 0, 0}, 
                new float[] {0, 0, 0, 1, 0},
                new float[] {0, 0, 0, 0, 1}
            });
    //ImageAttributesオブジェクトの作成
    System.Drawing.Imaging.ImageAttributes ia =
        new System.Drawing.Imaging.ImageAttributes();
    //ColorMatrixを設定する
    ia.SetColorMatrix(cm);

    //ImageAttributesを使用してセピア調に描画
    g.DrawImage(img,
        new Rectangle(0, 0, img.Width, img.Height),
        0, 0, img.Width, img.Height, GraphicsUnit.Pixel, ia);

    //リソースを解放する
    g.Dispose();

    return newImg;
}

//PictureBox1のClickイベントハンドラ
private void PictureBox1_Click(object sender, EventArgs e)
{
    //セピア調にする画像
    Bitmap img = new Bitmap(@"C:\test\1.png");
    //セピア調に変換
    Image sepiaImg = CreateSepiatoneImage(img);
    img.Dispose();
    //PictureBox1に表示
    if (PictureBox1.Image != null)
    {
        PictureBox1.Image.Dispose();
    }
    PictureBox1.Image = sepiaImg;
}

結果は、以下のようになります。上が変換元の画像で、下がセピア調に変換された後の画像です。

セピア調に変換された画像

.NET Mattersにも書かれていますが、ここで紹介した式が正解という訳ではありません。セピア調にする基本的な方法は、まず画像をグレースケールにしてから、赤、緑、青のカラーバランスを調節します。これらのやり方によって、色合いを変えることができます。

以下に紹介する例では、「画像をグレースケールに変換して表示する」のコードを基に、グレースケールと、さらに赤、緑、青の濃さを変更できるようにしています。

VB.NET
コードを隠すコードを選択
'Imports System.Drawing

''' <summary>
''' 指定した画像からグレースケール画像を作成する
''' </summary>
''' <param name="img">基の画像</param>
''' <param name="redRatio">赤色の補正比率</param>
''' <param name="greenRatio">緑色の補正比率</param>
''' <param name="blueRatio">青色の補正比率</param>
''' <returns>作成されたグレースケール画像</returns>
Public Shared Function CreateGrayscaleImage(ByVal img As Image, _
        ByVal redRatio As Single, _
        ByVal greenRatio As Single, _
        ByVal blueRatio As Single) As Image
    'グレースケールの描画先となるImageオブジェクトを作成
    Dim newImg As New Bitmap(img.Width, img.Height)
    'newImgのGraphicsオブジェクトを取得
    Dim g As Graphics = Graphics.FromImage(newImg)

    'ColorMatrixオブジェクトの作成
    'グレースケールにして、RGBに指定された補正比率をかける
    Dim cm As New System.Drawing.Imaging.ColorMatrix(New Single()() _
        { _
            New Single() {0.299F * redRatio, 0.299F * greenRatio, _
                          0.299F * blueRatio, 0, 0}, _
            New Single() {0.587F * redRatio, 0.587F * greenRatio, _
                          0.587F * blueRatio, 0, 0}, _
            New Single() {0.114F * redRatio, 0.114F * greenRatio, _
                          0.114F * blueRatio, 0, 0}, _
            New Single() {0, 0, 0, 1, 0}, _
            New Single() {0, 0, 0, 0, 1}})
    'ImageAttributesオブジェクトの作成
    Dim ia As New System.Drawing.Imaging.ImageAttributes()
    'ColorMatrixを設定する
    ia.SetColorMatrix(cm)

    'ImageAttributesを使用してグレースケールを描画
    g.DrawImage(img, New Rectangle(0, 0, img.Width, img.Height), _
                0, 0, img.Width, img.Height, GraphicsUnit.Pixel, ia)

    'リソースを解放する
    g.Dispose()

    Return newImg
End Function

'PictureBox1のClickイベントハンドラ
Private Sub PictureBox1_Click(ByVal sender As Object, ByVal e As EventArgs) _
        Handles PictureBox1.Click
    'セピア調にする画像
    Dim img As New Bitmap("C:\test\1.png")
    'セピア調に変換
    Dim sepiaImg As Image = CreateGrayscaleImage(img, 1.0F, 0.8F, 0.6F)
    img.Dispose()
    'PictureBox1に表示
    If Not PictureBox1.Image Is Nothing Then
        PictureBox1.Image.Dispose()
    End If
    PictureBox1.Image = sepiaImg
End Sub
C#
コードを隠すコードを選択
//using System.Drawing;

/// <summary>
/// 指定した画像からグレースケール画像を作成する
/// </summary>
/// <param name="img">基の画像</param>
/// <param name="redRatio">赤色の補正比率</param>
/// <param name="greenRatio">緑色の補正比率</param>
/// <param name="blueRatio">青色の補正比率</param>
/// <returns>作成されたグレースケール画像</returns>
public static Image CreateGrayscaleImage(Image img,
    float redRatio, float greenRatio, float blueRatio)
{
    //グレースケールの描画先となるImageオブジェクトを作成
    Bitmap newImg = new Bitmap(img.Width, img.Height);
    //newImgのGraphicsオブジェクトを取得
    Graphics g = Graphics.FromImage(newImg);

    //ColorMatrixオブジェクトの作成
    //グレースケールにして、RGBに指定された補正比率をかける
    System.Drawing.Imaging.ColorMatrix cm =
        new System.Drawing.Imaging.ColorMatrix(
            new float[][]{
        new float[]{0.299f * redRatio, 0.299f * greenRatio,
            0.299f * blueRatio, 0 ,0},
        new float[]{0.587f * redRatio, 0.587f * greenRatio,
            0.587f * blueRatio, 0, 0},
        new float[]{0.114f * redRatio, 0.114f * greenRatio,
            0.114f * blueRatio, 0, 0},
        new float[]{0, 0, 0, 1, 0},
        new float[]{0, 0, 0, 0, 1}
    });
    //ImageAttributesオブジェクトの作成
    System.Drawing.Imaging.ImageAttributes ia =
        new System.Drawing.Imaging.ImageAttributes();
    //ColorMatrixを設定する
    ia.SetColorMatrix(cm);

    //ImageAttributesを使用してグレースケールを描画
    g.DrawImage(img,
        new Rectangle(0, 0, img.Width, img.Height),
        0, 0, img.Width, img.Height, GraphicsUnit.Pixel, ia);

    //リソースを解放する
    g.Dispose();

    return newImg;
}

//PictureBox1のClickイベントハンドラ
private void PictureBox1_Click(object sender, EventArgs e)
{
    //セピア調にする画像
    Bitmap img = new Bitmap(@"C:\test\1.png");
    //セピア調に変換
    Image sepiaImg = CreateGrayscaleImage(img, 1f, 0.8f, 0.6f);
    img.Dispose();
    //PictureBox1に表示
    if (PictureBox1.Image != null)
    {
        PictureBox1.Image.Dispose();
    }
    PictureBox1.Image = sepiaImg;
}

この結果は、以下のようになります。値を色々変えて試してみてください。

セピア調に変換した画像

なおここで紹介したColorMatrixクラスを使用した方法以外の方法も考えられます。これについては、「画像のカラーバランスを補正して表示する」を参考にしてください。

注意:この記事では、基本的な事柄の説明が省略されているかもしれません。初心者の方は、特に以下の点にご注意ください。

  • このサイトで紹介されているコードの多くは、例外処理が省略されています。例外処理については、こちらをご覧ください。
  • イベントハンドラの意味が分からない、C#のコードをそのまま書いても動かないという方は、こちらをご覧ください。
  • コードの先頭に記述されている「Imports ??? がソースファイルの一番上に書かれているものとする」(C#では、「using ???; がソースファイルの一番上に書かれているものとする」)の意味が分からないという方は、こちらをご覧ください。
  • Windows Vista以降でUACが有効になっていると、ファイルへの書き込みに失敗する可能性があります。詳しくは、こちらをご覧ください。
  • .NET Tipsをご利用いただく際は、注意事項をお守りください。