Esempio n. 1
1
        internal static BitmapSource ApplyOrientation(BitmapSource bitmap, BitmapMetadata metadata)
        {
            if (metadata == null || !metadata.ContainsQuery("System.Photo.Orientation"))
                return bitmap;

            ushort orientation = (ushort)metadata.GetQuery("System.Photo.Orientation");

            switch (orientation)
            {
                case 2: // flip horizontal
                    return new TransformedBitmap(bitmap, new ScaleTransform(-1, 1));

                case 3: // rotate 180
                    return new TransformedBitmap(bitmap, new RotateTransform(-180));

                case 4: // flip vertical
                    return new TransformedBitmap(bitmap, new ScaleTransform(1, -1));

                case 5: // transpose
                    bitmap = new TransformedBitmap(bitmap, new ScaleTransform(1, -1));
                    goto case 8;

                case 6: // rotate 270
                    return new TransformedBitmap(bitmap, new RotateTransform(-270));

                case 7: // transverse
                    bitmap = new TransformedBitmap(bitmap, new ScaleTransform(-1, 1));
                    goto case 8;

                case 8: // rotate 90
                    return new TransformedBitmap(bitmap, new RotateTransform(-90));

                default:
                    return bitmap;
            }
        }
Esempio n. 2
0
 private static short getOrientation(BitmapMetadata metadata)
 {
     try {
         ushort?orientationProp;
         if (metadata.ContainsQuery(JpegOrientationQuery))
         {
             orientationProp = metadata.GetQuery(JpegOrientationQuery) as ushort?;
         }
         else if (metadata.ContainsQuery(RawOrientationQuery))
         {
             orientationProp = metadata.GetQuery(RawOrientationQuery) as ushort?;
         }
         else
         {
             return(1);
         }
         if (orientationProp.HasValue)
         {
             return((short)orientationProp.Value);
         }
     } catch (ArgumentException) {
         return(1);
     }
     return(1);
 }
Esempio n. 3
0
        public static void MoveQuery(this BitmapMetadata bitmapMetadata, string sourceQuery, string destinationQuery, bool overWriteExistingData)
        {
            // Check Source Query exists
            if (bitmapMetadata.ContainsQuery(sourceQuery))
            {
                bool existingData = bitmapMetadata.ContainsQuery(destinationQuery);

                if (existingData && !overWriteExistingData)
                {
                    // Skip the copy and source the value
                    bitmapMetadata.RemoveQuery(sourceQuery);
                }
                else
                {
                    // Copy the Query
                    bitmapMetadata.CopyQuery(sourceQuery, destinationQuery);

                    // Finally remove old query
                    bitmapMetadata.RemoveQuery(sourceQuery);

                    // Ensure old query has been removed
                    if (!bitmapMetadata.ContainsQuery(destinationQuery))
                    {
                        throw new Exception("Move Query Failed");
                    }
                }
            }
        }
Esempio n. 4
0
        public static void UpdateWLPGRegions(string inputFile)
        {
            using (WpfFileManager wpfFileManager = new WpfFileManager(inputFile, true))
            {
                // Declare a bunch of XMP paths (see my last blog for details)
                string microsoftRegions           = @"/xmp/MP:RegionInfo/MPRI:Regions";
                string microsoftPersonDisplayName = @"/MPReg:PersonDisplayName";
                string microsoftRectangle         = @"/MPReg:Rectangle";

                // Check the sourceMetadata contains a Region
                if (wpfFileManager.BitmapMetadata.ContainsQuery(microsoftRegions))
                {
                    // Get Region Data as BitmapMetadata
                    BitmapMetadata regionsMetadata = wpfFileManager.BitmapMetadata.GetQuery(microsoftRegions) as BitmapMetadata;

                    // Loop through each Region
                    foreach (string regionQuery in regionsMetadata)
                    {
                        string regionFullQuery = microsoftRegions + regionQuery;

                        // Grab Region metadata as BitmapMetadata
                        BitmapMetadata regionMetadata = wpfFileManager.BitmapMetadata.GetQuery(regionFullQuery) as BitmapMetadata;

                        // Change Rectangle & DisplayName to test values
                        if (regionMetadata != null)
                        {
                            // If the region has a DisplayName, change the value
                            if (regionMetadata.ContainsQuery(microsoftPersonDisplayName))
                            {
                                regionMetadata.SetQuery(XmpMicrosoftQueries.RegionPersonDisplayName.Query, "test");
                            }

                            // If the region has a DisplayName, change the value
                            if (regionMetadata.ContainsQuery(microsoftRectangle))
                            {
                                regionMetadata.SetQuery(XmpMicrosoftQueries.RegionRectangle.Query, "test");
                            }
                        }

                        // Write the Region back to Regions
                        wpfFileManager.BitmapMetadata.SetQuery(regionFullQuery, regionMetadata);
                    }

                    // Write the Regions back to Root Metadata
                    wpfFileManager.BitmapMetadata.SetQuery(microsoftRegions, regionsMetadata);
                }

                wpfFileManager.WriteMetadata();
            }
        }
