Best way to pass an Image

Oct 26, 2008 at 7:44 PM
Edited Oct 26, 2008 at 7:45 PM
Hi,

I would like to pass an image from my addin to my host (WPF GUI)

I tried to use, System.Drawing.Bitmap in addin contract, but it's not possible : "The Bitmap class is not accessible across application domains"
see : http://msdn2.microsoft.com/en-us/library/system.drawing.bitmap.aspx

So I tried to use, System.Windows.media.Imaging.BitmapSource. Same kind of problem : see exception trace at the end of the post.

The only way I found (not yet tested) is to use a serializable custom image class, like described in this page :
http://social.msdn.microsoft.com/Forums/en-US/clr/thread/c1c292e7-d6a6-4f73-969a-5d37848d010d/

Is there a better way ?

Thanks in advance.



System.Windows.Data Error: 12 : Cannot get 'Image' value (type 'BitmapSource') from '' (type 'Action'). BindingExpression:Path=Image; DataItem='Action' (HashCode=20096322); target element is 'Image' (Name=''); target property is 'Source' (type 'ImageSource') TargetInvocationException:'System.Reflection.TargetInvocationException: Property accessor 'Image' on object 'AP.Core.Action' threw the following exception:'Type 'System.Windows.Media.Imaging.BitmapImage' in Assembly 'PresentationCore, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' is not marked as serializable.' ---> System.Runtime.Serialization.SerializationException: Type 'System.Windows.Media.Imaging.BitmapImage' in Assembly 'PresentationCore, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' is not marked as serializable.

Server stack trace:
   at System.Runtime.Serialization.FormatterServices.InternalGetSerializableMembers(RuntimeType type)
   at System.Runtime.Serialization.FormatterServices.GetSerializableMembers(Type type, StreamingContext context)
   at System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.InitMemberInfo()
   at System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.InitSerialize(Object obj, ISurrogateSelector surrogateSelector, StreamingContext context, SerObjectInfoInit serObjectInfoInit, IFormatterConverter converter, ObjectWriter objectWriter)
   at System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.Serialize(Object obj, ISurrogateSelector surrogateSelector, StreamingContext context, SerObjectInfoInit serObjectInfoInit, IFormatterConverter converter, ObjectWriter objectWriter)
   at System.Runtime.Serialization.Formatters.Binary.ObjectWriter.Serialize(Object graph, Header[] inHeaders, __BinaryWriter serWriter, Boolean fCheck)
   at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize(Stream serializationStream, Object graph, Header[] headers, Boolean fCheck)
   at System.Runtime.Remoting.Channels.CrossAppDomainSerializer.SerializeMessageParts(ArrayList argsToSerialize)
   at System.Runtime.Remoting.Messaging.SmuggledMethodReturnMessage..ctor(IMethodReturnMessage mrm)
   at System.Runtime.Remoting.Messaging.SmuggledMethodReturnMessage.SmuggleIfPossible(IMessage msg)
   at System.Runtime.Remoting.Channels.CrossAppDomainSink.DoDispatch(Byte[] reqStmBuff, SmuggledMethodCallMessage smuggledMcm, SmuggledMethodReturnMessage& smuggledMrm)
   at System.Runtime.Remoting.Channels.CrossAppDomainSink.DoTransitionDispatchCallback(Object[] args)

Exception rethrown at [0]:
   at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
   at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
   at AP.Addin.Contracts.IAction.get_Image()
   at AP.Addin.HostSideAdapters.IActionContractToViewHostAdapter.get_Image() in X:\Users\wesley\projets\ActionProposal\ActionProposalCore\HostSideAdapters\Generated Files\IActionContractToViewHostAdapter.g.cs:line 65
   at AP.Core.Action.get_Image() in X:\Users\wesley\projets\ActionProposal\ActionProposalCore\ActionProposalCore\Action.cs:line 49
   --- End of inner exception stack trace ---
   at System.ComponentModel.ReflectPropertyDescriptor.GetValue(Object component)
   at MS.Internal.Data.ValueTable.GetValue(Object item, PropertyDescriptor pd, Boolean indexerIsNext)
   at MS.Internal.Data.PropertyPathWorker.GetValue(Object item, Int32 level)
   at MS.Internal.Data.PropertyPathWorker.RawValue(Int32 k)'
Apr 9, 2010 at 7:39 PM
Edited Apr 9, 2010 at 7:40 PM

For what it's worth, I was able to pass a bitmap across the boundary.  The bitmap is a proxy version when it reaches the boundary.  But I could create a copy of the bitmap here and then throw away the proxy reference.  I initially attempted to use the proxy version, but at some point it would disconnect itself, which would throw an exception.  So now that I have the copy, I believe this is fixed.  To copy it I did a Bitmap.FromHbitmap(bitmapImage.GetHbitmap()).  Not sure if this is the best way, but it worked.