[Image Resizer] Fix image resizer unexpected property type or value (#14475)

* fixes issue #9885, image 2 and 3

* fixes issue #9885, image 1

* fixes issue #9885, image 2 and 3 (refactoring)

* try to get past the spell checker

* Loop over all metadata and try to read the actual value. Remove metadata item if exception is thrown on reading the value.

* Add debug utils which will help to troubleshoot further metadata bugs

* Revert "try to get past the spell checker"

This reverts commit 34aa0728b5.

* I gave up on fiddling with individual metadata decided to  build up the metadata object from the scratch

* Improved log messages, add comments, renamed variables
This commit is contained in:
CleanCodeDeveloper 2021-11-23 12:19:09 +01:00 committed by GitHub
parent 641d838140
commit 6452369351
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 214 additions and 5 deletions

View file

@ -3,6 +3,8 @@
// See the LICENSE file in the project root for more information.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Windows.Media.Imaging;
namespace ImageResizer.Extensions
@ -43,7 +45,14 @@ namespace ImageResizer.Extensions
try
{
return metadata.GetQuery(query);
if (metadata.ContainsQuery(query))
{
return metadata.GetQuery(query);
}
else
{
return null;
}
}
catch (NotSupportedException)
{
@ -51,5 +60,179 @@ namespace ImageResizer.Extensions
return null;
}
}
public static void RemoveQuerySafe(this BitmapMetadata metadata, string query)
{
if (metadata == null || string.IsNullOrWhiteSpace(query))
{
return;
}
try
{
if (metadata.ContainsQuery(query))
{
metadata.RemoveQuery(query);
}
}
#pragma warning disable CA1031 // Do not catch general exception types
catch (Exception ex)
#pragma warning restore CA1031 // Do not catch general exception types
{
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);
}
#pragma warning disable CA1031 // Do not catch general exception types
catch (Exception ex)
#pragma warning restore CA1031 // Do not catch general exception types
{
Debug.WriteLine($"Exception while trying to set metadata {value} at position: {query}");
Debug.WriteLine(ex);
}
}
/// <summary>
/// Gets all metadata
/// Iterates recursively through all metadata
/// </summary>
public static List<(string metadataPath, object value)> GetListOfMetadata(this BitmapMetadata metadata)
{
var listOfAllMetadata = new List<(string metadataPath, object value)>();
GetMetadataRecursively(metadata, string.Empty);
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);
}
#pragma warning disable CA1031 // Do not catch general exception types
catch (Exception ex)
#pragma warning restore CA1031 // Do not catch general exception types
{
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>
/// Intented for debug only!!!
/// </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}\");");
Debug.WriteLine($"{metadataItem.metadataPath} | {metadataItem.value}");
}
}
/// <summary>
/// Gets all metadata
/// Iterates recursively through all metadata
/// </summary>
/// <remarks>
/// Intented for debug only!!!
/// </remarks>
public static List<(string metadataPath, object value)> GetListOfMetadataForDebug(this BitmapMetadata metadata)
{
var listOfAllMetadata = new List<(string metadataPath, object value)>();
GetMetadataRecursively(metadata, string.Empty);
return listOfAllMetadata;
void GetMetadataRecursively(BitmapMetadata metadata, string query)
{
foreach (string relativeQuery in metadata)
{
string absolutePath = query + relativeQuery;
object metadataQueryReader = null;
try
{
metadataQueryReader = metadata.GetQuerySafe(relativeQuery);
listOfAllMetadata.Add((absolutePath, metadataQueryReader));
}
#pragma warning disable CA1031 // Do not catch general exception types
catch (Exception ex)
#pragma warning restore CA1031 // Do not catch general exception types
{
listOfAllMetadata.Add((absolutePath, $"######## INVALID METADATA: {ex.Message}"));
Debug.WriteLine(ex);
}
if (metadataQueryReader is BitmapMetadata innerMetadata)
{
GetMetadataRecursively(innerMetadata, absolutePath);
}
}
}
}
}
}

View file

@ -3,6 +3,7 @@
// See the LICENSE file in the project root for more information. Code forked from Brice Lambson's https://github.com/bricelam/ImageResizer/
using System;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.IO.Abstractions;
@ -83,11 +84,36 @@ namespace ImageResizer.Models
try
{
// Detect whether metadata can copied successfully
_ = metadata.Clone();
var modifiableMetadata = metadata.Clone();
#if DEBUG
Debug.WriteLine($"### Processing metadata of file {_file}");
modifiableMetadata.PrintsAllMetadataToDebugOutput();
#endif
// read all metadata and build up metadata object from the scratch. Discard invalid (unreadable/unwritable) metadata.
var newMetadata = new BitmapMetadata(metadata.Format);
var listOfMetadata = modifiableMetadata.GetListOfMetadata();
foreach (var (metadataPath, value) in listOfMetadata)
{
if (value is BitmapMetadata bitmapMetadata)
{
var innerMetadata = new BitmapMetadata(bitmapMetadata.Format);
newMetadata.SetQuerySafe(metadataPath, innerMetadata);
}
else
{
newMetadata.SetQuerySafe(metadataPath, value);
}
}
metadata = newMetadata;
}
catch (ArgumentException)
catch (ArgumentException ex)
{
metadata = null;
Debug.WriteLine(ex);
}
}
@ -105,9 +131,9 @@ namespace ImageResizer.Models
encoder.Frames.Add(
BitmapFrame.Create(
Transform(originalFrame),
thumbnail: null,
originalFrame.Thumbnail,
metadata,
colorContexts: null));
originalFrame.ColorContexts));
}
path = GetDestinationPath(encoder);