I'm trying to encode an image as an interlaced png using WIC. I can save the image as png without any problems and set the interlaced mode. But if i try to set a filtermode (any filter), i get the following error:
[System.Runtime.InteropServices.COMException] = {"The bitmap property type is unexpected. (Exception from HRESULT: 0x88982F8E)"}
Do i set the value of the property bag in a wrong way? This is the code, the exception is thrown at propBag.Write.
[...]
var arg = new IPropertyBag2[1];
encoder.CreateNewFrame(out outputFrame, arg);
var propBag = arg[0];
var propertyBagOptions = new PROPBAG2[2];
propertyBagOptions[0].pstrName = "InterlaceOption";
propertyBagOptions[1].pstrName = "FilterOption";
propBag.Write(2, propertyBagOption1, new object[] { true, WICPngFilterOption.WICPngFilterAdaptive});
[...]
Thanks for Help, Stephanie
I believe this is because the FilterOption
property needs to be an Unsigned Byte:
| Property Name |VARTYPE|Value Range | Default Value |
|---------------|-------|------------------|------------------------|
|InterlaceOption|VT_BOOL|TRUE/FALSE |FALSE |
|FilterOption |VT_UI1 |WICPngFilterOption|WICPngFilterUnspecified |
The underlying Write
method is marked to marshall the Value
as a VARIANT
(i.e. UnmanagedType.Struct
), which is correct:
void Write(
uint cProperties,
[MarshalAs(UnmanagedType.LPArray)] PROPBAG2[] pPropBag,
[MarshalAs(UnmanagedType.Struct)] ref object pvarValue
);
I'm not going to test it; because i can't, but i think the fix is to cast your PNG filter option to the C# equivalent of an unsigned byte byte.
propBag.Write(
1,
propertyBagOption,
UInt8(WICPngFilterOption.WICPngFilterAdaptive));
The reason i think this is because from my native code, i was giving the property value as a variant. But the variant was actually a signed 32-bit (aka Int32
). This caused the error:
0x88982F8E
When you look at WinCodec.h
(which is the native code that .NET imaging is using), it corresponds to error:
WINCODEC_ERR_PROPERTYUNEXPECTEDTYPE = HRESULT($88982f8E);
I has to make sure to force the variant to contain a VT_UI1:
propertyBagHelper.Write('FilterOption', VarAsType(WICPngFilterAdaptive, VT_UI1));
Then it succeeded.
This is all great from native code, when you know what's going on. The .NET/CLR/C# wrapper world loves to obfuscate everything; so you don't really know what the parameters contain when you pass them.
Note: Any code released into public domain. No attribution required.
User contributions licensed under CC BY-SA 3.0