Reading JPEG problems Metadata (orientation)

I have a JPEG image that was shot on an iphone. On my desktop PC (Windows Photo Viewer, Google Chrome, etc.) The orientation is incorrect.

I am working on an ASP.NET MVC 3 web application where I need to upload photos (plupload is currently used).

I have server code for image processing, including reading EXIF โ€‹โ€‹data.

I tried reading the PropertyTagOrientation field in EXIF โ€‹โ€‹metadata (using GDI - Image.PropertyItems ), but this field is missing.

So this is either some specific iphone metadata or some other metadata.

I used another tool, such as Aurigma Photo Uploader, and it reads metadata correctly and rotates the image. How it's done?

Does anyone know what other JPEG metadata may contain the information needed to know that it needs to be rotated, which is used by Aurigma?

Here is the code that I use to read EXIF โ€‹โ€‹data:

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

Any ideas?

+48
c # image-processing jpeg metadata gdi
Jun 03 '11 at 1:15
source share
6 answers

It looks like you forgot that the orientation identifier values โ€‹โ€‹you were looking for are in hexadecimal format. If you use 112, you should use 0x112.

This article explains how Windows-oriented orientation is ported, and this one seems pretty important for what you do.

+17
Jun 03 2018-11-11T00:
source share

Here is a snippet that refers to 8 orientation values.

First, a few notes:

EXIF id 0x0112 is for orientation. This is a useful EXIF โ€‹โ€‹id link http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/EXIF.html

0x0112 is the hexadecimal equivalent of 274 . The data type PropertyItem.Id is int , which means 274 .

Also, assume that 5029 is 0x5029 or 20521 , which correlates with ThumbnailOrientation, although this is most likely not the case. / p>

Orientation Image:

Note: img is or inherited from System.Drawing.Bitmap , e.g. 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); } 
+110
May 01 '14 at 1:23
source share

I wrote a small helper class to summarize all the answers. It will also update the Exif Orientation Tag according to the changes made to the image, which can be useful if you view the image in the exif-aware viewer after rotating it. This should also solve the problem raised by @ShalinJirawla above.

 using System.Drawing; using System.Drawing.Imaging; using System.Linq; public static class ImageHelper { /// <summary> /// Rotate the given image file according to Exif Orientation data /// </summary> /// <param name="sourceFilePath">path of source file</param> /// <param name="targetFilePath">path of target file</param> /// <param name="targetFormat">target format</param> /// <param name="updateExifData">set it to TRUE to update image Exif data after rotation (default is TRUE)</param> /// <returns>The RotateFlipType value corresponding to the applied rotation. If no rotation occurred, RotateFlipType.RotateNoneFlipNone will be returned.</returns> public static RotateFlipType RotateImageByExifOrientationData(string sourceFilePath, string targetFilePath, ImageFormat targetFormat, bool updateExifData = true) { // Rotate the image according to EXIF data var bmp = new Bitmap(sourceFilePath); RotateFlipType fType = RotateImageByExifOrientationData(bmp, updateExifData); if (fType != RotateFlipType.RotateNoneFlipNone) { bmp.Save(targetFilePath, targetFormat); } return fType; } /// <summary> /// Rotate the given bitmap according to Exif Orientation data /// </summary> /// <param name="img">source image</param> /// <param name="updateExifData">set it to TRUE to update image Exif data after rotation (default is TRUE)</param> /// <returns>The RotateFlipType value corresponding to the applied rotation. If no rotation occurred, RotateFlipType.RotateNoneFlipNone will be returned.</returns> public static RotateFlipType RotateImageByExifOrientationData(Image img, bool updateExifData = true) { int orientationId = 0x0112; var fType = RotateFlipType.RotateNoneFlipNone; if (img.PropertyIdList.Contains(orientationId)) { var pItem = img.GetPropertyItem(orientationId); fType = GetRotateFlipTypeByExifOrientationData(pItem.Value[0]); if (fType != RotateFlipType.RotateNoneFlipNone) { img.RotateFlip(fType); // Remove Exif orientation tag (if requested) if (updateExifData) img.RemovePropertyItem(orientationId); } } return fType; } /// <summary> /// Return the proper System.Drawing.RotateFlipType according to given orientation EXIF metadata /// </summary> /// <param name="orientation">Exif "Orientation"</param> /// <returns>the corresponding System.Drawing.RotateFlipType enum value</returns> public static RotateFlipType GetRotateFlipTypeByExifOrientationData(int orientation) { switch (orientation) { case 1: default: return RotateFlipType.RotateNoneFlipNone; case 2: return RotateFlipType.RotateNoneFlipX; case 3: return RotateFlipType.Rotate180FlipNone; case 4: return RotateFlipType.Rotate180FlipX; case 5: return RotateFlipType.Rotate90FlipX; case 6: return RotateFlipType.Rotate90FlipNone; case 7: return RotateFlipType.Rotate270FlipX; case 8: return RotateFlipType.Rotate270FlipNone; } } } 

Further information and a brief case study are also available here:

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

+26
Jul 19 '16 at 13:23
source share

From this post it 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; } } 
+15
Jun 03 2018-11-11T00:
source share

I combined these answers and comments and came up with the following:

  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; } } } 
+12
Jan 27 '14 at 10:33
source share

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

The code is pretty simple:

 var img = new MagickImage(inputStream); img.AutoOrient(); // Fix orientation img.Strip(); // remove all EXIF information img.Write(outputPath); 
0
Nov 30 '18 at 21:16
source share



All Articles