misc.log

日常茶飯事とお仕事と

マルチページTIFF画像ファイルを作る

古いソースを引っ張り出して整理してみました。Visual Studio.NET 2003のVisual Basic.NET(2003)で作った、複数画像をTIFFファイルにまとめるコードの抜粋です。最初に「CreateBaseImage」で1枚目の画像ファイルを作成してから、「AddImage」で2枚目以降を追加していくようになっています。もっと良く作ることは出来ると思いますが、他からの転記や取込&時間が無い中の自作だったという言い訳を添えてご容赦頂きたく(笑)。


最初に、クラス内で参照出来るスコープで、下記のオブジェクトを宣言しておきます。

    Private imageObject As Image = Nothing


次が、CreateBaseImageのコード。1枚目画像を含んだTiffファイル書込みで使うImageCodecInfoの取り出しにループを使っているのは、海外の掲示板であったやりかた。これしかないのかどうか、ちょっと調べたいのですが、実現できていません。

    Private Sub CreateBaseImage(ByVal fileName As String, ByVal targetFileName As String)

        Dim imgStream As FileStream

        Try
            'コーデック情報を探す?(総当たりか!?)
            Dim cdcInfo As ImageCodecInfo
            For Each info As ImageCodecInfo In ImageCodecInfo.GetImageEncoders()
                If info.MimeType = "image/tiff" Then
                    cdcInfo = info
                    Exit For
                End If
            Next

            'とりあえず「マルチTIFF」としてだけ指定、圧縮等はデフォルトのまま
            Dim encParameters = New EncoderParameters(1)
            encParameters.Param(0) = New EncoderParameter(Encoder.SaveFlag, CLng(EncoderValue.MultiFrame))

            '1枚目画像を読み込む
            Dim imageData() As Byte = Nothing
            imgStream = New FileStream(fileName, FileMode.Open, FileAccess.Read)

            'Imageオブジェクトに読み込んでファイルに保存
            imageObject = Image.FromStream(imgStream)
            imageObject.Save(targetFileName, cdcInfo, encParameters)

        Catch ex As Exception
            MessageBox.Show(ex.Message)
            Throw ex

        Finally
            If Not imgStream Is Nothing Then
                imgStream.Close()
            End If

        End Try


次が、2枚目以降の画像を追加する処理。imageObjectはCreateBaseImageと同じモノを使っています。3枚、4枚と画像がある場合は、AddImageをその回数分だけ繰り返せば追加可能です。

    Private Sub AddImage(ByVal fileName As String)

        If imageObject Is Nothing Then
            Throw New ApplicationException("事前にCreateBaseImageを実行しないとダメです。")

        Else
            '既にCreateBaseImageを実行している場合
            Dim imgStream As FileStream
            Dim addedImage As Image

            'マルチTIFFの2枚目以降としてエンコードを指定。圧縮等はデフォルトのまま。
            Dim encParameters = New EncoderParameters(1)
            encParameters.Param(0) = New EncoderParameter(Encoder.SaveFlag, CLng(EncoderValue.FrameDimensionPage))

            Try
                'CreateBaseImageと同じ処理で読み込む
                Dim imageData() As Byte = Nothing
                imgStream = New FileStream(fileName, FileMode.Open, FileAccess.Read)
                addedImage = Image.FromStream(imgStream)

                '"SaveAdd"で保存するとマルチページ
                imageObject.SaveAdd(addedImage, encParameters)

            Catch ex As Exception
                MessageBox.Show(ex.Message)
                Throw ex

            Finally
                If Not imgStream Is Nothing Then
                    imgStream.Close()
                End If
                addedImage.Dispose()
                imageObject.Dispose()

            End Try

        End If

    End Sub


実際には、作成したオブジェクトのDisposeや、複数枚追加処理をAddImageの繰り返しではなく、内部で回数分回すなどの工夫をしなければ無駄が多いと思います。あくまで「やりかた」の確認程度と思っておいてください。2007年に質問を受けて片手間で作成したコードでした。



TIFF画像は、FAXでの画像転送などに使われている画像フォーマットで、コンテナとしての外側に、様々な圧縮方式や形式の画像を複数枚(それぞれ独立した方式で)格納できるというのが特徴です。

TIFFWikipedia
http://ja.wikipedia.org/wiki/Tagged_Image_File_Format
TIFF仕様(Adobeのサイト)
http://partners.adobe.com/public/developer/tiff/index.html

課題

上記のコードで自分が納得していないところ。

  • コーデックのオブジェクト取得方法、もうちょっとなんとかならんか。
  • エンコードパラメータは複数列挙して、圧縮方式や色深度などを指定できるが、今回のサンプルでは指定していない。では、無指定時はどういう設定が使われるのかといった点を把握できていない(少なくとも、無圧縮を明示的に指定するとファイルサイズが凄く大きくなることから、無圧縮ではないことは判っている)。