Skip to content

Commit

Permalink
Merge branch 'develop'
Browse files Browse the repository at this point in the history
  • Loading branch information
sbaeumlisberger committed Aug 14, 2020
2 parents 4015e76 + c80a48c commit 3b1d391
Show file tree
Hide file tree
Showing 12 changed files with 276 additions and 176 deletions.
4 changes: 2 additions & 2 deletions Samples/InPlaceMetadataEncoding/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ static void Main(string[] args)
{
Console.WriteLine("The file format does not support the requested metadata.");
}
catch (Exception ex) when (ex.HResult == WinCodecError.TOOMUCHMETADATA
|| ex.HResult == WinCodecError.INSUFFICIENTBUFFER
catch (Exception ex) when (ex.HResult == WinCodecError.TOO_MUCH_METADATA
|| ex.HResult == WinCodecError.INSUFFICIENT_BUFFER
|| ex.HResult == WinCodecError.IMAGE_METADATA_HEADER_UNKNOWN
|| ex.HResult == WinCodecError.UNSUPPORTED_OPERATION)
{
Expand Down
9 changes: 7 additions & 2 deletions WIC/Constants/WinCodecError.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
namespace WIC
{
/// <summary>
/// <see cref="https://docs.microsoft.com/de-de/windows/win32/wic/-wic-codec-error-codes"/>
/// </summary>
public static class WinCodecError
{
public const int PROPERTY_NOT_FOUND = unchecked((int)0x88982F40);
public const int PROPERTY_NOT_SUPPORTED = unchecked((int)0x88982F41);
public const int UNSUPPORTED_OPERATION = unchecked((int)0x88982F81);
public const int TOOMUCHMETADATA = unchecked((int)0x88982F52);
public const int INSUFFICIENTBUFFER = unchecked((int)0x88982F8C);
public const int TOO_MUCH_METADATA = unchecked((int)0x88982F52);
public const int INSUFFICIENT_BUFFER = unchecked((int)0x88982F8C);
public const int IMAGE_METADATA_HEADER_UNKNOWN = unchecked((int)0x88982F63);
public const int COMPONENT_NOT_FOUND = unchecked((int)0x88982F50);
public const int CODEC_NO_THUMBNAIL = unchecked((int)0x88982F44);
}
}
2 changes: 1 addition & 1 deletion WIC/Enumerations/ExifColorSpace.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@
public enum ExifColorSpace : int
{
SRGB = 1,
AdobeSRGB = 2,
AdobeRGB = 2,
}
}
18 changes: 17 additions & 1 deletion WIC/Extensions/IWICBitmapFrameDecodeExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,23 @@ public static IWICMetadataBlockReader AsMetadataBlockReader(this IWICBitmapFrame

public static IWICColorContext[] GetColorContexts(this IWICBitmapFrameDecode bitmapFrameDecode)
{
return FetchIntoBufferHelper.FetchArray<IWICColorContext>(bitmapFrameDecode.GetColorContexts);
var wic = new WICImagingFactory();

bitmapFrameDecode.GetColorContexts(0, null, out int length);

var colorContexts = new IWICColorContext[length];

if (length > 0)
{
for (int i = 0; i < length; i++)
{
colorContexts[i] = wic.CreateColorContext();
}

bitmapFrameDecode.GetColorContexts(length, colorContexts, out _);
}

return colorContexts;
}

public static void Initialize(this IWICBitmapFrameEncode bitmapFrameEncode, IPropertyBag2 pIEncoderOptions = null)
Expand Down
10 changes: 8 additions & 2 deletions WIC/Extensions/IWICImagingFactoryExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.ComponentModel;
using System.IO;

namespace WIC
{
Expand Down Expand Up @@ -45,14 +46,19 @@ public static IWICBitmapDecoder CreateDecoderFromFilename(this IWICImagingFactor
}
}

public static IWICBitmapDecoder CreateDecoderFromStream(this IWICImagingFactory imagingFactory, IStream pIStream, WICDecodeOptions metadataOptions, Guid? pguidVendor = null)
public static IWICBitmapDecoder CreateDecoderFromStream(this IWICImagingFactory imagingFactory, IStream stream, WICDecodeOptions metadataOptions, Guid? pguidVendor = null)
{
using (var pguidVendorPtr = CoTaskMemPtr.From(pguidVendor))
{
return imagingFactory.CreateDecoderFromStream(pIStream, pguidVendorPtr, metadataOptions);
return imagingFactory.CreateDecoderFromStream(stream, pguidVendorPtr, metadataOptions);
}
}

public static IWICBitmapDecoder CreateDecoderFromStream(this IWICImagingFactory imagingFactory, Stream stream, WICDecodeOptions metadataOptions, Guid? pguidVendor = null)
{
return imagingFactory.CreateDecoderFromStream(stream.AsCOMStream(), metadataOptions, pguidVendor);
}

public static IWICBitmapEncoder CreateEncoder(this IWICImagingFactory factory, Guid guidContainerFormat, Guid? pguidVendor = null)
{
using (var pguidVendorPtr = CoTaskMemPtr.From(pguidVendor))
Expand Down
78 changes: 73 additions & 5 deletions WIC/Extensions/IWICMetadataQueryReaderExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,19 +1,39 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.InteropServices;
using static WIC.PropVariantHelper;

namespace WIC
{
[EditorBrowsable(EditorBrowsableState.Advanced)]
public static class IWICMetadataQueryReaderExtensions
{
/// <summary>
/// Retrieves the current path relative to the root metadata block.
/// </summary>
/// <returns>The current namespace location.</returns>
/// <remarks>
/// If the query reader is relative to the top of the metadata hierarchy, it will return a single-char string.
/// <br/>
/// If the query reader is relative to a nested metadata block, this method will return the path to the current query reader.
/// </remarks>
public static string GetLocation(this IWICMetadataQueryReader metadataQueryReader)
{
return FetchIntoBufferHelper.FetchString(metadataQueryReader.GetLocation);
}

public static bool TryGetMetadataByName<T>(this IWICMetadataQueryReader metadataQueryReader, string name, out T value)
/// <summary>
/// Retrieves the metadata block or item identified by a metadata query expression.
/// </summary>
/// <param name="name">The query expression to the requested metadata block or item.</param>
/// <returns>The metadata block or item requested.</returns>
/// <exception cref="COMException">Thrown when the metadata block or item was not found (HRESULT 0x88982F40).</exception>
/// <remarks>
/// GetMetadataByName uses metadata query expressions to access embedded metadata. For more information on the metadata query language, see the Metadata Query Language Overview.
/// <br/>
/// If multiple blocks or items exist that are expressed by the same query expression, the first metadata block or item found will be returned.
/// </remarks>
public static object GetMetadataByName(this IWICMetadataQueryReader metadataQueryReader, string name)
{
if (metadataQueryReader is null)
{
Expand All @@ -28,17 +48,65 @@ public static bool TryGetMetadataByName<T>(this IWICMetadataQueryReader metadata
try
{
metadataQueryReader.GetMetadataByName(name, ref variant);
return TryDecode(ref variant, out value);
return PropVariantHelper.Decode(ref variant);
}
finally
{
PropVariantHelper.Dispose(ref variant);
}
}

/// <summary>
/// Retrieves the metadata block or item identified by a metadata query expression.
/// </summary>
/// <param name="name">The query expression to the requested metadata block or item.</param>
/// <param name="value">The metadata block or item requested or null if not found.</param>
/// <returns>True when the metadata block or item was found, otherwise false.</returns>
/// <remarks>
/// GetMetadataByName uses metadata query expressions to access embedded metadata. For more information on the metadata query language, see the Metadata Query Language Overview.
/// <br/>
/// If multiple blocks or items exist that are expressed by the same query expression, the first metadata block or item found will be returned.
/// </remarks>
public static bool TryGetMetadataByName(this IWICMetadataQueryReader metadataQueryReader, string name, out object value)
{
if (metadataQueryReader is null)
{
throw new NullReferenceException();
}
if (name is null)
{
throw new ArgumentNullException(nameof(name));
}

var variant = new PROPVARIANT();
try
{
metadataQueryReader.GetMetadataByName(name, ref variant);
value = PropVariantHelper.Decode(ref variant);
return true;
}
catch (COMException ex) when (ex.ErrorCode == WinCodecError.PROPERTY_NOT_FOUND)
{
value = default(T);
value = null;
return false;
}
finally
{
Dispose(ref variant);
PropVariantHelper.Dispose(ref variant);
}
}

/// <summary>
/// Gets the names of all metadata items at the current relative location within the metadata hierarchy.
/// </summary>
/// <returns>An enumerable that contains query strings that can be used in the current <see cref="IWICMetadataQueryReader"/>.</returns>
/// <remarks>
/// The retrieved enumerable only contains query strings for the metadata blocks and items in the current level of the hierarchy.
/// </remarks>
public static IEnumerable<string> GetNames(this IWICMetadataQueryReader metadataQueryReader)
{
return metadataQueryReader.GetEnumerator().AsEnumerable();
}

}
}
14 changes: 11 additions & 3 deletions WIC/Extensions/IWICMetadataQueryWriterExtensionsy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,22 @@ namespace WIC
[EditorBrowsable(EditorBrowsableState.Advanced)]
public static class IWICMetadataQueryWriterExtensions
{
/// <summary>
/// Sets a metadata item to a specific location.
/// </summary>
/// <param name="name">The name of the metadata item.</param>
/// <param name="value">The metadata to set.</param>
/// <remarks>
/// SetMetadataByName uses metadata query expressions to set metadata. For more information on the metadata query language, see the Metadata Query Language Overview.
/// </remarks>
public static void SetMetadataByName(this IWICMetadataQueryWriter metadataQueryWriter, string name, object value)
{
if (metadataQueryWriter is null)
{
throw new NullReferenceException();
}
if (name is null)
{
if (name is null)
{
throw new ArgumentNullException(nameof(name));
}
if (value is null)
Expand All @@ -29,7 +37,7 @@ public static void SetMetadataByName(this IWICMetadataQueryWriter metadataQueryW
}
finally
{
variant.Dispose();
PropVariantHelper.Dispose(ref variant);
}
}

Expand Down
Loading

0 comments on commit 3b1d391

Please sign in to comment.