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

品質を指定してJPEG画像を保存する

画像をファイルに保存する方法は「画像フォーマットを指定して保存する」で説明しましたが、ここではさらに品質を指定して画像を保存する方法を紹介します。

そのためには、イメージエンコーダを指定して画像を保存します。以下に示すSaveImageメソッドは、画像ファイルを指定された品質(Quality)でJPEG形式で保存します。(MSDNの「Encoder.Qualityフィールド」のコードを参考にしています。)品質に1以下の値を指定した時は1を、100以上の値を指定した時は100を指定した時と同じになるようです。

使い方は、例えば画像ファイル"test.bmp"を品質25でJpegに保存する時は、「SaveImage("test.bmp", 25)」のように呼び出します。

VB.NET
コードを隠すコードを選択
''' <summary>
''' 指定された画像ファイルを、品質を指定してJPEGで保存する
''' </summary>
''' <param name="fileName">変換する画像ファイル名</param>
''' <param name="quality">品質</param>
Public Shared Sub SaveImage(fileName As String, quality As Integer)
    '画像ファイルを読み込む
    Dim bmp As New System.Drawing.Bitmap(fileName)

    'EncoderParameterオブジェクトを1つ格納できる
    'EncoderParametersクラスの新しいインスタンスを初期化
    'ここでは品質のみ指定するため1つだけ用意する
    Dim eps As New System.Drawing.Imaging.EncoderParameters(1)
    '品質を指定
    Dim ep As New System.Drawing.Imaging.EncoderParameter( _
        System.Drawing.Imaging.Encoder.Quality, CLng(quality))
    'EncoderParametersにセットする
    eps.Param(0) = ep

    'イメージエンコーダに関する情報を取得する
    Dim ici As System.Drawing.Imaging.ImageCodecInfo = _
        GetEncoderInfo("image/jpeg")

    '新しいファイルの拡張子を取得する
    Dim ext As String = ici.FilenameExtension.Split(";"c)(0)
    ext = System.IO.Path.GetExtension(ext).ToLower()
    '保存するファイル名を決定(拡張子を変える)
    Dim saveName As String = System.IO.Path.ChangeExtension(fileName, ext)

    '保存する
    bmp.Save(saveName, ici, eps)

    bmp.Dispose()
    eps.Dispose()
End Sub

Private Shared Function GetEncoderInfo(mineType As String) _
        As System.Drawing.Imaging.ImageCodecInfo
    'GDI+ に組み込まれたイメージ エンコーダに関する情報をすべて取得
    Dim encs As System.Drawing.Imaging.ImageCodecInfo() = _
        System.Drawing.Imaging.ImageCodecInfo.GetImageEncoders()
    '指定されたMimeTypeを探して見つかれば返す
    Dim enc As System.Drawing.Imaging.ImageCodecInfo
    For Each enc In encs
        If enc.MimeType = mineType Then
            Return enc
        End If
    Next
    Return Nothing
End Function

'ImageFormatで指定されたImageCodecInfoを探して返す
Private Shared Function GetEncoderInfo(f As System.Drawing.Imaging.ImageFormat) _
        As System.Drawing.Imaging.ImageCodecInfo
    Dim encs As System.Drawing.Imaging.ImageCodecInfo() = _
        System.Drawing.Imaging.ImageCodecInfo.GetImageEncoders()
    Dim enc As System.Drawing.Imaging.ImageCodecInfo
    For Each enc In encs
        If enc.FormatID = f.Guid Then
            Return enc
        End If
    Next
    Return Nothing
End Function
C#
コードを隠すコードを選択
/// <summary>
/// 指定された画像ファイルを、品質を指定してJPEGで保存する
/// </summary>
/// <param name="fileName">変換する画像ファイル名</param>
/// <param name="quality">品質</param>
public static void SaveImage(string fileName, int quality)
{
    //画像ファイルを読み込む
    System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(fileName);

    //EncoderParameterオブジェクトを1つ格納できる
    //EncoderParametersクラスの新しいインスタンスを初期化
    //ここでは品質のみ指定するため1つだけ用意する
    System.Drawing.Imaging.EncoderParameters eps =
        new System.Drawing.Imaging.EncoderParameters(1);
    //品質を指定
    System.Drawing.Imaging.EncoderParameter ep =
        new System.Drawing.Imaging.EncoderParameter(
        System.Drawing.Imaging.Encoder.Quality, (long)quality);
    //EncoderParametersにセットする
    eps.Param[0] = ep;

    //イメージエンコーダに関する情報を取得する
    System.Drawing.Imaging.ImageCodecInfo ici = GetEncoderInfo("image/jpeg");

    //新しいファイルの拡張子を取得する
    string ext = ici.FilenameExtension.Split(';')[0];
    ext = System.IO.Path.GetExtension(ext).ToLower();
    //保存するファイル名を決定(拡張子を変える)
    string saveName = System.IO.Path.ChangeExtension(fileName, ext);

    //保存する
    bmp.Save(saveName, ici, eps);

    bmp.Dispose();
    eps.Dispose();
}

//MimeTypeで指定されたImageCodecInfoを探して返す
private static System.Drawing.Imaging.ImageCodecInfo
    GetEncoderInfo(string mineType)
{
    //GDI+ に組み込まれたイメージ エンコーダに関する情報をすべて取得
    System.Drawing.Imaging.ImageCodecInfo[] encs =
        System.Drawing.Imaging.ImageCodecInfo.GetImageEncoders();
    //指定されたMimeTypeを探して見つかれば返す
    foreach (System.Drawing.Imaging.ImageCodecInfo enc in encs)
    {
        if (enc.MimeType == mineType)
        {
            return enc;
        }
    }
    return null;
}

//ImageFormatで指定されたImageCodecInfoを探して返す
private static System.Drawing.Imaging.ImageCodecInfo
    GetEncoderInfo(System.Drawing.Imaging.ImageFormat f)
{
    System.Drawing.Imaging.ImageCodecInfo[] encs =
        System.Drawing.Imaging.ImageCodecInfo.GetImageEncoders();
    foreach (System.Drawing.Imaging.ImageCodecInfo enc in encs)
    {
        if (enc.FormatID == f.Guid)
        {
            return enc;
        }
    }
    return null;
}

上記のコードの「Encoder.Quality」を「Encoder.ColorDepth」に変えることで色深度を、「Encoder.Transformation」に変えることで回転や反転を、「Encoder.LuminanceTable」に変えることで輝度を、「Encoder.Compression」に変えることで圧縮方法を変更することもできます。

  • 履歴:
  • 2010/11/12 SaveImageメソッドでbmpをDisposeしていなかったのを修正。
  • 2013/7/5 qualityをlongに明示的にキャストするように変更したなど。

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

  • このサイトで紹介されているコードの多くは、例外処理が省略されています。例外処理については、こちらをご覧ください。
  • .NET Tipsをご利用いただく際は、注意事項をお守りください。