画像フォーマットとエンコーダパラメータ

注意:
この文書は以前「.NETでいきまっしょい!」で公開していたものですが、公開以降メンテナンスされていません。 今や古い情報となった内容が記載されている場合があるのでご注意ください。

0.はじめに


 この文章では、ビットマップを始めJPEG・GIFなどの様々なフォーマットの画像を用いてサンプルプログラムを組んでいますが、決して画像フォーマットについて検証するものではありません。 従って、各々の画像フォーマットについて詳しく説明することはしません。 必要な場合は適宜調べるなどしてください。

1.様々なフォーマットで画像を保存する


 Bitmapクラスを用いることでビットマップ・JPEG・GIF・PNGなど様々なフォーマットの画像を読み込み操作することができます。 さらに、BitmapクラスやGraphicsコンテナを用いて描画処理などを施したイメージをファイルに保存することもできます。 このとき、読み込めるフォーマット同様に保存するフォーマットを選択することができます。
 次のサンプルはファイルからイメージを読み込んでBitmapオブジェクトを作成し、それを様々なフォーマットで保存するものです。 この例ではわかりやすさのために名前空間のインポートはしていません。
様々なフォーマットで画像を保存する
001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
Module ImageFormatAndCodec

    ' アプリケーションのエントリーポイント
    Sub Main()

        Dim imageSource As System.Drawing.Image

        ' ファイルからBitmapオブジェクトを作成
        imageSource = System.Drawing.Bitmap.FromFile("E:\source.bmp")

        ' BitmapオブジェクトをGIFで保存
        imageSource.Save("E:\dest.gif", System.Drawing.Imaging.ImageFormat.Gif)

        ' BitmapオブジェクトをPNGで保存
        imageSource.Save("E:\dest.png", System.Drawing.Imaging.ImageFormat.Png)

        ' BitmapオブジェクトをJPEGで保存
        imageSource.Save("E:\dest.jpg", System.Drawing.Imaging.ImageFormat.Jpeg)

        ' Bitmapオブジェクトを解放
        imageSource.Dispose()

    End Sub

End Module

source.bmp (24 Bits, 240x240 Pixel, 168kB)

出力例
dest.gif (16.9kB) dest.png (4.67kB) dest.jpg (5.49kB)

 実際に保存を行うためのメソッドがSave()メソッドです。 第一引数に出力するファイル名、第二引数に出力する画像のフォーマットを指定します。 画像フォーマットにはここで使用したもの以外にもいくつかあります。 また、第二引数を指定しない場合、つまり画像フォーマットを指定しないで保存した場合はビットマップで保存されるようです。 このように、Bitmapオブジェクトのイメージを様々なフォーマットで保存することができます。

2.品質パラメータを指定した出力


 画像フォーマットを直接指定してイメージを出力することができるのは前項で説明したとおりですが、色深度や輝度、さらにJPEGなどでは品質(画質)を設定して出力したいという場合があります。 このような場合には前項のような単純なコーディングでは実現できませんが、ある程度の量のコードを記述するだけで様々なパラメータを指定してイメージを出力することができます。
 次の例ではイメージをファイルに出力する際に品質パラメータを指定してJPEGとして保存しています。 ソースコードの詳しい解説は後ほどするので、まずは次のコードを見てください。
品質パラメータを指定した出力
001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
Option Strict On

Module ImageFormatAndCodec

    ' アプリケーションのエントリーポイント
    Sub Main()

        Dim encoderInfo As System.Drawing.Imaging.ImageCodecInfo

        ' JPEG用のImageCodecInfoオブジェクトを取得
        encoderInfo = GetEncoderInfo("image/jpeg")

        ' ImageCodecInfoオブジェクトが取得できない場合は中止
        If encoderInfo Is Nothing Then Return


        ' エンコーダパラメータ
        Dim encoderParams As New System.Drawing.Imaging.EncoderParameters()

        ' 品質を指定するパラメータ (品質25)
        encoderParams.Param(0) = New System.Drawing.Imaging.EncoderParameter(System.Drawing.Imaging.Encoder.Quality, 25)


        ' 元のイメージ
        Dim sourceImage As System.Drawing.Image

        ' ファイルからBitmapオブジェクトを作成
        sourceImage = System.Drawing.Bitmap.FromFile("E:\source.bmp")


        ' ImageCodecInfoオブジェクトおよびエンコーダパラメータを指定して出力
        sourceImage.Save("E:\dest.jpg", encoderInfo, encoderParams)

        ' イメージを解放
        sourceImage.Dispose()

    End Sub

    ' 指定された MIME と一致するイメージエンコーダを取得する
    Function GetEncoderInfo(ByVal mimeType As String) As System.Drawing.Imaging.ImageCodecInfo

        Dim encoderInfoes() As System.Drawing.Imaging.ImageCodecInfo
        Dim encoderInfo As System.Drawing.Imaging.ImageCodecInfo

        ' イメージエンコーダ一覧を取得
        encoderInfoes = System.Drawing.Imaging.ImageCodecInfo.GetImageEncoders()

        ' 一覧から指定された MIME と一致するものを探す
        For Each encoderInfo In encoderInfoes

            ' MIME が一致するか
            If encoderInfo.MimeType = mimeType Then Return encoderInfo

        Next

        ' 見つからない場合
        Return Nothing

    End Function

