うならぼ

申し訳程度のアフィリエイトとか広告とか解析とかは/aboutを参照

Exifのサムネイルの縦横比を修正して、デジカメできちんと表示されるように

SDカードに過去の写真が結構入っている*1のですが、RAWで撮ってるので結構場所をとります。原本をPCに転送したらJPEGに置き換えたい。

と思って適当にJPEGに変換して入れてみると、個別に表示することはできても一覧でサムネイルが表示されない。

f:id:unarist:20160811224057p:plain

いろいろ探った結果、サムネイルの大きさが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いらないのではと気付いた。面倒くささはいい勝負のような気がするけど…。

*1:撮った写真を人に見せられるようにってことなんですが、本当は画面大きくて操作しやすいタブレットに移行したい。

*2:CIPAのサイトからダウンロードできるDC-009-2010の§4.4.6.3参照

*3:うちのKiss X4でも液晶ディスプレイが横1400pxぐらいはあるようなので、3枚横に並べるとしても一枚160pxは余裕すぎる。ファイルサイズや表示速度に影響しそうではあるけど。

緊急地震速報の高度利用者向けと一般向けと

昨日の緊急地震速報の誤報騒ぎの話です。まああまりにでかすぎて、冗談でなければ色々諦めそうな感じでしたが。

あれはなんだったのか

気象庁のPDFによると、

平成 28 年 8 月 1 日 17 時 09 分頃に、千葉県富津市付近を中心に最大震度7を予測した緊急地震速報(予報)を発表しましたが、その後周辺の観測点で揺れが観測されなかったため、15 秒後にキャンセル報を発表しました。この原因は、緊急地震速報に活用している防災科学技術研究所の富津観測点のデータに大きなノイズが記録されたためです。 http://www.data.jma.go.jp/svd/eew/data/nc/oshirase/20160801.pdf

とあります。おおかた雷でも落ちたんじゃないかという話です。

テレビや携帯には来なかったよ?

緊急地震速報には警報と予報の二種類があり、警報は地震波が2点以上の地震観測点で観測され、最大震度が5弱以上と予想された場合にしか発報されません。今回はひとつの観測点でしか観測されなかったために、警報に至ることなくキャンセルされました。

2点以上の地震観測点で地震波が観測された場合とした理由は、地震計のすぐ近くへの落雷等による誤報を避けるためです。最大震度5弱以上が予想された場合とした理由は、震度5弱以上になると顕著な被害が生じ始めるため、事前に身構える必要があるためです。 気象庁|緊急地震速報|緊急地震速報(警報)及び(予報)について

不特定多数向けに伝達する警報は、誤報でなくとも、軽微なものに一々警報出してたら余計な心配や混乱を招きかねないので、よほどのことがないと警報を出さないようになっているわけです。オオカミ少年的なことにもなりそうですし。

でもネットやアプリで見たよ?

それは前述の予報が元になっています。誤報の可能性があっても安全側に倒して一刻も早く車両のブレーキをかけておきたいとか、予備系統を起動しておきたいとか、あるいは建物の耐震性を考慮して判断したいとか、そういう用途なので「高度利用者向け」とも呼ばれます。

これを元に利用者や客にアナウンスをしてもいいんですが、予報の特性を十分に理解していない相手に対しては警報と同程度の基準・内容にすることが推奨されています。

緊急地震速報(予報)」を用いた地震動予報業務許可事業者の手法によるポイント予報の伝達に関しては、個別契約等を通じて事前に利用者が緊急地震速報(予報)の特性や限界等を十分理解している場合以外や、集客施設等において館内放送等する場合は、提供に伴う混乱の防止のため、その情報については「緊急地震速報(警報)」の発表をもって伝達していただくか、緊急地震速報(警報)と同じような内容の範囲内で伝達していただくことが望ましいと考えていますのでご理解とご協力をお願いします。 気象庁|緊急地震速報|緊急地震速報(予報)の伝達に係るお願い

専用の受信装置を設置したり、同様に専用のアプリを導入した場合は「特性や限界等を十分理解している」という前提のような気はしますが、無料のスマホアプリとかは微妙なところですね。とあるアプリでレビュー欄が荒れているのも、つまりはこの辺が伝わっていないってことで。キャンセルの通知もなしに一覧から消して、アプリの説明文で釈明してるだけなのもあれと言えばあれですが。