Automating Clip Output to Graphics Extent with arcpy

2829
6
11-09-2017 06:32 PM
AllisonBailey
New Contributor III

I have a set of mxds that I would like to automate the process of printing to a PNG.  These files will be incorporated into other documents, so I need to remove the whitespace around the edge of the layout.  I can do this from the ArcMap interface using "Clip Output to Graphics Extent.", but there is no parameter in the ExportToPNG function to replicate this process in arcpy.mapping.    See:  arcpy function to Clip Output to Graphics Extent 

Similar questions have been posed on this board, 

Clip Output to Graphics Extent with arcpy 

Arcpy.mapping Get the extent of the map elements. 

but I need a little more clarification about how to actual automate the process with the version of Python and associated libraries that are installed with ArcMap (if that is, in fact, possible). 

I can get the max/min extent of the layout elements, (in page units) using arcpy.mapping.ListLayoutElements(), but I'm not sure how I can then use those values within the script to constrain the output image extent.  Is this possible?  Or do I need to use an external graphics library as mentioned by Gerry Gabrisch?  

The use of Data Driven Pages functionality was mentioned, but the specifics of this approach are not clear to me, since I have not used them before.   At first glance seems like a bit of a cumbersome approach for a simple need to get rid of white space around the edge of the page, but I'm open to using it if it's possible to automate the whole process.   

My layouts are often made up of several data frames as well as some individual graphic and text elements, so I'm not sure if that has any implications for use of the DDP approach.   In addition, the mxds that I would like to print, are not necessarily related to each other, I just want to be able to batch export a set of maps.

Thanks for any code snippets, tips, or ideas.   

Cross-referencing to mapping group: https://community.esri.com/community/gis/mapping 

0 Kudos
6 Replies
JoshuaBrengel
New Contributor III

Hi Allison,

I realize this is an old post, but did you ever get any traction on this?  I have a similar issue.  I would like to export hundreds of layout view grouped graphics as a JPEG for use in a Word Doc.  I don't want any white space surrounding my exported map.  

Thank you for any help you might be able to provide!

Sincerely,

- Josh

0 Kudos
AllisonBailey
New Contributor III

Hi Josh,

Sadly, no, I did not get any replies and just defaulted to manually exporting them from the ArcMap interface.  I am using ArcMap 10.4, so I do not know if this option was added to the arcpy.mapping library in a later version or in ArcPro.    

If you do come up with a solution, please post back to this thread.

Allison

0 Kudos
JoshuaBrengel
New Contributor III

Ok, thanks for following up Allison.  I use 10.4, too.  I sort of follow what Gerry said but I'm struggling to translate it into automated Python code. 

In essence, I believe he is getting each of the elements' extent from the layout view using arcpy.mapping classes (ie GraphicsElements, DataFrame, TextElements, etc).  That may take some math in python to calculate the extent values (xy min/max) if you are using any other layout element besides DataFrame (LegendElement, TextElement, etc.).   DataFrame has an "extent" property from which you can get xmin, xmax, ymin, ymax values.  If using other elements, you would have to calculate those values using the elementHeight, elementWidth, elementXPosition, and elementYPosition properties.  

Then, I suppose he is cropping the original exported image using PIL's (Python Image Library) "crop" method, which requires four pixel coordinates values- left, upper, right, lower.  I've never used PIL, so I'm not familiar enough with what properties (xmin, xmax, ymin, ymax) from the mapping class equal what pixel coordinates from PIL crop method.  Also, I'm not sure if the properties (xmin, xmax, etc) from ArcGIS mapping, which are in map units, can easily be inputted into PIL's crop method without first undergoing some type of conversion to get them into pixel coordinates.   Plus, I'm not sure what the units of the original exported image (in my case, a JPEG with unwanted white space) are!  If they aren't correct in pixel coordinates, then you'd have to convert them so crop method works properly.   

That's probably more confusing than helpful, but I was basically thinking off the top of my head in hopes it was useful for you.  It would be nice to have Gerry's input, but I don't think he's even logged into GeoNet for quite some time...

0 Kudos
AllisonBailey
New Contributor III

Thanks Josh.

Yeah, I agree, conceptually it all makes sense and relies on getting the page coordinates set up for the clipping.  It just seems a bit cumbersome to have to go through so many steps to implement a checkbox function that ESRI has already coded!  

Because my workflow did not include hundreds of images, I fell back on the manual method, but I would probably try to automate if I was in your shoes.

Good luck!

0 Kudos
JoshuaBrengel
New Contributor III

Hi Allison, 

Thought I'd follow up on this question.  I was able to create a bit of a workaround that worked for me.  You can convert your mxd to a pdf using "ExportToPDF" and then use "PDFToTIFF_conversion" to convert the pdf to an image:

import arcpy
import numpy as np
import os

basepath = r'L:\Projects\WIP_Toolbox'
num = 1583 #Map Number
i = 0
cntylist = ['County1']#County2, County3, County4, County5, County6, County7, County8]

for cnty in cntylist:
    cntypath = os.path.join(basepath, cnty)
    inpath = r'L:\Projects\WIP_Toolbox\County\County_Wshds.mxd' # Input path for Watershed basemap
    outpath = r'L:\Projects\WIP_Toolbox\Test'
    outpdf = os.path.join(outpath, 'Test.pdf')
    outtiff = os.path.join(outpath, 'testimage.tif')
    mxd = arcpy.mapping.MapDocument(inpath)
    arcpy.mapping.ExportToPDF(mxd, outpdf, "PAGE_LAYOUT")
    arcpy.PDFToTIFF_conversion(outpdf, outtiff, clip_option = True, resolution = 250, color_mode = "RGB_TRUE_COLOR", tiff_compression = "JPEG")
‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

I'm self aware enough to realize this is not the most elegant/efficient solution and it may not work for other cases (ie for those whose purposes are better suited to a direct jpeg output or people who may have trouble clipping their picture in a more custom manner).  But, for those comfortable exclusively with arcpy tools, it does remain entirely inside that domain.  You can use the "RasterToOtherFormat_conversion" tool to get a JPEG (or another desired format)- though again, admittedly inefficient.

At the very least, I'm hoping this answer spurs someone with more advanced skills in Python image analysis to suggest a more elegant solution using perhaps the Python package PIL or pillow.  Hopefully, it provides a good first step though!

- Josh

JoshuaBrengel
New Contributor III

I should also add that ArcGIS Pro has a method for its Layout object called exportToPDF.  It includes a "clip_to_elements" parameter, which appears to accomplish the same outcome as clipping to graphic's extent- albeit in PDF format.  Could convert to a JPEG though.  Perhaps Esri will add this new parameter as an option in the old "mapping" class module in future updates.  Note: we haven't updated to ArcGIS Pro yet, so I'm not able to provide an actual test of this method for various layout types/formats.

0 Kudos