End Module

 まずはGetEncoderInfo()メソッドの動作から説明します。 このメソッドはMIMEからそれと一致するイメージエンコーダを取得するための関数です。 MIME とは Multipurpose Internet Mail Extension の略で、簡単に言えばファイルの拡張子と同じようなものでそのファイルの種類を特定するために用いるものです。 MSDNによると、この MIME は「application/type」という形式になっていて、applicationはアプリケーションまたはアプリケーションのクラスを表し、typeは一意のMIMEの種類を表します。 「ジャンル/名称」という風に考えても差し支えないと思います。 そして、このメソッドではGetImageEncoders()メソッドによって得られたイメージエンコーダの配列から、引数として受け取ったMIMEと同じものを持つイメージエンコーダを見つけだし、返します。
 次に、Main()メソッドの動作を説明します。 Main()メソッドではまず先ほどのGetEncoderInfo()メソッドを用いてJPEGのイメージエンコーダを取得します。 JPEGのMIMEは "image/jpeg" です。 イメージエンコーダが取得できたら、引き続きエンコーダパラメータの設定を行います。 18行目ではEncoderParametersのインスタンスを作成しています。 これはEncoderParameterのインスタンスを複数格納するためのクラスで、コンストラクタになにも指定しないと、1つだけEncoderParameterを格納することができるEncoderParametersを作成することができます。 また逆に、数値を指定した場合はその分だけEncoderParameterを格納する事ができるインスタンスが生成されます。
 その次の21行目ではEncoderParameterクラスのインスタンスを作成し、先ほどのEncoderParametersクラスのインスタンスのインデックス0に格納します。 このコンストラクタの一つ目の引数にはEncoderクラスのオブジェクトを指定します。 このEncoderクラスはイメージエンコーダに対して指定するパラメータの種類を表します。 この例で使用しているEncoder.QualityはEncoderクラスの静的フィールドで品質パラメータを表します。 二つ目の引数に指定する値は一つ目の引数で指定したパラメータの実際の値となります。 その値には様々な指定方法がありますが、品質の場合は0から100までの整数値を指定します。
 この時点でイメージエンコーダとエンコーダパラメータの二者の用意ができました。 後は実際にこれを使用するだけです。 画像フォーマットを指定して保存したとき同様、既存のイメージを保存する際にこれらのインスタンスを使用して保存を行います。 それが32行目に記述されている部分で、Save()メソッドに対して2つ目の引数にイメージエンコーダ、3つ目の引数にエンコーダパラメータを指定します。 こうして出力されたファイルが次の画像です。 元の画像は先ほどのものと同じものを使用しています。
出力例
dest.jpg (3.27kB)

3.色深度パラメータを指定した出力


 TIFFフォーマットで画像を出力する場合、色深度パラメータを指定することができます。 TIFFを使用した場合、色深度は1, 4, 8, 24, 32のいずれかの値を指定することができるはずなのですが、実験した環境ではなぜか24ビット以外での出力ができませんでした。 次にそのコードを記述しますが、そのほとんどは先ほどのものと同じです。
色深度パラメータを指定した出力
001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
Option Strict On

Module ImageFormatAndCodec

    ' アプリケーションのエントリーポイント
    Sub Main()

        Dim encoderInfo As System.Drawing.Imaging.ImageCodecInfo

        ' TIFF用のImageCodecInfoオブジェクトを取得
        encoderInfo = GetEncoderInfo("image/tiff")

        ' ImageCodecInfoオブジェクトが取得できない場合は中止
        If encoderInfo Is Nothing Then Return


        ' エンコーダパラメータ
        Dim encoderParams As New System.Drawing.Imaging.EncoderParameters()

        ' 色深度パラメータ
        encoderParams.Param(0) = New System.Drawing.Imaging.EncoderParameter(System.Drawing.Imaging.Encoder.ColorDepth, 24L)

        ' 元のイメージ
        Dim sourceImage As System.Drawing.Image

        ' ファイルからBitmapオブジェクトを作成
        sourceImage = System.Drawing.Bitmap.FromFile("E:\source.bmp")


        ' ImageCodecInfoオブジェクトおよびエンコーダパラメータを指定して出力
        sourceImage.Save("E:\dest.tif", encoderInfo, encoderParams)

        ' イメージを解放
        sourceImage.Dispose()

    End Sub


    ' 途中略


End Module

出力されたファイル dest.tif (32.4kB)
イメージビューアなどを使用しないと見られない場合があります

 このほかにも指定できるパラメータはいくつかありますが、そのほとんどで例外エラーが発生するなどして使用できませんでした。 原因はいまいち分かりませんが、パラメータの指定方法に原因があると考えられます。 この事項に関する詳しい情報を知っている方はぜひ教えてください。