ごった煮

色々な事を書いてます

カメラで撮影した写真の向きの検出方法について

以前カメラで写真撮影をして画像を使う機能を実装する際に, 携帯電話の上下左右を間違えて撮影するなど, 90度反転した画像が投稿された際の処理が なかなかに厄介だと感じたので, メモついでにまとめてみます.

さっそくやってみる

方法としては, 画像のExif情報を読み取り回転情報に応じて処理を加える方法をとります.

ちなみに, 抜き出した情報と回転情報を紐づけると

  1. 通常
  2. 左右反転
  3. 時計回りに180度回転
  4. 上下反転
  5. 時計回りに270度回転, 上下反転
  6. 時計回りに90度回転
  7. 時計回りに90度回転, 上下反転
  8. 時計回りに270度回転

と, 数値で状態が表されます.

Byte型配列を受け取って変換するコードを以下に示します.

private static byte[] LotateImage(byte[] image)
{
    var converter = new ImageConverter();
    var img = (Image)converter.ConvertFrom(image);
    var bmp = new Bitmap(img);
    var props = bmp.PropertyItems;
    for (int i = 0; i < props.Length; i++)
    {
        var p = props[i];
        if (p.Id == 0x0112)
        {
            switch (p.Value[0])
            {
                case 1:
                    break;
                case 3:
                    bmp.RotateFlip(System.Drawing.RotateFlipType.Rotate180FlipNone);
                    break;
                case 6:
                    bmp.RotateFlip(System.Drawing.RotateFlipType.Rotate270FlipNone);
                    break;
                case 8:
                    bmp.RotateFlip(System.Drawing.RotateFlipType.Rotate90FlipNone);
                    break;
            }
        }
    }
    var ms = new MemoryStream();
    bmp.Save(ms,System.Drawing.Imaging.ImageFormat.Jpeg);
    return ms.GetBuffer();
}

今回は, 180度回転している場合にそれを補正する操作を行っています.

画像をbitmapイメージに変換してItemPropertyの中身から, 向きの情報が含まれている部分を抜き出して処理します.

画像の向きが含まれている部分は, Idが0x0112の値の部分なのでその部分を指定します.

このほかの部分を抜き出して処理したい場合は, その都度それぞれ対応したIdのプロパティを抜き出します.

まとめ

このようにすることで携帯電話など向きがどちらだかわからない状況などが想定される場合にこれに類推する実装をしておけば, 基本的には問題なくなると思いますので, ぜひお試しください.

また, Exif情報が残らないような設定にしている場合は使用出来ないので気を付けてください.