LoginSignup
3
8

More than 5 years have passed since last update.

C# WPF Exifの回転情報を取得して画像を表示する

Last updated at Posted at 2018-05-02

はじめに

WPF で画像ビューワを作っていて、タイトルの通りのところでつまったので、まとめておきます。

画像ファイルを読み取って Image コントロールに表示する。

Image という名前の Image コントロールが Form に配置されていて、 path 変数に画像のファイルパスが入っている状態だとして

  Image.Source =  new BitmapImage(new Uri(path));

これで表示することができます。簡単です。

ですが、罠がありまして、ファイル閲覧中はファイル削除できないとか、そういうロックされる動作になります。

画像ビューアとして使い勝手悪いので、改善します。

画像ファイルのロックを解除する。

ここに書いてあるとおりにやればうまくいきます。

ファイルロックのかからない画像表示方法
http://neareal.net/index.php?Programming%2F.NetFramework%2FWPF%2FWriteableBitmap%2FLoadReleaseableBitmapImage

Exif の回転情報を読み取る

英語ですがこちらに載っています。

JPEG "Orientation" from EXIF for automatic rotation
https://social.msdn.microsoft.com/Forums/en-US/f2e4f23c-f6fd-4474-b47d-b4280f094c8f/jpeg-orientation-from-exif-for-automatic-rotation?forum=wpf

10サイトくらい調べましたが、正確に書かれていて動作するのは、ここの情報くらいです。

画像に回転や左右上下反転の加工をする

方法 : BitmapImage に変換を適用する | Microsoft Docs
https://docs.microsoft.com/ja-jp/dotnet/framework/wpf/graphics-multimedia/how-to-apply-a-transform-to-a-bitmapimage

このあたりを参考にしました。

ソース

全体的に、再利用しやすいようにライブラリとして、ラッピングしました。


        //----------------------------------------
        //BitmapSorce
        //----------------------------------------

        //単純なImageコントロールへの画像のセット
        BitmapSource GetImageSourceLock(string path,
            Rotation rotation = Rotation.Rotate0) {
            var bmpImage = new BitmapImage(new Uri(path));
            bmpImage.Rotation = rotation;
            return bmpImage;
        }

        //画像ファイルロックをしないコントロールへの画像のセット
        BitmapSource GetImageSource(string path,
            Rotation rotation = Rotation.Rotate0) {
            var bmpImage = new BitmapImage();
            FileStream stream = File.OpenRead(path);
            bmpImage.BeginInit();
            bmpImage.CacheOption = BitmapCacheOption.OnLoad;
            bmpImage.StreamSource = stream;
            bmpImage.Rotation = rotation;
            bmpImage.EndInit();
            stream.Close();
            return bmpImage;
        }

        //画像ファイルロックをしないコントロールへの画像のセット
        //Exif情報を読み取って自動で回転や左右上下反転を行う
        BitmapSource GetImageSourceAutoExifOrientate(string path) {
            var bmpImage = new BitmapImage();
            FileStream stream = File.OpenRead(path);
            bmpImage.BeginInit();
            bmpImage.CacheOption = BitmapCacheOption.OnLoad;
            bmpImage.StreamSource = stream;

            var metaData = (BitmapFrame.Create(stream).Metadata) as BitmapMetadata;

            stream.Position = 0;
            bmpImage.EndInit();
            stream.Close();

            string query = "/app1/ifd/exif:{uint=274}";
            if (!metaData.ContainsQuery(query)) {
                return bmpImage;
            }

            switch (Convert.ToUInt32(metaData.GetQuery(query))) {
                case 1:
                    return bmpImage;
                case 3:
                    return TransformBitmap(
                        bmpImage,
                        new RotateTransform(180));
                case 6:
                    return TransformBitmap(
                        bmpImage,
                        new RotateTransform(90));
                case 8:
                    return TransformBitmap(
                        bmpImage,
                        new RotateTransform(270));
                case 2:
                    return TransformBitmap(
                        bmpImage,
                        new ScaleTransform(-1, 1, 0, 0));
                case 4:
                    return TransformBitmap(
                        bmpImage,
                        new ScaleTransform(1, -1, 0, 0));
                case 5:
                    return TransformBitmap(
                        TransformBitmap(
                            bmpImage,
                            new RotateTransform(90)
                        ),
                        new ScaleTransform(-1, 1, 0, 0));
                case 7:
                    return TransformBitmap(
                        TransformBitmap(
                            bmpImage,
                            new RotateTransform(270)
                        ),
                        new ScaleTransform(-1, 1, 0, 0));
            }
            return bmpImage;
        }

        BitmapSource TransformBitmap(BitmapSource source, Transform transform) {
            var result = new TransformedBitmap();
            result.BeginInit();
            result.Source = source;
            result.Transform = transform;
            result.EndInit();
            return result;
        }

       void ShowImage(string path) {
            if (File.Exists(path)) {
                Image.Source = GetImageSourceAutoExifOrientate(path);
            } else {
                Image.Source = null;
            }
       }

ShowImage が画面表示する部分です。次のようになっています。

  Image.Source = GetImageSourceAutoExifOrientate(path);

ここを、下記のようにしても動作させることができます。

  Image.Source = GetImageSourceLock(path);
  Image.Source = GetImageSource(path);

もちろん、Exif 情報は読み取りません。外部から回転方向を指定できますが、あんまり意味がないかもしれません。実装上、作りやすかったからつけただけの機能です。

3
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
8