读取JPEG元数据时的问题(方向)
我有一个在iPhone上拍摄的JPEG图像。 在我的台式电脑(Windows照片查看器,谷歌浏览器等)方向是不正确的。
我正在一个ASP.NET MVC 3 Web应用程序,我需要上传照片(目前正在使用plupload)。
我有一些服务器端代码来处理图像,包括读取EXIF数据。
我已经尝试读取EXIF元数据中的PropertyTagOrientation
字段(使用GDI – Image.PropertyItems
),但该字段不存在。
所以它是一些特定的iPhone元数据,或者其他元数据。
我已经使用了像Aurigma Photo Uploader这样的工具,它正确地读取元数据并旋转图像。 这是怎么做到的?
有没有人知道其他JPEG元数据可能包含所需的信息,以便知道它需要旋转,这是由Aurigma使用?
这里是我用来读取EXIF数据的代码:
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's in here - can't find these properties. } }
有任何想法吗?
您似乎忘记了您查找的方向ID值是hex的。 在你使用112的地方,你应该使用0x112。
这篇文章解释了Windows如何高枕无忧地定位处理,而这个处理看起来与你正在做的事情非常相关。
这是一个解决8方向值的片段。
首先几个注意事项:
EXIF ID 0x0112用于方向。 这是一个有用的EXIF ID参考http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/EXIF.html
0x0112是274的hex等值。 PropertyItem.Id
的数据types是一个int
,这意味着在这里有用。
此外, 5029可能应该是0x5029或20521与ThumbnailOrientation相关,但可能不是这里所需的。
东方形象:
注意: img
是一个System.Drawing.Image
或从它inheritance,像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); }
我写了一个小帮手来总结所有的答案。 它也将相应更新Exif方向标签,对图像进行修改,如果在旋转后在exif-aware查看器应用程序中查看图像,这可能很有用。 这也应该可以解决上面的@ShalinJirawla提出的问题。
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; } } }
其他信息和快速案例研究也可在这里:
在C#中更改iPhone和/或Android图片的图像方向
从这个post看起来像你需要检查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; } }
我结合了给定的答案和评论,并提出这个:
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; } } }