IPictureMarkerSymbols and IPictureDisp fun

I've been converting some GDI+ rendering code to use ESRI Graphics Layers...you know: IElement, ISymbol and all the usual suspects. The application environment I've been working in is a distributed app with many different clients and prior to my arrival on the project the decision was made that all custom symbologies would be serialized into an RDBMS, extracted at run-time, and sent down to each client at log on. It's just as well, since leveraging file paths and resource file images isn't exactly straightforward due to the need for us to leverage an unmanaged COM picture interface to create our custom picture marker symbols.

Basically, one portion of my task was to receive a byte array and turn that into an IPictureMarkerSymbol that could be used to plop a point in a map. The gist of the code would look something like... //Need a symbol, a picture marker symbol, and a color //in order to properly manipulate supplied icons IPictureMarkerSymbol pictureMarkerSymbol; IRgbColor color; stdole.IPictureDisp pic; //An IPictureDisp object is required to build picture markers // Create Picture Marker Symbol glyphs from provisioned items pictureMarkerSymbol = new PictureMarkerSymbolClass(); pic = SupportingUtilities.ImageConverter.GetIPictureDispFromBitmap(iconBytes); //if any portion of the icon is supposed to be transparent, deal with those RGB settings color = new RgbColorClass(); color.Red = icon.TransparencyColor.R; color.Green = icon.TransparencyColor.G; color.Blue = icon.TransparencyColor.B; color.UseWindowsDithering = true; pictureMarkerSymbol.BitmapTransparencyColor = (IColor)color; //set picture and size pictureMarkerSymbol.Picture = pic; pictureMarkerSymbol.Size = iconSize; sym = pictureMarkerSymbol as ISymbol; //QI for the symbol Note the "pic" variable and the call to ImageConverter::GetIPictureDispFromBitmap. The picture for a marker symbol isn't an image, bitmap, or filepath...it's an IPictureDisp. Thing one was to look up IPictureDisp and find out that it's an unmanaged COM picture interface. So how to create an IPictureDisp from the byte array I was being handed from the DAL? Andrew Whitechapel has a pretty good post over here summarizing how to leverage an undocumented private method of the AxHost object. I should note that Ryan offers an alternative solution developed by Thomas Quinn that doesn't leverage AxHost inheritance...that approach can be found here. Here's the file that I came up with. It'll accept either an array of bytes for the input image or an actual image class and hand back an IPictureDisp for use in building picture based markers, etc. in the ESRI realm. Hopefully it's of use to somebody. internal class ImageConverter : AxHost { internal ImageConverter() : base(string.Empty) { } static internal IPictureDisp GetIPictureDispFromBitmap(byte[] currentIconBytes) { if (currentIconBytes == null) { throw new ArgumentNullException("currentIconBytes"); } //Must do this on a non null byte array with something in it if (currentIconBytes != null && currentIconBytes.Length > 0) { //get a stream Stream bmpStream = new MemoryStream(currentIconBytes); //and create an image from stream Image image = Image.FromStream(bmpStream); //now access the protected utility method and return the result return (IPictureDisp)ImageConverter.GetIPictureDispFromPicture(image); } else { return null; } } static internal IPictureDisp GetIPictureDispFromImage(Image useImage) { if (useImage == null) { throw new ArgumentNullException("useImage"); } return (IPictureDisp)ImageConverter.GetIPictureDispFromPicture(useImage); } }