SDカードに過去の写真が結構入っている*1のですが、RAWで撮ってるので結構場所をとります。原本をPCに転送したらJPEGに置き換えたい。
と思って適当にJPEGに変換して入れてみると、個別に表示することはできても一覧でサムネイルが表示されない。
いろいろ探った結果、サムネイルの大きさがDCF規格の160x120*2と違う縦横比だったのが原因だったようです。ちなみに比率が正しければもっと大きくても表示できました*3。
プログラム書かない方へ:F6 Exifのインポート機能なども使えます(手間はかかりますが)。他にもサムネ再生成してくれるソフトはありそうですが、適当なものだと縦横比修正してくれないかも。
で、サムネイル再生成する何かをいつものようにC#で書こうとしたものの、System.DrawingやWPFでメタデータ付きのJPEGを書き出すとビッグエンディアンになってしまうようなのです。これではサムネイルだけでなく全く表示できなくなってしまいました。
そこで今回はExiv2のコマンドラインツールで埋め込むことにしました。exiv2 -it hoge.jpg
とすると、hoge-thumb.jpg を hoge.jpg に埋め込んでくれます。
またRAWからのJPEG化・サムネイル生成はPhotoshopをCOM経由で叩いてみました。
参考 Automating Photoshop With C# // Josh Wright
ただうちの環境ではタイプライブラリの場所が正しく登録されていなかったようで、手動で C:\Program Files (x86)\Adobe\Adobe Photoshop CS5\Plug-ins\Extensions\ScriptingSupport.8li
からtlbimpしました。
// using Photoshop; var src_dir = @"G:\Src\"; var target_dir = @"G:\Thumb\"; var exiv2_exe = @"R:\exiv2.exe"; var thumb_width = 320; var app = new Application(); //app.Visible = false; app.BackgroundColor = new SolidColor { RGB = new RGBColor { HexValue = "000000" } }; // 後々の座標・長さ指定はこの単位が適用される var ruler_old = app.Preferences.RulerUnits; app.Preferences.RulerUnits = PsUnits.psPixels; var export_opts = new ExportOptionsSaveForWeb { Format = PsSaveDocumentType.psJPEGSave, Blur = 0.2, Quality = 50, Optimized = true }; var save_opts = new JPEGSaveOptions { Quality = 8, FormatOptions = PsFormatOptionsType.psOptimizedBaseline }; foreach (var src in Directory.EnumerateFiles(src_dir, "*.cr2")) { var basename = Path.GetFileNameWithoutExtension(src); var img_path = $"{target_dir}{basename}.jpg"; var thumb_path = $"{target_dir}{basename}-thumb.jpg"; if (File.Exists(img_path)) File.Delete(img_path); if (File.Exists(thumb_path)) File.Delete(thumb_path); // サムネイル生成で使うExportはファイル名を指定できないので、後で移動する。 // ので、先にサムネ生成してから縮小前までUndoしてフルサイズ画像を書き出す。 var doc = app.Open(src); var state = doc.ActiveHistoryState; if (doc.Width > doc.Height) { doc.ResizeImage(Width: thumb_width, ResampleMethod: PsResampleMethod.psBicubicSharper); } else { // doc.ResizeImage(Height: thumb_width * 3 / 4, ResampleMethod: PsResampleMethod.psBicubicSharper); // サムネはこれでいいが、フルサイズ画像も(横長のまま)Exifで回転指定しないといけない・・・ throw new NotSupportedException("縦長画像は今後の課題。"); } doc.ResizeCanvas(thumb_width, thumb_width * 3 / 4, PsAnchorPosition.psMiddleCenter); doc.Export(target_dir, PsExportType.psSaveForWeb, export_opts); File.Move(img_path, thumb_path); doc.ActiveHistoryState = state; doc.SaveAs(img_path, save_opts); doc.Close(); // exiv2 -it foo.jpg // => foo.jpg に foo-thumb.jpg をサムネイル画像として埋め込む Process.Start(new ProcessStartInfo { FileName = exiv2_exe, Arguments = $"-it \"{img_path}\"", UseShellExecute = false, CreateNoWindow = true }).WaitForExit(); File.Delete(thumb_path); } app.Preferences.RulerUnits = ruler_old; //app.Quit();
ここまで書いてから、WICなんだからRAW形式もBitmapImageとかで読み込めて、Photoshopいらないのではと気付いた。面倒くささはいい勝負のような気がするけど…。