Problem reading JPEG Metadata (Orientation)
Asked Answered
C

6

71

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?

Cannonball answered 3/6, 2011 at 1:15 Comment(0)
N
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.

Nauseous answered 3/6, 2011 at 1:48 Comment(2)
Iphone5S is not work, photo toked with no EXIF data, any solution?Arathorn
@Arathorn if you save it as png its will not save the EXIF save it as jpgGuillen
S
155

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);
}
Sulfa answered 1/5, 2014 at 1:23 Comment(3)
Much more complete answer: full description of orientation cases, plus note to remove the EXIF data (in case it's processed later)Interrex
very helpful. this should be the accepted answer IMHO.Lexy
Here one can find some oriented image examples for testing: github.com/recurser/exif-orientation-examplesWilhelmstrasse
N
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.

Nauseous answered 3/6, 2011 at 1:48 Comment(2)
Iphone5S is not work, photo toked with no EXIF data, any solution?Arathorn
@Arathorn if you save it as png its will not save the EXIF save it as jpgGuillen
F
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;
      }
}
Forklift answered 3/6, 2011 at 1:42 Comment(4)
Hmm, tried that too. It found a property with id 274, but the orientation value is 1. So it doesn't do the flip.Cannonball
+1 - although it's not the correct answer, my rotations were wrong - and yours are right.Cannonball
In addition, "3" is upside-down, per sylvana.net/jpegcrop/exif_orientation.html My testing concurs.Assam
This helped me immensely. You can use this code along with a case for all orientations to properly orient any image.Explanatory
C
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;
            } 
        }
    }
Claytor answered 27/1, 2014 at 10:33 Comment(4)
0x112 = 274, they are equal so you can leave one of the two out of your if statement.Kadi
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?Pandolfi
@ShalinJirawla I had your same problem: just added an answer that fixed it for me.Garrido
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!Turin
K
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);
Krucik answered 30/11, 2018 at 21:16 Comment(2)
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.Buddle
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.Krucik
C
0

I've taken ReenignE answer, made it an extension, but in stead of removing property 274, I set it to 1 (= horizontal (normal))

public static Image AutoOrientation(this Image image)
{
    // 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.
    const int EXIF_Orientation = 0x0112; //274

    if (Array.IndexOf(image.PropertyIdList, EXIF_Orientation) > -1)
    {
        var orientationProperty = image.GetPropertyItem(EXIF_Orientation);
        var orientation = (int)orientationProperty.Value[0];
        switch (orientation)
        {
            case 1:
                // No rotation required.
                break;
            case 2:
                image.RotateFlip(RotateFlipType.RotateNoneFlipX);
                break;
            case 3:
                image.RotateFlip(RotateFlipType.Rotate180FlipNone);
                break;
            case 4:
                image.RotateFlip(RotateFlipType.Rotate180FlipX);
                break;
            case 5:
                image.RotateFlip(RotateFlipType.Rotate90FlipX);
                break;
            case 6:
                image.RotateFlip(RotateFlipType.Rotate90FlipNone);
                break;
            case 7:
                image.RotateFlip(RotateFlipType.Rotate270FlipX);
                break;
            case 8:
                image.RotateFlip(RotateFlipType.Rotate270FlipNone);
                break;
        }
        orientationProperty.Value[0] = 1; //set it to 1 = Horizontal (normal)
        image.SetPropertyItem(orientationProperty);
    }

    return image;
}
Camphene answered 2/4, 2024 at 17:33 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.