Ask A Cartographer

GeoPDFs and ArcGIS

December 13 2011 | 10 comments
Categories: Map Data

USGS has embarked on digitizing historic topographic maps for all US states.(http://nationalmap.gov/historical/) Finished maps are in GeoPDF format, which as far as I can tell is not useable directly in ArcGIS 10. Opening GeoPDF in Acrobat Reader or Professional with TerraGo toolbar works fine but has limitations. I can "save as" out of Acrobat Professional as either a TIFF or JPEG/JPEG2000, but no world file is created and resulting files are not georeferenced. It is possible, of course, to georeference the files in Arc, but I would like to find a way to work with these files directly in Arc without the additional steps of file conversion and georeferencing. Is this possible? and if not please add it to the list of functions that should be addressed. This is a huge and valuable dataset that should be accessible to Arc users.

Thanks & Happy Holidays

Dave

Mapping Center Answer:

You cannot currently view GeoPDF in ArcMap. You might like to add your support to this functionality at the Ideas site entry View GeoPDF files in ArcMap.

GeoPDFs and ArcGIS posted by Dave Tewksbury on Dec 15 2011 12:35PM
Added these comments to the Ideas Site. Hope some progress occurs. Comments on the Ideas site go back to July 2010 looking for this functionality. TerraGo Publisher toolbar for ArcGIS adds the capability to import GeoPDFs into ArcGIS but it is $$$$$ to add. With only a few quads needed it probably makes more sense simply to export the georeferenced GeoPDF from Acrobat as non georeferenced TIFF and re-georeference the GeoPDF derived TIFF file so it can be used in Arc. Seems rather silly to have to jump through all these hoops.

Worth noting that if you work for an agency associated with the Department of Defense and have a DoD CAC card, the Army corps of Engineers have a free GeoPDF to ArcGIS extension that allows importing GeoPDFs or any geo-referenced PDF directly into ArcGIS. This plug in was announced in 2007!
Thanks posted by Kenneth Field on Dec 15 2011 12:39PM
Thanks for the additional comments.
Esri Options for GeoPDF? posted by Lorri Peltz-Lewis on Apr 4 2012 4:29PM
Are there plans for Esri to allow for loading of GeoPDFs since this is now becoming a defacto standard? Seems this was done for SID when we faced the same issues in the past..... what about supporting this product as core?
Vote it up! Time to rally! posted by Lorri Peltz-Lewis on Apr 4 2012 5:54PM
If you want to see this capability in Esri products then use the ArcGIS Ideas website to vote this up.
ArcGIS Ideas posted by Aileen Buckley on Apr 5 2012 9:39AM
Thanks for reminding us, Lorrie!
TerraGo posted by Aileen Buckley on Apr 5 2012 10:07AM
Regarding your question from April 4th, Lorrie: TerraGo's ArcMap extension lets you both write and read GeoPDF files. That's the only solution we know of right now, but of course, it's not free.
GEO PDFs posted by Dave Tewksbury on Apr 5 2012 10:45AM
Here is a work-around until ESRI supports GeoPDFs. Global Mapper will read GeoPDFs and export them with a world file as a GeoTiff or Imagine file which can be read by ArcMap. Just tested this with Geo PDF downloaded from USGS Historical quad site, opened GeoPDF in GM, exported as GeoTiff and opened in ArcMap. GM is $399, there is an educational discount. There is also a 2 week free trial which is fully functional and is how I just tested this.

Cheers,

Dave
Conversion of GeoPDFs to GeoTiffs for USGS Histori posted by jim schmidt on Aug 2 2013 10:21AM
Here's a python script (version 3.3) that will convert historic USGS GeoPDFs in polyconic coordinates to UTM GeoTiffs. Requires GDAL libraries. I installed the MS4W package and run the script from the MS4W shell prompt.

import glob, os
import subprocess
import pyproj

def GetLatLon(line):
coords = line.split(') (')[1]
coords = coords[:-1]
LonStr, LatStr = coords.split(',')
# Longitude
LonStr = LonStr.split('d') # Get the degrees, and the rest
LonD = int(LonStr[0])
LonStr = LonStr[1].split('\'')# Get the arc-m, and the rest
LonM = int(LonStr[0])
LonStr = LonStr[1].split('"') # Get the arc-s, and the rest
LonS = float(LonStr[0])
Lon = LonD + LonM/60. + LonS/3600.
if LonStr[1] in ['W', 'w']:
Lon = -1*Lon
# Same for Latitude
LatStr = LatStr.split('d')
LatD = int(LatStr[0])
LatStr = LatStr[1].split('\'')
LatM = int(LatStr[0])
LatStr = LatStr[1].split('"')
LatS = float(LatStr[0])
Lat = LatD + LatM/60. + LatS/3600.
if LatStr[1] in ['S', 's']:
Lat = -1*Lat
return Lat, Lon

EPSGin = "EPSG:4267" # Lat-Lon, NAD27 - Assumed coordinate system of lat-lon corner coordinates
#EPSGout = "EPSG:26910" # UTM10, NAD83 - Output coordinate system for Geotiff files
EPSGout = "EPSG:26911" # UTM11, NAD83 - Output coordinate system for Geotiff files

dirname = "C:\\GeoPDFSold\\UTM11_62K\\" # Location of input pdf files Also used for output directory
print(dirname)
p1=pyproj.Proj(init= EPSGin) # Define input projection
p2=pyproj.Proj(init= EPSGout) # Define output projection

list_of_files1 = glob.glob(dirname +'*.pdf') # create the list of PDF files


for file_name in list_of_files1:
os.rename(file_name, file_name.replace(" ", "_")) #replace any blanks in filenames with underscore character

list_of_files2 = glob.glob(dirname +'*.pdf') # create the list of renamed PDF files

for file_name in list_of_files2:

FIPDF = file_name
FOTIFF1 = FIPDF.replace('pdf', 'tif')
FOTIFF2 = FOTIFF1.replace('CA_', 'CA1_')
print(FIPDF)
print(FOTIFF1)
print(FOTIFF2)

# Export geoPDF to Geotiff at 300 dpi in original map projection coordinates (polyconic for USGS historic maps)

os.system('gdal_translate.exe -of GTiff --config GDAL_PDF_DPI 300 -co COMPRESS=JPEG ' + FIPDF + ' '+ FOTIFF1)

CornerLats = [0,0,0,0]
CornerLons = [0,0,0,0]
Cornerx = [0,0,0,0]
Cornery = [0,0,0,0]
gcp = ['','','','']
xstr = ['','','','']
ystr = ['','','','']
GdalInfo = subprocess.check_output('gdalinfo {}'.format(FOTIFF1),shell=True,universal_newlines=True)# Runs Gdalinfo on exported GeoTiff
GdalInfo = GdalInfo.splitlines() # Creates a line by line list.
GotUL, GotUR, GotLL, GotLR, GotSize, GotPixel, Proj, NeedReproj = False, False, False, False, False, False, False, True

for line in GdalInfo:
print(line)
if line.startswith("Size"):
size = line.split()
R = size[3]
size2 = size[2].split(',')
C = size2[0]
CornerRow = ['0', R, '0', R]
CornerCol = ['0', '0', C, C]
GotSize = True

if line.startswith("Pixel Size"):
pix1 = line.split('(')
pix2 = pix1[1].split(',')
pixsize = float(pix2[0])
halfpix = pixsize/2 # Adjustment to move coordinates to cell center from edge
GotPixel = True

if line.startswith("Upper Left"):
CornerLats[0], CornerLons[0] = GetLatLon(line)
Cornerx[0], Cornery[0] = pyproj.transform(p1,p2,CornerLons[0],CornerLats[0]) #Reproject edge coords in LL to Map proj
Cornerx[0] = Cornerx[0] - halfpix # Adjustment to pixel edge
Cornery[0] = Cornery[0] + halfpix
GotUL = True

if line.startswith("Lower Left"):
CornerLats[1], CornerLons[1] = GetLatLon(line)
Cornerx[1], Cornery[1] = pyproj.transform(p1,p2,CornerLons[1],CornerLats[1])
Cornerx[1] = Cornerx[1] - halfpix
Cornery[1] = Cornery[1] - halfpix
GotLL = True

if line.startswith("Upper Right"):
CornerLats[2], CornerLons[2] = GetLatLon(line)
Cornerx[2], Cornery[2] = pyproj.transform(p1,p2,CornerLons[2],CornerLats[2])
Cornerx[2] = Cornerx[2] + halfpix
Cornery[2] = Cornery[2] + halfpix
GotUR = True

if line.startswith("Lower Right"):
CornerLats[3], CornerLons[3] = GetLatLon(line)
Cornerx[3], Cornery[3] = pyproj.transform(p1,p2,CornerLons[3],CornerLats[3])
Cornerx[3] = Cornerx[3] + halfpix
Cornery[3] = Cornery[3] - halfpix
GotLR = True

if GotUL and GotUR and GotLL and GotLR and GotSize and GotPixel and NeedReproj:
xstr[0] = str(Cornerx[0])
xstr[1] = str(Cornerx[1])
xstr[2] = str(Cornerx[2])
xstr[3] = str(Cornerx[3])
ystr[0] = str(Cornery[0])
ystr[1] = str(Cornery[1])
ystr[2] = str(Cornery[2])
ystr[3] = str(Cornery[3])

gcp[0] = ' -gcp '+ CornerCol[0]+ ' ' + CornerRow[0]+ ' ' + xstr[0]+ ' ' + ystr[0]
gcp[1] = ' -gcp '+ CornerCol[1]+ ' ' + CornerRow[1]+ ' ' + xstr[1]+ ' ' + ystr[1]
gcp[2] = ' -gcp '+ CornerCol[2]+ ' ' + CornerRow[2]+ ' ' + xstr[2]+ ' ' + ystr[2]
gcp[3] = ' -gcp '+ CornerCol[3]+ ' ' + CornerRow[3]+ ' ' + xstr[3]+ ' ' + ystr[3]

# Reproject to new geotiff file using control points

gdalstr = 'gdal_translate.exe -of GTIFF -co COMPRESS=JPEG ' + FOTIFF1 + gcp[0] + gcp[1] + gcp[2] + gcp[3]+ ' -a_srs ' + EPSGout + ' '+ FOTIFF2
print(gdalstr)
os.system(gdalstr)
NeedReproj = False
Proj = True

if GotUL and GotUR and GotLL and GotLR and GotSize and GotPixel and Proj:
break
Re: Conversion of GeoPDFs to GeoTiffs posted by John Niles on Sep 18 2013 5:09PM
Can you explain these steps for someone with very little experience running python scripts? Please? The nightmare that is GeoPDFs needs to end..
Aerials posted by Chad Foster on Jul 8 2014 9:32AM
Is there a way to turn off or not export the aerial photography layer associated with the USGS GeoPDF's using the python script that was provided?

If you would like to post a comment, please login.

Contact Us | Legal | Privacy |