Esempio n. 5
0
        public static void MoveStruct(this BitmapMetadata bitmapMetadata, string sourceNameSpace, string sourceStructName, string destinationNameSpace, string destinationStructName, bool overWriteExistingData, bool ignoreInvalidSource)
        {
            // Rewrite Structnames
            string sourceStruct = @"/xmp/" + sourceNameSpace + sourceStructName;
            string sourceQuery  = sourceStruct + "/" + sourceNameSpace;

            string destinationStruct = @"/xmp/" + destinationNameSpace + destinationStructName;
            string destinationQuery  = destinationStruct + "/" + destinationNameSpace;

            // Check Source exists
            bool sourceExists = bitmapMetadata.ContainsQuery(sourceStruct);

            if (sourceExists)
            {
                // Create a new Struct, if it doesn't exist
                if (!bitmapMetadata.ContainsQuery(destinationStruct))
                {
                    bitmapMetadata.SetQuery(destinationStruct, new BitmapMetadata("xmpstruct"));
                }

                List <string> sourceSubQueries = bitmapMetadata.GetSubQueries(sourceStruct);

                // Loop through all data in the struct
                foreach (string sourceProperty in sourceSubQueries)
                {
                    // Construct the full query
                    string destinationProperty = sourceProperty.Replace(sourceQuery, destinationQuery);

                    bitmapMetadata.MoveQuery(sourceProperty, destinationProperty, overWriteExistingData);
                }

                // Remove the old struct
                bitmapMetadata.RemoveQuery(sourceStruct);

                // Get Destination Queries
                List <string> destinationSubQueries = bitmapMetadata.GetSubQueries(destinationStruct);

                // Check the destination has at least as many subqueries as the source
                if (destinationSubQueries.Count < sourceSubQueries.Count)
                {
                    throw new Exception("Source Struct was not fully moved to Destination");
                }
            }
            else if (!sourceExists && !ignoreInvalidSource)
            {
                throw new Exception("Source Struct does not exist:" + sourceStruct);
            }
        }
    public Transformations(BitmapMetadata md)
    {
        // https://docs.microsoft.com/en-us/windows/win32/wic/-wic-photoprop-system-photo-orientation
        // https://docs.microsoft.com/en-us/windows/win32/properties/props-system-photo-orientation
        const string orientationProperty = "System.Photo.Orientation";

        if (md != null && md.ContainsQuery(orientationProperty))
        {
            var orientation = (Orientation)md.GetQuery(orientationProperty);
            switch (orientation)
            {
            case Orientation.FlipHorizontal:
                FlipHorizontal = true;
                break;

            case Orientation.FlipVertical:
                FlipVertical = true;
                break;

            case Orientation.Rotate90:
                Rotation = Rotation.Rotate90;
                break;

            case Orientation.Rotate180:
                Rotation = Rotation.Rotate180;
                break;

            case Orientation.Rotate270:
                Rotation = Rotation.Rotate270;
                break;
                // we don't support transpose & transverse
            }
        }
    }
