2021-11-03 19:05:35 +01:00
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System ;
2021-11-23 12:19:09 +01:00
using System.Collections.Generic ;
using System.Diagnostics ;
2021-11-03 19:05:35 +01:00
using System.Windows.Media.Imaging ;
namespace ImageResizer.Extensions
{
internal static class BitmapMetadataExtension
{
public static void CopyMetadataPropertyTo ( this BitmapMetadata source , BitmapMetadata target , string query )
{
if ( source = = null | | target = = null | | string . IsNullOrWhiteSpace ( query ) )
{
return ;
}
try
{
var value = source . GetQuerySafe ( query ) ;
if ( value = = null )
{
return ;
}
target . SetQuery ( query , value ) ;
}
catch ( InvalidOperationException )
{
// InvalidOperationException is thrown if metadata object is in readonly state.
return ;
}
}
public static object GetQuerySafe ( this BitmapMetadata metadata , string query )
{
if ( metadata = = null | | string . IsNullOrWhiteSpace ( query ) )
{
return null ;
}
try
{
2021-11-23 12:19:09 +01:00
if ( metadata . ContainsQuery ( query ) )
{
return metadata . GetQuery ( query ) ;
}
else
{
return null ;
}
2021-11-03 19:05:35 +01:00
}
catch ( NotSupportedException )
{
// NotSupportedException is throw if the metadata entry is not preset on the target image (e.g. Orientation not set).
return null ;
}
}
2021-11-23 12:19:09 +01:00
public static void RemoveQuerySafe ( this BitmapMetadata metadata , string query )
{
if ( metadata = = null | | string . IsNullOrWhiteSpace ( query ) )
{
return ;
}
try
{
if ( metadata . ContainsQuery ( query ) )
{
metadata . RemoveQuery ( query ) ;
}
}
catch ( Exception ex )
{
Debug . WriteLine ( $"Exception while trying to remove metadata entry at position: {query}" ) ;
Debug . WriteLine ( ex ) ;
}
}
public static void SetQuerySafe ( this BitmapMetadata metadata , string query , object value )
{
if ( metadata = = null | | string . IsNullOrWhiteSpace ( query ) | | value = = null )
{
return ;
}
try
{
metadata . SetQuery ( query , value ) ;
}
catch ( Exception ex )
{
Debug . WriteLine ( $"Exception while trying to set metadata {value} at position: {query}" ) ;
Debug . WriteLine ( ex ) ;
}
}
/// <summary>
2021-12-10 14:54:05 +01:00
/// Gets all metadata.
/// Iterates recursively through metadata and adds valid items to a list while skipping invalid data items.
2021-11-23 12:19:09 +01:00
/// </summary>
2021-12-10 14:54:05 +01:00
/// <remarks>
/// Invalid data items are items which throw an exception when reading the data with metadata.GetQuery(...).
/// Sometimes Metadata collections are improper closed and cause an exception on IEnumerator.MoveNext(). In this case, we return all data items which were successfully collected so far.
/// </remarks>
/// <returns>
/// metadata path and metadata value of all successfully read data items.
/// </returns>
2022-12-18 14:27:14 +01:00
public static List < ( string MetadataPath , object Value ) > GetListOfMetadata ( this BitmapMetadata metadata )
2021-11-23 12:19:09 +01:00
{
2022-12-18 14:27:14 +01:00
var listOfAllMetadata = new List < ( string MetadataPath , object Value ) > ( ) ;
2021-11-23 12:19:09 +01:00
2021-12-10 14:54:05 +01:00
try
{
GetMetadataRecursively ( metadata , string . Empty ) ;
}
catch ( Exception ex )
{
Debug . WriteLine ( $"Exception while trying to iterate recursively over metadata. We were able to read {listOfAllMetadata.Count} metadata entries." ) ;
Debug . WriteLine ( ex ) ;
}
2021-11-23 12:19:09 +01:00
return listOfAllMetadata ;
void GetMetadataRecursively ( BitmapMetadata metadata , string query )
{
foreach ( string relativeQuery in metadata )
{
string absolutePath = query + relativeQuery ;
object metadataQueryReader = null ;
try
{
metadataQueryReader = GetQueryWithPreCheck ( metadata , relativeQuery ) ;
}
catch ( Exception ex )
{
Debug . WriteLine ( $"Removing corrupt metadata property {absolutePath}. Skipping metadata entry | {ex.Message}" ) ;
Debug . WriteLine ( ex ) ;
}
if ( metadataQueryReader ! = null )
{
listOfAllMetadata . Add ( ( absolutePath , metadataQueryReader ) ) ;
}
else
{
Debug . WriteLine ( $"No metadata found for query {absolutePath}. Skipping empty null entry because its invalid." ) ;
}
if ( metadataQueryReader is BitmapMetadata innerMetadata )
{
GetMetadataRecursively ( innerMetadata , absolutePath ) ;
}
}
}
object GetQueryWithPreCheck ( BitmapMetadata metadata , string query )
{
if ( metadata = = null | | string . IsNullOrWhiteSpace ( query ) )
{
return null ;
}
if ( metadata . ContainsQuery ( query ) )
{
return metadata . GetQuery ( query ) ;
}
else
{
return null ;
}
}
}
/// <summary>
/// Prints all metadata to debug console
/// </summary>
/// <remarks>
2023-10-04 11:05:06 +01:00
/// Intended for debug only!!!
2021-11-23 12:19:09 +01:00
/// </remarks>
public static void PrintsAllMetadataToDebugOutput ( this BitmapMetadata metadata )
{
if ( metadata = = null )
{
Debug . WriteLine ( $"Metadata was null." ) ;
}
var listOfMetadata = metadata . GetListOfMetadataForDebug ( ) ;
foreach ( var metadataItem in listOfMetadata )
{
// Debug.WriteLine($"modifiableMetadata.RemoveQuerySafe(\"{metadataItem.metadataPath}\");");
2022-12-18 14:27:14 +01:00
Debug . WriteLine ( $"{metadataItem.MetadataPath} | {metadataItem.Value}" ) ;
2021-11-23 12:19:09 +01:00
}
}
/// <summary>
/// Gets all metadata
/// Iterates recursively through all metadata
/// </summary>
/// <remarks>
2023-10-04 11:05:06 +01:00
/// Intended for debug only!!!
2021-11-23 12:19:09 +01:00
/// </remarks>
2022-12-18 14:27:14 +01:00
public static List < ( string MetadataPath , object Value ) > GetListOfMetadataForDebug ( this BitmapMetadata metadata )
2021-11-23 12:19:09 +01:00
{
2022-12-18 14:27:14 +01:00
var listOfAllMetadata = new List < ( string MetadataPath , object Value ) > ( ) ;
2021-11-23 12:19:09 +01:00
2021-12-10 14:54:05 +01:00
try
{
GetMetadataRecursively ( metadata , string . Empty ) ;
}
catch ( Exception ex )
{
Debug . WriteLine ( $"Exception while trying to iterate recursively over metadata. We were able to read {listOfAllMetadata.Count} metadata entries." ) ;
Debug . WriteLine ( ex ) ;
}
2021-11-23 12:19:09 +01:00
return listOfAllMetadata ;
void GetMetadataRecursively ( BitmapMetadata metadata , string query )
{
2022-02-04 17:59:33 +01:00
if ( metadata = = null )
{
return ;
}
2021-11-23 12:19:09 +01:00
foreach ( string relativeQuery in metadata )
{
string absolutePath = query + relativeQuery ;
object metadataQueryReader = null ;
try
{
metadataQueryReader = metadata . GetQuerySafe ( relativeQuery ) ;
listOfAllMetadata . Add ( ( absolutePath , metadataQueryReader ) ) ;
}
catch ( Exception ex )
{
listOfAllMetadata . Add ( ( absolutePath , $"######## INVALID METADATA: {ex.Message}" ) ) ;
Debug . WriteLine ( ex ) ;
}
if ( metadataQueryReader is BitmapMetadata innerMetadata )
{
GetMetadataRecursively ( innerMetadata , absolutePath ) ;
}
}
}
}
2021-11-03 19:05:35 +01:00
}
}