0

NOTE: this is UWP-specific, please do not reply with what works in WPF, WinForms, C++, etc. we have already looked at these.

Trying to encode iTXt metadata block into a PNG in UWP/WIC but having an issue with the Keyword field. Encoding metadata with other encoders works fine (if you know the "rules" of each encoder).

"Vanilla" WIC documentation says that Keyword has type VT_LPSTR. A well-referenced example (not for UWP) states to pass the "char array" via String.toCharArray but this does not work in UWP, and generates ArgumentException: Value does not fall within the expected range. when trying to set the BitmapProperties.SetPropertiesAsync.

Trying to encode a "regular" tEXt metadata block works just fine, because the keyword is part of the "path" e.g. "/tEXt/{str=Software}" for the "Software" tag.

pset.Add("/[*]tEXt/{str=Author}", new BitmapTypedValue("The Author", Windows.Foundation.PropertyType.String));

As a bonus complication, the [*] is required when adding multiple blocks (e.g. Author and Description), otherwise only one comes out!

However for an iTXt block (at least) two such values are required: the Keyword and the TextEntry.

What also failed for iTXt is using the "key" syntax so "/[*]iTXt/{str=Software}/TextEntry" results in Exception: The codec is in the wrong state so this is clearly not intended use.

This applies to any other "structured" metadata items in other formats. This does not appear to be an issue for the "media policy" based metadata; it appears already "destructured" to facilitate BitmapTypeValue for everything.

Can anyone provide insight into how to make this work (in UWP C#)?

Update

In the meantime, figured out we need to pass in an "aggregate" object instead of doing it as indicated previously (deleted). This means passing in a value of Inspectable.

When receiving decoded metadata from e.g. a JPG with XMP in it, these appear as Windows.Graphics.Imaging.BitmapPropertiesView instances. This makes sense; as commenter pointed out, the data is "structured".

However, there appears to be no way to construct an instance of BitmapPropertyView and set that as the BitmapTypedValue representing an aggregate metadata value. Looking at the other relevant classes, there appear to be no "moves" to get from something with a constructor, to BitmapPropertiesView.

We have tried this incantation with no luck; produces a "cast" exception (which makes sense considering).

var txt = new BitmapPropertySet();
txt.Add("Keyword", new BitmapTypedValue("Software", Windows.Foundation.PropertyType.String));
txt.Add("CompressionFlag", new BitmapTypedValue(1, Windows.Foundation.PropertyType.UInt8));
txt.Add("TextEntry", su);
pset.Add("/[*]iTXt", new BitmapTypedValue(txt, Windows.Foundation.PropertyType.Inspectable));

Obviously BitmapPropertySet cannot function as the "container" but then what class in the UWP can be used here?

escape-llc
  • 1,295
  • 1
  • 12
  • 25
  • VT_LPSTR is for VARIANT type only. UWP (C#) should do the mapping between WinRT HSTRING and .NET string and WIC/COM string types. "Value does not fall within the expected range" doesn't sound like a type issue. Have you tried to read back metadata from an existing file using UWP. Metadata is a hierarchy, maybe you don't properly define/use it. – Simon Mourier Aug 10 '21 at 17:27
  • That occurred to me after posting; I have a different problem now please read the edited answer. – escape-llc Aug 11 '21 at 23:38
  • In fact, if you try this `txt.Add("/iTXt/TranslatedKeyword", new BitmapTypedValue("Software", Windows.Foundation.PropertyType.String));` directly on root, it seems to work for *TranslatedKeyword*, *TextEntry* and (0 or 1) for *CompressionFlag* (although nothing is written). *TranslatedKeyword* and *TextEntry* are supposed to be LPWSTR (unicode string) while it fails for *Keyword* and *LanguageTag* which are supposed to be ansi string... this looks like a bug somewhere in language projections... IMHO you should ask Microsoft. Note this is not UWP-only, this the WinRT API. – Simon Mourier Aug 12 '21 at 10:46
  • @SimonMourier thank you for the follow-up and if it's language projection issue that makes sense. I was thinking of switching to some C++/RT interop instead do you think that would fly? – escape-llc Aug 25 '21 at 13:56
  • Thinking twice, I'm not sure it's a language projection issue. It can also be a lower WinRT issue, when WinRT's Windows.Graphics.dll (this dll hosts BitmapTypedValue type) converts WIC's VARIANTs into WinRT's PropertyValue. UWP uses the same stuff. You can try with C++/WinRT (or even C#/WinRT, you don't need UWP, just .NET 5). If it doesn't change anything I would ask Microsoft. – Simon Mourier Aug 25 '21 at 15:40

0 Answers0