古いソースを引っ張り出して整理してみました。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での画像転送などに使われている画像フォーマットで、コンテナとしての外側に、様々な圧縮方式や形式の画像を複数枚(それぞれ独立した方式で)格納できるというのが特徴です。
- TIFF(Wikipedia)
- http://ja.wikipedia.org/wiki/Tagged_Image_File_Format
- TIFF仕様(Adobeのサイト)
- http://partners.adobe.com/public/developer/tiff/index.html
課題
上記のコードで自分が納得していないところ。
- コーデックのオブジェクト取得方法、もうちょっとなんとかならんか。
- エンコードパラメータは複数列挙して、圧縮方式や色深度などを指定できるが、今回のサンプルでは指定していない。では、無指定時はどういう設定が使われるのかといった点を把握できていない(少なくとも、無圧縮を明示的に指定するとファイルサイズが凄く大きくなることから、無圧縮ではないことは判っている)。
