ホーム ] 実行時間計測ラブラリ ] EXIF情報ライブラリ ] 文字式演算 ] クイックソートライブラリ ] 多倍長演算ライブラリ ] 多倍長演算ライブラリU ] 画像処理ライブラリ ]

上へ
実行例
EXIF情報の獲得
EXIF情報の保存

技術解説

EXIF情報の保存

最終更新日:2007/04/26  全面改訂

●概要

 EXIF(JPEG)画像を保存する方法と、EXIF情報も含めて保存する方法を。また、EXIF情報を編集する方法も紹介する。

 EXIF情報の保存は、筆者にとっては長い間不明であったが最近たどり着いた。勿論、バイナリ処理なしで、すべて、標準組込みクラスによるVBコードで解決した。しかし、例によって、紹介する方法が正しいと言う保証はない。

●保存の原理/方法

○一般の画像保存

 Imageクラスのメソッドで保存できる。

 Image.Save("ファイルパス")

である。この場合は、BMP形式となり、当然、EXIF情報は一切なくなる。

○JPG画像の保存

 メソッドに、画像形式を指定するオーバーロードがある。

 Image.Save("ファイルパス", ImgType)

ImgType は関係深いものは以下がある。

Imaging.ImageFormat.Bmp
Imaging.ImageFormat.Exif
Imaging.ImageFormat.Jpeg
Imaging.ImageFormat.Gif

Exif と、Jpeg が最もJPGに関係する。しかし、Exif で保存すると、どうも不正なファイルになってしまうようだ。Jpeg が正しくファイルでき、EXIF情報も保存される。しかし、この方法でJPGの品質は指定できない。調べてみると、品質としては 75 程度となるようである。(品質は、0〜100 で、100が最高)品質が常に75前後で良いならこの方法が最も簡便。

○品質を指定して保存

 これは、エンコーダ、エンコードパラメータを指定する方法で、

 Image.Save("ファイルパス", enc, enp )

となる。実際には、Jpeg を指定するので、以下のようにする。

Dim QV As Integer = 値     '品質を指定
Dim enp As EncoderParameters = New EncoderParameters(1)
enp.Param(0) = New Imaging.EncoderParameter(Imaging.Encoder.Quality, QV)
bmp.Save("ファイルパス", GetEncoderInfo("Image/jpeg"), enp)

エンコーダはシステムに登録されている中からMIME型を指定して以下のように検索する。

Friend Function GetEncoderInfo(ByVal m As String) As ImageCodecInfo
   Dim encs As ImageCodecInfo()
   encs = ImageCodecInfo.GetImageEncoders()
   Dim j As Integer
   For j = 0 To encs.Length - 1
      If encs(j).MimeType = m Then
         Return encs(j)
      End If
   Next
   Return Nothing
End Function

注意:当たり前であるが、元の画像がJpegなど非可逆圧縮画像であったなら、保存(コピーではない)すれば、たとえ、品質を100と指定しても必ずその元画像品質より低下する(ファイルサイズが無駄に大きくなるだけ)。

○EXIF情報の保存状態

 下表のようになる。○が保存される。

 

PropertyItem関連

保存方法

アクセスしない アクセスした(参照/設定)
Imaging.ImageFormat.Jpeg
エンコーダ指定 ×

 エンコーダ指定では、Imgage のPropertyItem を一度でもアクセスしたかどうかで状態が変わる。

 また、下図のように、元のファイルがインテル形式、モトローラ形式であっても、インスタンス(メモリ上のEXIF情報)は、すべてインテル形式になる。保存した場合も、インテル形式として保存される。Tiffヘッダも当然、"II"になる。

●EXIF情報編集の原理/方法

○PropertyItemのインスタンスを得る

 PropertyItem は、パブリックなコンストラクタ(New)がないので、任意にインスタンスを生成できない(MSのMSDNによる)。従って、既存のあるPropertyItemのインスタンスを得て、それを半ば強引に使用する。インスタンスを得てしまえば、自由に、Id やType、値を編集できる。

例えば、以下のようにする。

Dim bmp As Bitmap = Bitmap.FromFile("ファイルパス")
Dim pi As PropertyItem = bmp.GetPropertyItem(37510)    '37510 はユーザコメント

pi を編集対象とする。

→現実的には、編集対象となるTagは限られている。タイトル、撮影者、著作権、ユーザコメントなどとなる。これ以外は編集する意味がない。

○更新と追加

 強引に得たインスタンスのIdをそのままで、値などを編集すれば更新となり、Id を、現在ないもの(但し、EXIF仕様にはあるTag)にすれば、新しいアイテムとして追加される

・更新例

pi.Len = XX
pi.Value = NewBytes

bmp.SetPropertyItem(pi)

・追加例

pi.Id = XX
pi.Len = YY
pi.Type = TT
pi.Value = NewBytes

bmp.SetPropertyItem(pi)     'この場合は自動的に追加処理される

注意:この例では、Bitmap.FromFileなので画像の上書き保存はできない。