37

having problem in getting image orientation with below code

    string fileName = @"D:\...\...\01012015004435.jpeg";

    int rotate = 0;
    using (var image = System.Drawing.Image.FromFile(fileName))
    {
        foreach (var prop in image.PropertyItems)
        {
            if (prop.Id == 0x112)
            {
                if (prop.Value[0] == 6)
                    rotate = 90;
                if (prop.Value[0] == 8)
                    rotate = -90;
                if (prop.Value[0] == 3)
                    rotate = 180;
                prop.Value[0] = 1;
            }
        }
    }

and after get proper orientation i used to rotate image like

private static RotateFlipType OrientationToFlipType(string orientation)
{
    switch (int.Parse(orientation))
    {
        case 1:
            return RotateFlipType.RotateNoneFlipNone;
            break;
        case 2:
            return RotateFlipType.RotateNoneFlipX;
            break;
        case 3:
            return RotateFlipType.Rotate180FlipNone;
            break;
        case 4:
            return RotateFlipType.Rotate180FlipX;
            break;
        case 5:
            return RotateFlipType.Rotate90FlipX;
            break;
        case 6:
            return RotateFlipType.Rotate90FlipNone;
            break;
        case 7:
            return RotateFlipType.Rotate270FlipX;
            break;
        case 8:
            return RotateFlipType.Rotate270FlipNone;
            break;
        default:
            return RotateFlipType.RotateNoneFlipNone;
    }
}

but problem is in first code

prop.Id i always get [20625]

prop.Id == 20625

so not satisfy the condition every time please let me know if any problem or other option

thanks

Soner Gönül
  • 97,193
  • 102
  • 206
  • 364
Jimmy Darji
  • 371
  • 1
  • 3
  • 6
  • Do the images you are viewing specify their orientation? I'm not sure that this is a property that is set by default (i.e what could be the default orientation of your gravatar?) – Sayse Jan 08 '15 at 07:36
  • 1
    Rather than inspecting every image `PropertyItem`, you should simply query for the one you want, e.g. `image.GetPropertyItem(0x112);`. If the rotation property isn't present, it will throw an exception (which you can catch and handle). Not all image files will have a rotation property. Note also that the `PropertyItem.Type` value should be 3 (16-bit integers), and the `Len` value at least 2. While the code you have should work, IMHO it is more correct to go ahead and use `BitConverter` to convert the first two bytes in the `Value` array to an `Int16`, in case there's some weird value > 255. – Peter Duniho Jan 08 '15 at 08:36
  • hi thanks for reply, actually i am service provider and web service in wcf service. android and ios developer sent me image and as per image i have to rotate or crop. so they need to set image property? – Jimmy Darji Jan 08 '15 at 12:25
  • A note if you are using `Image.FromStream` to read the image. You must set `useEmbeddedColorManagement` to `true` for this to work. Otherwise, `PropertyItems` will be empty. Example: `var image = Image.FromStream(memoryStream, true);` – rybl Sep 02 '21 at 20:52

5 Answers5

66

There's probably enough information in the other answers and comments to put this all together, but here's a working code example.

This extension method will take a System.Drawing Image, read its Exif Orientation tag (if present), and flip/rotate it (if necessary).

private const int exifOrientationID = 0x112; //274

public static void ExifRotate(this Image img)
{
    if (!img.PropertyIdList.Contains(exifOrientationID))
        return;

    var prop = img.GetPropertyItem(exifOrientationID);
    int val = BitConverter.ToUInt16(prop.Value, 0);
    var rot = RotateFlipType.RotateNoneFlipNone;

    if (val == 3 || val == 4)
        rot = RotateFlipType.Rotate180FlipNone;
    else if (val == 5 || val == 6)
        rot = RotateFlipType.Rotate90FlipNone;
    else if (val == 7 || val == 8)
        rot = RotateFlipType.Rotate270FlipNone;

    if (val == 2 || val == 4 || val == 5 || val == 7)
        rot |= RotateFlipType.RotateNoneFlipX;

    if (rot != RotateFlipType.RotateNoneFlipNone)
    {
        img.RotateFlip(rot);
        img.RemovePropertyItem(exifOrientationID);
    }
}
William
  • 8,007
  • 5
  • 39
  • 43