Esempio n. 7
0
        private static TimeSpan GetFrameDelay(BitmapFrame frame)
        {
            // 100ms by default if the value is not defined in metadata
            TimeSpan duration = TimeSpan.FromMilliseconds(100);

            BitmapMetadata metaData = null;

            try
            {
                metaData = frame.Metadata as BitmapMetadata;
                if (metaData != null)
                {
                    const string query = "/grctlext/Delay";
                    if (metaData.ContainsQuery(query))
                    {
                        object o = metaData.GetQuery(query);
                        if (o != null)
                        {
                            ushort delay = (ushort)o;
                            duration = TimeSpan.FromMilliseconds(10 * delay);
                        }
                    }
                }
            }
            catch (NotSupportedException)
            {
            }

            return(duration);
        }
            static Rotation GetRotation(string filename)
            {
                BitmapFrame    bitmapFrame    = BitmapFrame.Create(new Uri(filename), BitmapCreateOptions.DelayCreation, BitmapCacheOption.None);
                BitmapMetadata bitmapMetadata = bitmapFrame.Metadata as BitmapMetadata;

                if (bitmapMetadata == null || !bitmapMetadata.ContainsQuery("System.Photo.Orientation"))
                {
                    return(Rotation.Rotate0);
                }

                //refer to http://www.impulseadventure.com/photo/exif-orientation.html for details on orientation values
                switch (bitmapMetadata.GetQuery("System.Photo.Orientation") as ushort?)
                {
                case 6:
                    return(Rotation.Rotate90);

                case 3:
                    return(Rotation.Rotate180);

                case 8:
                    return(Rotation.Rotate270);

                default:
                    return(Rotation.Rotate0);
                }
            }
Esempio n. 9
0
        /// <summary>
        /// Retrieves the EXIF meta data in JPEG format.
        /// </summary>
        /// <param name="metaData">The meta data.</param>
        /// <returns>The EXIF meta data, or null.</returns>
        internal static BitmapMetadata GetEXIFMetaData(BitmapMetadata metaData)
        {
            string format = string.Empty;

            try
            {
                format = metaData.Format; // Some WIC codecs do not implement the format property.
            }
            catch (ArgumentException)
            {
            }
            catch (NotSupportedException)
            {
            }

            if (format == "jpg")
            {
                if (metaData.ContainsQuery("/app1/ifd/exif"))
                {
                    return(metaData);
                }
            }
            else if (format != "gif" && format != "png")
            {
                // GIF and PNG files do not contain EXIF meta data.
                return(ConvertEXIFMetaData(metaData));
            }

            return(null);
        }
Esempio n. 10
0
        public static bool IsQueryValidAndOfType(this BitmapMetadata bitmapMetadata, string query, Type type)
        {
            // Check there's a query value
            if (bitmapMetadata.ContainsQuery(query))
            {
                type = bitmapMetadata.GetStorageType(type);

                // Get object
                Object obj = bitmapMetadata.GetQuery(query).GetType();

                if (obj != null)
                {
                    // Special case for empty strings, return true if set
                    // Otherwise check for null and then type
                    if (type == typeof(string))
                    {
                        return(true);
                    }
                    else if (obj == type)
                    {
                        return(true);
                    }
                }
            }

            return(false);
        }
Esempio n. 11
0
        public static bool TryGetQueryAs <TValue>(this BitmapMetadata metadata, string query, out TValue result)
        {
            if (!metadata.ContainsQuery(query))
            {
                result = default(TValue);
                return(false);
            }

            var value = metadata.GetQuery(query);

            if (value is TValue typedValue)
            {
                result = typedValue;
                return(true);
            }

            try
            {
                result = (TValue)Convert.ChangeType(value, typeof(TValue));
                return(true);
            }
            catch (Exception ex)
            {
                LogEx.For(typeof(ImageMetadataEx)).Error(
                    ex, "Failed to convert {Value} to {Type}",
                    value, typeof(TValue));

                result = default(TValue);
                return(false);
            }
        }
Esempio n. 12
0
        private Double GetRotation(string path)
        {
            using (FileStream fileStream = new FileStream(path, FileMode.Open, FileAccess.Read))
            {
                BitmapFrame    bitmapFrame    = BitmapFrame.Create(fileStream, BitmapCreateOptions.DelayCreation, BitmapCacheOption.None);
                BitmapMetadata bitmapMetadata = bitmapFrame.Metadata as BitmapMetadata;

                if ((bitmapMetadata != null) && (bitmapMetadata.ContainsQuery(_orientationQuery)))
                {
                    object o = bitmapMetadata.GetQuery(_orientationQuery);

                    if (o != null)
                    {
                        //refer to http://www.impulseadventure.com/photo/exif-orientation.html for details on orientation values
                        switch ((ushort)o)
                        {
                        case 6:
                            return(90D);

                        case 3:
                            return(180D);

                        case 8:
                            return(270D);
                        }
                    }
                }
                return(0D);
            }
        }
