I am attempting (and failing) to add an image to a map layout using ArcObjects via Python comtypes. I do need to run this outside of ArcMap (i.e. not in the ArcMap Python window).

The basic idea is: open mxd, place jpg in layout, save/close mxd.

Python solution preferred, but I would also accept a similar workflow in VB.NET.

Using ArcGIS 10.2.2, Python 2.7.5


from comtypes.client import GetModule, CreateObject
from Snippets import GetLibPath, InitStandalone

def CType(obj, interface):
   """Casts obj to interface and returns comtypes POINTER or None"""
       newobj = obj.QueryInterface(interface)
       return newobj
       return None

def main():
    modCarto = GetModule(r"C:\Program Files (x86)\ArcGIS\Desktop10.2\com\esriCarto.olb")
    modGeom = GetModule(r"C:\Program Files (x86)\ArcGIS\Desktop10.2\com\esriGeometry.olb")
    modArcMapUI = GetModule(r"C:\Program Files (x86)\ArcGIS\Desktop10.2\com\esriArcMapUI.olb")
    modFramework = GetModule(r"C:\Program Files (x86)\ArcGIS\Desktop10.2\com\esriFramework.olb")

    app = CreateObject(modFramework.AppROT, interface=modFramework.IAppROT)
    mxDoc = CType(app.Item(0).Document,modArcMapUI.IMxDocument)
    layout = mxDoc.PageLayout
    graphicContainer = CType(layout, modCarto.IGraphicsContainer)

    pictureElement = CreateObject(modCarto.JpgPictureElement, interface=modCarto.IPictureElement)

    envelope = CreateObject(modGeom.Envelope, interface=modGeom.IEnvelope)
    envelope.PutCoords(0, 0, 5, 5)

    pictureElement.Geometry = envelope

    iElement = CType(pictureElement,modCarto.IElement)

    graphicContainer.AddElement(pictureElement,0) # ERROR HERE


if __name__ == '__main__':

Traceback (whether attempting to add pictureElement or iElement):

Traceback (most recent call last):
  File "C:\Scripts\arcobjects_add_jpeg.py", line 54, in <module>
  File "C:\Scripts\arcobjects_add_jpeg.py", line 47, in main
COMError: (-2147024809, 'The parameter is incorrect.', (None, None, None, 0, None))

Full disclosure: I am absolutely new with ArcObjects, so whether or not I am handling/creating/juggling objects between interfaces correctly, I am not sure, but I think I'm close.

  • I've not done picture elements but the docs say pictureElement doesn't have a geometry, IElement does. Cast to iElement and then set iElement.geometry = envelope. You may need to set some other stuff on the picture element before casting see help.arcgis.com/en/sdk/10.0/arcobjects_net/componenthelp/… (aspect ratio, save in doc..) Apr 16 '15 at 0:05
  • @MichaelMiles-Stimson You're absolutely right! Please add as an answer. I still haven't figured out the ArcObject Help files - can you elaborate how you determined pictureElement doesn't have geometry? I thought I was specifying a JpgPictureElement, which should accept geometry (help.arcgis.com/en/sdk/10.0/arcobjects_net/componenthelp/…) but there is obviously something I'm missing. Thanks for the clue, exactly what I was looking for!
    – phloem
    Apr 16 '15 at 16:30

The Esri help can be quite counter-intuitive, you need to know what you're searching for to get the description...

The issue here is that the pictureElement doesn't have a geometry property.. see the Help page for picture element:

enter image description here

However the IElement, which implements JpegPictureElement, does have a geometry: enter image description here

Explanation of Esri help symbols, they are in the documentation for Properties and Methods:

enter image description here

This is from the Esri help, methods do something and properties are values in/of the object. These symbols are very important, especially when you're getting frustrated trying to set values on an object only to find that they're read only. In this case you can get the SelectionTracker but you cannot set it, conversely you can update or retrieve the Geometry 'value' of the object.

But the only way to tell if you can make a JpegPictureElement into an IElement is on the IElement help page in the CoClasses that implement IElement: enter image description here

This tells you that any of the listed CoClasses can be cast into an IElement, if it's not on the list you will get an error if you try to cast. For example IFeature isn't on the list so if you try iElement = CType(myFeature,modCarto.IElement) it will fail!

The correct order to do this in is:

pictureElement.ImportPictureFromFile(r'C:\junk\happy.jpg') # populate the JpegPictureElement

iElement = CType(pictureElement,modCarto.IElement) # convert JpegPictureElement into IElement
iElement.Geometry = envelope                       # set the geometry

graphicContainer.AddElement(iElement,0)            # add to frame
  • Thank you for the thorough explanation, especially about co-classes and casting from one to the other.
    – phloem
    Apr 16 '15 at 22:20
  • excellent answer. Please consider recasting (without duplicating) for gis.stackexchange.com/questions/129456/… May 15 '15 at 20:04
  • nice job gratz but, work it in 10.1? Jun 11 '15 at 17:04
  • The answer contains general information that would (theoretically) work back to 9.1 (and possibly before, but I have to draw a line somewhere) I personally use 10.1 and can attest that the instructions will work for that version. Which particular part are you having difficulty with? In order to use COM types in python a further download is required, see gis.stackexchange.com/questions/80/… and be sure to follow the links, a small hack is required to the default install to get COMTypes to work in python with ArcGis. Jun 11 '15 at 21:57
  • @mattwilkie, I'm not sure how to do that. Can you give instructions on how to recast or point me to a link that shows steps. Jun 11 '15 at 21:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.