saucecontrol
  • 1,446
  • 15
  • 17
  • This worked perfectly on my dev machine. I upload it to production and, for the same picture, it acts as if the file doesn't have the Exif information. Do you know why that could be? – Diego Jancic Nov 28 '18 at 21:12
  • 1
    `System.Drawing` uses the [Windows Imaging Component](https://learn.microsoft.com/en-us/windows/desktop/wic/-wic-about-windows-imaging-codec) underneath, so there could be some difference in codec capabilities between your dev and prod Windows installs. Same applies if you're using `System.Drawing` on a non-Windows machine, where a compatibility layer would be in place. – saucecontrol Nov 29 '18 at 22:23
  • I've put a question here in case you know more info: https://stackoverflow.com/questions/53546113/net-exif-information-not-working-on-production-server Thanks! – Diego Jancic Nov 29 '18 at 23:07
  • 1
    Thanks! I noticed that iphone images are turned to the side when I try to display them. I do a re-size which strips the exif data (which is what I want, that makes the display correctly)... but it was saving them the wrong way. Perfect fix for me nice one – eric k atwood Mar 01 '20 at 21:41
  • 1
    You may also want to use `SetPropertyItem` to set the `exifOrientationID` to `0`. – Jamie Kitson Jul 30 '21 at 15:25
  • @JamieKitson or just remove it after rotation img.RemovePropertyItem(exifOrientationID); – mhapps May 18 '22 at 10:26
  • 1
    This code is great but slightly "too clever" imho. For example value 4 = vertical flip, is implemented as 180 rotation + horizontal flip. It is more readable to have a simple switch enumerating all possible values and mapping directly to their .NET counterparts. – Joan Charmant Mar 29 '23 at 10:31
6

Use the following:

  • img.PropertyIdList.Contains(orientationId) to check if the Exif tag is present.
  • img.GetPropertyItem(orientationId) to get it (after the above check, otherwise you'll get an ArgumentException).
  • img.SetPropertyItem(pItem) to set it.

I wrote a simple helper class that does all that: you can check the full source code here.

Other info and a quick case-study is also available on the following post on my blog:

Change image orientation for iPhone and/or Android pics in NET C#

Darkseal
  • 9,205
  • 8
  • 78
  • 111
2

You can use this link http://regex.info/exif.cgi to examine your image embedded metadata. If you don't find "0x0112" in the EXIF table, then the image does not contain rotation property.

TH Todorov
  • 1,129
  • 11
  • 26
0

Maybe you resizing of the image and at this moment you lose exif and you want to make a rotate image according to exif, in this case you just can copy exif into resized image:

const string inputFileName = "input.jpg";
const string outputFileName = "output.jpg";
var newSize = new Size(640, 480);
using (var bmpInput = Image.FromFile(inputFileName))
{
    using (var bmpOutput = new Bitmap(bmpInput, newSize))
    {
        foreach (int exif in bmpInput.PropertyIdList)
            bmpOutput.SetPropertyItem(bmpInput.GetPropertyItem(exif));
        bmpOutput.Save(outputFileName, ImageFormat.Jpeg);
    }
}
Dmitry Shashurov
  • 1,148
  • 13
  • 11
0

This is what I use:

// pass in an image
ChkImage.ImageOrientation image = ChkImage.GetOrientation(picCrop.Image);


public enum ImageOrientation
{
  /// <summary>
  /// Image is correctly oriented
  /// </summary>
  Original = 1,
  /// <summary>
  /// Image has been mirrored horizontally
  /// </summary>
  MirrorOriginal = 2,
  /// <summary>
  /// Image has been rotated 180 degrees
  /// </summary>
  Half = 3,
  /// <summary>
  /// Image has been mirrored horizontally and rotated 180 degrees
  /// </summary>
  MirrorHalf = 4,
  /// <summary>
  /// Image has been mirrored horizontally and rotated 270 degrees clockwise
  /// </summary>
  MirrorThreeQuarter = 5,
  /// <summary>
  /// Image has been rotated 270 degrees clockwise
  /// </summary>
  ThreeQuarter = 6,
  /// <summary>
  /// Image has been mirrored horizontally and rotated 90 degrees clockwise.
  /// </summary>
  MirrorOneQuarter = 7,
  /// <summary>
  /// Image has been rotated 90 degrees clockwise.
  /// </summary>
  OneQuarter = 8
}



public static PropertyItem SafeGetPropertyItem(Image image, int propid)
{
  try
  {
    return image.GetPropertyItem(propid);
  }
  catch (ArgumentException)
  {
    return null;
  }
}


public static ImageOrientation GetOrientation(this Image image)
{
  PropertyItem pi = SafeGetPropertyItem(image, 0x112);

  if (pi == null || pi.Type != 3)
  {
    return ImageOrientation.Original;
  }

  return (ImageOrientation)BitConverter.ToInt16(pi.Value, 0);
}
  • Remember that Stack Overflow isn't just intended to solve the immediate problem, but also to help future readers find solutions to similar problems, which requires understanding the underlying code. This is especially important for members of our community who are beginners, and not familiar with the syntax. Given that, **can you [edit] your answer to include an explanation of what you're doing** and why you believe it is the best approach? – Jeremy Caney May 26 '23 at 03:10