Esempio n. 13
0
        private int GetRotation(BitmapMetadata metadata)
        {
            int rotation = 0;

            if ((metadata != null) && metadata.ContainsQuery("System.Photo.Orientation"))
            {
                object o = metadata.GetQuery("System.Photo.Orientation");

                if (o != null)
                {
                    //refer to http://www.impulseadventure.com/photo/exif-orientation.html for details on orientation values
                    switch ((ushort)o)
                    {
                    case 6:
                        rotation = 90;
                        break;

                    case 3:
                        rotation = 180;
                        break;

                    case 8:
                        rotation = 270;
                        break;
                    }
                }
            }

            return(rotation);
        }
Esempio n. 14
0
        /// <summary>
        /// Retrieves the XMP meta data in TIFF format.
        /// </summary>
        /// <param name="metaData">The meta data.</param>
        /// <returns>The XMP meta data, or null.</returns>
        internal static BitmapMetadata GetXMPMetaData(BitmapMetadata metaData)
        {
            string format = string.Empty;

            try
            {
                format = metaData.Format; // Some WIC codecs do not implement the format property.
            }
            catch (ArgumentException)
            {
            }
            catch (NotSupportedException)
            {
            }

            if (format == "tiff")
            {
                if (metaData.ContainsQuery("/ifd/xmp"))
                {
                    return(metaData);
                }
            }
            else if (format != "gif")
            {
                // GIF files do not contain frame-level XMP meta data.
                return(ConvertXMPMetaData(metaData, format));
            }

            return(null);
        }
Esempio n. 15
0
 private static T GetQueryOrDefault <T>(
     this BitmapMetadata metadata,
     string query,
     T defaultValue)
 {
     return(metadata.ContainsQuery(query) ? (T)Convert.ChangeType(metadata.GetQuery(query), typeof(T), (IFormatProvider)CultureInfo.InvariantCulture) : defaultValue);
 }
        public static Rotation GetRotation(BitmapSource bitmapSource)
        {
            BitmapMetadata bitmapMetadata = bitmapSource.Metadata as BitmapMetadata;

            if ((bitmapMetadata != null) && (bitmapMetadata.ContainsQuery(OrientationQuery)))
            {
                object o = bitmapMetadata.GetQuery(OrientationQuery);

                if (o != null)
                {
                    //refer to http://www.impulseadventure.com/photo/exif-orientation.html for details on orientation values
                    switch ((ushort)o)
                    {
                        case 6:
                            return Rotation.Rotate90;
                        case 3:
                            return Rotation.Rotate180;
                        case 8:
                            return Rotation.Rotate270;
                    }
                }
            }

            return Rotation.Rotate0;
        }
Esempio n. 17
0
 public static T GetQueryOrDefault <T>(this BitmapMetadata metadata, string query, T defaultValue) where T : struct
 {
     if (!metadata.ContainsQuery(query))
     {
         return(defaultValue);
     }
     return((metadata.GetQuery(query) as T?).GetValueOrDefault(defaultValue));
 }
Esempio n. 18
0
 private object QueryMetadata(string query)
 {
     if (_metadata.ContainsQuery(query))
     {
         return(_metadata.GetQuery(query));
     }
     return(null);
 }
Esempio n. 19
0
 public static T?GetQueryOrNull <T>(this BitmapMetadata metadata, string query) where T : struct
 {
     if (!metadata.ContainsQuery(query))
     {
         return(null);
     }
     return(metadata.GetQuery(query) as T?);
 }
