Hi Lars,
welcome to the forums!
Yes, UAAttributeData.ValueType just gets you the .NET type of the value. And the .NET type is derived from the "type on the wire". And on the wire, in OPC UA, all Image data types are encoded as ByteArray, so it is not possible to distinguish between them. So, simply by reading the Value attribute, you cannot determine the image type - and that applies to UAExpert too.
What you are really interested in is not the "type on the wire", but the DataType of the node in OPC UA sense. To obtain that, you need to read the DataType attribute of the node (in addition to the Value attribute which you are already reading). So you may end up with twice as much items in your ReadMultiple call.
Example of reading the UA data types is here:
opclabs.doc-that.com/files/onlinedocs/QuickOpc/Latest/User%2...d%20DataType%20attributes.html
You need to pass in UAAttributeId.DataType somewhere - depending on the concrete method overload you are using.
What you get back is a value for that attribute node ID (UANodeId object, in QuickOPC). And you can compare it to predefined values from the OPC specification:
reference.opcfoundation.org/v104/Core/DataTypes/#ImageBMP
In QuickOPC, you can use following symbols for the comparison (namespace OpcLabs.EasyOpc.UA.AddressSpace.Standard):
- UADataTypeIds.ImageBMP
- UADataTypeIds.ImageGIF
- UADataTypeIds.ImageJPG
- UADataTypeIds.ImagePNG
Note: For complete correctness, because there is no way in OPC UA to "seal" the types, one would have to consider that somebody may derive his own type from one of these types, and use it, and the consuming software should still be able to deal with it. In this case the comparisons against predefined DataTypes won't work, and it would be necessary to walk through the DataType hierarchy in the server to figure out the type inheritance. If you are interested, I can elaborate on that, but frankly, I would not bother with it in your case.
Best regards