69

I've got a JPEG image which was taken on an iphone. On my desktop PC (Windows Photo Viewer, Google Chrome, etc) the orientation is incorrect.

I'm working on an ASP.NET MVC 3 web application where i need to upload photos (currently using plupload).

I've got some server-side code to process images, including reading EXIF data.

I've tried reading the PropertyTagOrientation field in the EXIF meta data (using GDI - Image.PropertyItems), but the field isn't present.

So it's either some specific iphone meta data, or some other meta data.

I've used another tool like Aurigma Photo Uploader, and it reads the meta data correctly and rotates the image. How does it do this?

Does anyone know what other JPEG meta data could contain the information required in order to know that it needs to be rotated, that is used by Aurigma?

Here's the code i'm using to read the EXIF data:

var image = Image.FromStream(fileStream);

foreach (var prop in image.PropertyItems)
{
   if (prop.Id == 112 || prop.Id == 5029)
   {
      // do my rotate code - e.g "RotateFlip"
      // Never get's in here - can't find these properties.
   }
}

Any ideas?

RPM1984
  • 72,246
  • 58
  • 225
  • 350

5 Answers5

149

Here is a snippet addressing the 8 orientation values.

First a few notes:

The EXIF id 0x0112 is for Orientation. This is a helpful EXIF id reference http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/EXIF.html

0x0112 is the hex equivalent of 274. The data type of a PropertyItem.Id is an int, meaning 274 is what is useful here.

Additionally, 5029 likely was supposed to be 0x5029 or 20521 which correlates to ThumbnailOrientation, though is likely not what is desired here.

Orient Image:

Note: img is a System.Drawing.Image or inherits from it, like System.Drawing.Bitmap.

if (Array.IndexOf(img.PropertyIdList, 274) > -1)
{
    var orientation = (int)img.GetPropertyItem(274).Value[0];
    switch (orientation)
    {
        case 1:
            // No rotation required.
            break;
        case 2:
            img.RotateFlip(RotateFlipType.RotateNoneFlipX);
            break;
        case 3:
            img.RotateFlip(RotateFlipType.Rotate180FlipNone);
            break;
        case 4:
            img.RotateFlip(RotateFlipType.Rotate180FlipX);
            break;
        case 5:
            img.RotateFlip(RotateFlipType.Rotate90FlipX);
            break;
        case 6:
            img.RotateFlip(RotateFlipType.Rotate90FlipNone);
            break;
        case 7:
            img.RotateFlip(RotateFlipType.Rotate270FlipX);
            break;
        case 8:
            img.RotateFlip(RotateFlipType.Rotate270FlipNone);
            break;
    }
    // This EXIF data is now invalid and should be removed.
    img.RemovePropertyItem(274);
}
ReenignE
  • 1,751
  • 2
  • 11
  • 5
17

It appears that you forgotten that the orientation id values you looked up are in hex. Where you use 112, you should have used 0x112.

This article explains how Windows ballsed-up orientation handing, and this one seems pretty relevant to what you are doing.

spender
  • 117,338
  • 33
  • 229
  • 351
14

I combined the given answers and comments and came up this:

    MemoryStream stream = new MemoryStream(data);
    Image image = Image.FromStream(stream);

    foreach (var prop in image.PropertyItems) {
        if ((prop.Id == 0x0112 || prop.Id == 5029 || prop.Id == 274)) {
            var value = (int)prop.Value[0];
            if (value == 6) {
                image.RotateFlip(RotateFlipType.Rotate90FlipNone);
                break;
            } else if (value == 8) {
                image.RotateFlip(RotateFlipType.Rotate270FlipNone);
                break;
            } else if (value == 3) {
                image.RotateFlip(RotateFlipType.Rotate180FlipNone);
                break;
            } 
        }
    }
Ron Burgundy
  • 149
  • 1
  • 2
  • 2
    0x112 = 274, they are equal so you can leave one of the two out of your if statement. – Louis Somers Jul 03 '14 at 16:25
  • 2
    I tried this but still facing problem in Mobile browser. In Web browser it is working fine. But in Mobile, the image turns 90 degree right. help? – Shalin Jirawla Jun 15 '16 at 17:47
  • @ShalinJirawla I had your same problem: just added an answer that fixed it for me. – Darkseal Jul 19 '16 at 13:24
  • the answer with more upvotes was flipping my mobile images sometimes when not needed (possibly case 2,4,5,7). This worked better for me! – deebs Mar 10 '20 at 14:15
14

From this post looks like you need to check ID 274

foreach (PropertyItem p in properties) {
      if (p.Id == 274) {
            Orientation = (int)p.Value[0];
         if (Orientation == 6)
            oldImage.RotateFlip(RotateFlipType.Rotate90FlipNone);
         if (Orientation == 8)
            oldImage.RotateFlip(RotateFlipType.Rotate270FlipNone);
      break;
      }
}
Bala R
  • 107,317
  • 23
  • 199
  • 210
  • Hmm, tried that too. It found a property with id `274`, but the orientation value is `1`. So it doesn't do the flip. – RPM1984 Jun 03 '11 at 03:42
  • +1 - although it's not the correct answer, my rotations were wrong - and yours are right. – RPM1984 Jun 03 '11 at 03:59
  • 1
    In addition, "3" is upside-down, per http://sylvana.net/jpegcrop/exif_orientation.html My testing concurs. – DenNukem Jan 12 '13 at 06:55
  • This helped me immensely. You can use this code along with a case for all orientations to properly orient any image. – David C Dec 04 '13 at 23:03
2

Posting here just in case someone has the same issue. I had problems in production reading the orientation using WFP and GDI. The only thing that worked was using: https://github.com/dlemstra/Magick.NET

The code is fairly simple:

var img = new MagickImage(inputStream);
img.AutoOrient();   // Fix orientation
img.Strip();        // remove all EXIF information
img.Write(outputPath);
Diego Jancic
  • 7,280
  • 7
  • 52
  • 80
  • That doesn't fix it for me, pictures taken on Android and iOS are still displayed in landscape while they were both taken in portrait mode. – Mason Nov 13 '20 at 09:36
  • Check how you're uploading the images and make sure the original is being uploaded. If you're processing/compressing the image before uploading maybe you're removing important metadata. That code has worked for me ever since. – Diego Jancic Nov 13 '20 at 13:04