Esempio n. 20
0
 private static T GetQueryOrNull <T>(this BitmapMetadata metadata, string query) where T : class
 {
     if (metadata.ContainsQuery(query))
     {
         return(metadata.GetQuery(query) as T);
     }
     return(default(T));
 }
        /// <summary>
        /// 尝试从位图元数据中提取值并进行类型转换。
        /// </summary>
        /// <typeparam name="T">提取值的类型。</typeparam>
        /// <param name="metadata">位图元数据。</param>
        /// <param name="query">标识要在当前 <see cref="BitmapMetadata" /> 对象中查询的字符串。</param>
        /// <returns>位于指定查询位置的元数据。</returns>
        public static T GetQueryOrDefault <T>(this BitmapMetadata metadata, string query)
        {
            if (metadata.ContainsQuery(query))
            {
                return((T)Convert.ChangeType(metadata.GetQuery(query), typeof(T)));
            }

            return(default);
Esempio n. 22
0
 public static T GetQueryOrNull <T>(this BitmapMetadata metadata, string query)
     where T : class
 {
     if (metadata.ContainsQuery(query))
     {
         return(metadata.GetQuery(query) as T);
     }
     return(null);
 }
 public ushort GetOrientation()
 {
     if (_metaData.ContainsQuery(@"/app1/{ushort=0}/{ushort=274}"))
     {
         return((UInt16)_metaData.GetQuery(@"/app1/{ushort=0}/{ushort=274}")); //get rotation
     }
     else
     {
         return(1);
     }
 }
Esempio n. 24
0
 public static T GetQueryValue <T>(
     this BitmapMetadata poMetadata,
     string psQuery,
     T poDefault)
 {
     if (poMetadata.ContainsQuery(psQuery))
     {
         return((T)Convert.ChangeType(poMetadata.GetQuery(psQuery), typeof(T)));
     }
     return(poDefault);
 }
Esempio n. 25
0
 private object GetMetaInfo(string infoQuery)
 {
     if (_metaInfo.ContainsQuery(infoQuery))
     {
         return(_metaInfo.GetQuery(infoQuery));
     }
     else
     {
         return(null);
     }
 }
 private object queryMetadata(string query)
 {
     if (metadata.ContainsQuery(query))
     {
         return(metadata.GetQuery(query));
     }
     else
     {
         return(null);
     }
 }
Esempio n. 27
0
        public static void ReadWLPGRegions(string inputFile)
        {
            using (WpfFileManager wpfFileManager = new WpfFileManager(inputFile))
            {
                // Declare a bunch of XMP paths (see my last blog for details)
                string microsoftRegions           = @"/xmp/MP:RegionInfo/MPRI:Regions";
                string microsoftPersonDisplayName = @"/MPReg:PersonDisplayName";
                string microsoftRectangle         = @"/MPReg:Rectangle";

                // Check there is a RegionInfo
                if (wpfFileManager.BitmapMetadata.ContainsQuery(microsoftRegions))
                {
                    BitmapMetadata regionsMetadata = wpfFileManager.BitmapMetadata.GetQuery(microsoftRegions) as BitmapMetadata;

                    // Loop through each Region
                    foreach (string regionQuery in regionsMetadata)
                    {
                        string regionFullQuery = microsoftRegions + regionQuery;

                        // Query for all the data for this region
                        BitmapMetadata regionMetadata = wpfFileManager.BitmapMetadata.GetQuery(regionFullQuery) as BitmapMetadata;

                        if (regionMetadata != null)
                        {
                            if (regionMetadata.ContainsQuery(microsoftPersonDisplayName))
                            {
                                Console.WriteLine("PersonDisplayName:\t"
                                                  + regionMetadata.GetQuery(XmpMicrosoftQueries.RegionPersonDisplayName.Query).ToString());
                            }

                            if (regionMetadata.ContainsQuery(microsoftRectangle))
                            {
                                Console.WriteLine("Rectangle:\t\t"
                                                  + regionMetadata.GetQuery(XmpMicrosoftQueries.RegionRectangle.Query).ToString());
                            }
                        }
                    }
                }
            }
        }
Esempio n. 28
0
 private static T?GetQueryOrNull <T>(this BitmapMetadata metadata, string query)
     where T : struct
 {
     if (metadata.ContainsQuery(query))
     {
         object value = metadata.GetQuery(query);
         if (value != null)
         {
             return((T)value);
         }
     }
     return(null);
 }
Esempio n. 29
0
 private void CopyMetadataToProperties(BitmapMetadata bitmapMetadata, string query, string propertyName)
 {
     try
     {
         if (bitmapMetadata.ContainsQuery(query))
         {
             object value = bitmapMetadata.GetQuery(query);
             _properties[propertyName] = TranslateBitmapMetadataValue(value);
         }
     }
     catch (AccessViolationException e)
     {
         Debug.WriteLine(e);
     }
 }
Esempio n. 30
0
        public Process(string filepath, Task task)
        {
            if (string.IsNullOrEmpty(filepath))
            {
                throw new ArgumentNullException("filename", "Mandatory parameter is not specify");
            }

            Filename = filepath;

            // obtain later
            FileAccess accessType = FileAccess.Read;

            if (task.AccessType == MetadataAccessType.WRITE)
            {
                accessType = FileAccess.Write;
            }
            if (task.AccessType == MetadataAccessType.READWRITE)
            {
                accessType = FileAccess.ReadWrite;
            }

            string _orientationQuery = "/Text/Description";

            using (FileStream fileStream = new FileStream(filepath, FileMode.Open, accessType))
            {
                BitmapFrame    bitmapFrame    = BitmapFrame.Create(fileStream, BitmapCreateOptions.DelayCreation, BitmapCacheOption.None);
                BitmapMetadata bitmapMetadata = bitmapFrame.Metadata as BitmapMetadata;

                // read
                if ((bitmapMetadata != null))
                {
                    foreach (MetadataField fld in task.Queries)
                    {
                        if (bitmapMetadata.ContainsQuery(fld.Query))
                        {
                            object o = bitmapMetadata.GetQuery(fld.Query);

                            if (o != null)
                            {
                                //fld.ValueString = o as string;
                            }
                        }
                    }
                }
            }
        }
Esempio n. 31
0
        /// <summary>
        /// 画像のMetaDataの読み込み方
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Button_Click(object sender, RoutedEventArgs e)
        {
            // ファイル読み込み
            Uri         uri   = new Uri(tb_FileName.Text, UriKind.Absolute);
            BitmapFrame frame = BitmapFrame.Create(uri);

            // Metadataを格納し、下で取り出す
            BitmapMetadata metadata = frame.Metadata as BitmapMetadata;

            ////////////////////
            // 取り出し方① ContainsQueryでそのデータがあるか確認し、あればGetQueryで取り出す
            ////////////////////

            // ここのvarの値の型をbreak張って見て、uintであってるかどうか確認する!
            // また、戻り値の型が何かを確認する。
            // また、このクエリは画像のフォーマットによるらしい
            var queryMakerNote = string.Format("/app1/ifd/exif/{{uint={0}}}", 0x9000);

            bool containsMakerNote = metadata.ContainsQuery(queryMakerNote);

            if (containsMakerNote)
            {
                var objMakerNote = metadata.GetQuery(queryMakerNote);
                // GetQueryで帰ってくるデータはobject型なので、適切な型にキャストする必要がある
                //byte[] dataMakerNote = objMakerNote.GetBlobValue();
                // これがMakerNoteのデータ
                Console.WriteLine("Type : " + objMakerNote.GetType());
            }

            ////////////////////
            // 取り出し方② いきなりGetQueryで取り出す。{uint=xxxx}のところの型が間違えていると、エラーとなり取り出せない
            ////////////////////

            var val1 = metadata.GetQuery("/app1/ifd/gps/subifd:{ushort=1}");

            Debug.WriteLine(val1);
            var val2 = metadata.GetQuery("/app1/ifd/gps/subifd:{ushort=2}");

            Debug.WriteLine(val2);
            var val3 = metadata.GetQuery("/app1/ifd/gps/subifd:{ushort=3}");

            Debug.WriteLine(val3);
            var val4 = metadata.GetQuery("/app1/ifd/gps/subifd:{ushort=4}");

            Debug.WriteLine(val4);
        }
Esempio n. 32
0
        protected void EnumerateMetaData( BitmapMetadata _Root, params MetaDataProcessor[] _Processors )
        {
            foreach ( MetaDataProcessor Processor in _Processors )
            {
                if ( !_Root.ContainsQuery( Processor.Path ) )
                    continue;

                object	Value = _Root.GetQuery( Processor.Path );
                if ( Value == null )
                    throw new Exception( "Failed to find the metadata path \"" + Processor.Path + "\" !" );

                Processor.Process( Value );
            }
        }
Esempio n. 33
0
        private int GetRotation(BitmapMetadata metadata)
        {
            int rotation = 0;

            if ((metadata != null) && metadata.ContainsQuery("System.Photo.Orientation"))
            {
                object o = metadata.GetQuery("System.Photo.Orientation");

                if (o != null)
                {
                    //refer to http://www.impulseadventure.com/photo/exif-orientation.html for details on orientation values
                    switch ((ushort)o)
                    {
                        case 6:
                            rotation = 90;
                            break;
                        case 3:
                            rotation = 180;
                            break;
                        case 8:
                            rotation = 270;
                            break;
                    }
                }
            }

            return rotation;
        }