My Objective: I would like to use GDAL to convert a GeoPDF. I want the vector layers as shp files and the raster layers as tif files. I want to do this in a programmatic way.

Edit: In reality, I want to do this with many geospatial PDFs. I'm prototyping the workflow using Python, but it will probably end up being C++. (End Edit)

The Problem: Naturally, the command to convert a vector layer differs from a raster layer. And I don't know (again in a programmatic way) which layers are vector and which are raster.

What I've Tried: First, here is my sample data https://www.terragotech.com/images/pdf/webmap_urbansample.pdf.

gdalinfo webmap_urbansample.pdf -mdd LAYERS

gives the layer names:

Metadata (LAYERS):                           

I know to look at the data which are vector and which are raster, but I don't know how to parse this information to know whether to use ogr2ogr or gdal_translate to do the conversion.

Then I thought I could use ogrinfo and just diff all the layers to deduce which ones are raster, but ogrinfo gives me:

1: Cadastral Boundaries (Polygon)
2: Water Lines (Line String)
3: Sewerage Lines (Line String)
4: Sewerage Jump-Ups (Line String)
5: Roads
6: Water Points (Point)
7: Sewerage Pump Stations (Point)
8: Sewerage Man Holes (Point)
9: BPS - Buildings (Polygon)
10: BPS - Facilities (Polygon)
11: BPS - Water Sources (Point)

So there's not a one-to-one correspondence with the way these are output.

Does anyone know how to have gdal print the GeoPDF layers and indicate which are raster vs. vector?

  • Is there just one raster layer and the rest is vector? I think ogrinfo only lists those that it supports. Jul 30, 2015 at 14:08
  • @bugmenot123 In this data set, yes. There is only one raster layer. If you're getting at the fact that ogrinfo won't list raster layers, then yes, that's what I saw too. I thought I might be able to leverage that fact to tell which layers were raster (because they won't be listed by ogrinfo). By "not a one-to-one comparison", I meant that the layer text is different, e.g., spaces vs underscores and the Layers.* syntax.
    – user55937
    Jul 30, 2015 at 14:21

2 Answers 2


This is not really the answer, but something I've been using as a workaround.

The script compares the text of the layers between gdalinfo and ogrinfo to infer which ones are raster. This approach isn't definitive though, so I imagine it could be wrong from time to time. Even in this example, LAYER_00_NAME=Layers isn't really a raster layer.

def GetRasterVectorLayers(filename):
    from osgeo import gdal
    from osgeo import ogr
    from difflib import SequenceMatcher

    # get vector layers with ogr
    data_ogr = ogr.Open(filename)
    if data_ogr:
        vector_layers = [ data_ogr.GetLayer(i).GetName() for i in range(data_ogr.GetLayerCount()) ]
        vector_layers = []

    # get all layers with gdal
    data_gdal = gdal.Open( filename, gdal.GA_ReadOnly )
    layers = data_gdal.GetMetadata_List("LAYERS")
    # peel off label, e.g., LAYER_00_NAME=Layers
    layers = [ layer.split('=')[-1] for layer in layers ]

    # match the text to deduce which layers are vector or raster
    matched_layers = []
    for vector_layer in vector_layers:
        layer_matches = []
        for layer in layers:
            layer_matches.append( [SequenceMatcher(None, vector_layer, layer).ratio(), layer] )
        best_match = layer_matches[-1][1] # -1 gets the highest score, 1 gets the gdalinfo layer name
        matched_layers.append( [vector_layer,best_match] ) 

    layers_vector = [ match[1] for match in matched_layers ]
    layers_raster = [ layer for layer in layers if layer not in layers_vector ]
    return [layers_raster, layers_vector]

layers_raster, layers_vector = GetRasterVectorLayers('webmap_urbansample.pdf')

# ['Layers', 'Layers.Raster_Images']
# ['Layers.Cadastral_Boundaries', 'Layers.Water_Lines', 'Layers.Sewerage_Lines', 'Layers.Sewerage_Jump-Ups', 'Layers.Roads', 'Layers.Water_Points', 'Layers.Sewerage_Pump_Stations', 'Layers.Sewerage_Man_Holes', 'Layers.BPS_-_Buildings', 'Layers.BPS_-_Facilities', 'Layers.BPS_-_Water_Sources']
  • There's nothing wrong with answering your own question, providing it actually provides an answer (which you do). The fact that you are already working with the Python API is important though, when I first read your question I expected you wanted something simpler (like a shell script). I'd add that to your question, as it opens more options. Jul 31, 2015 at 17:19
  • Thanks - you're right, I should have included that information. I edited the question.
    – user55937
    Jul 31, 2015 at 17:41

I'm afraid it is up to the PDF creator how to name and number the raster and vector layers. New USGS Topo sheets are combined GeoPDF, and a sample file (NM_Santa_Fe_20131108_TM_geo.pdf) has this output from gdalinfo:


The layers are ordered hierarchical, with sublayers that have one or several points in the name. Layer 00, 02, 06, 14, 18, 19, 23 and 27 are meta layers, a combination of the following sublayers.

Ogrinfo reports:

1: Map_Collar
2: Map_Collar_Map_Elements
3: Map_Frame_Projection_and_Grids
4: Map_Frame_Geographic_Names (Multi Line String)
5: Map_Frame_Structures
6: Map_Frame_Transportation_Road_Names_and_Shields
7: Map_Frame_Transportation_Road_Features
8: Map_Frame_PLSS
9: Map_Frame_Hydrography
10: Map_Frame_Terrain_Contours
11: Map_Frame_Woodland
12: Map_Frame_Boundaries_Federal_Administered_Lands_Forest_Service

These are really only vector layers, but the substructure naming is lost, and different from your example the geometry type is only added in one layer. Both lists have no blanks in names (except the one with geometry). Meta layers and empty layers are omitted in the vector layer list. The numbering of the layers is not consistent (but not inverted as in your example).

If you want to extract all vector layers, you can use

ogr2ogr -f sqlite out.sqlite in.pdf

If you try that with the GDAL raster commands, it will try to rasterize your vector data, which might take some time. So you have to include the raster layer name explicitely for every layer:

gdalwarp -co "TILED=YES" -co "TFW=YES" rumney_farmforest_geopdf.pdf rumtif01.tif -overwrite  --config GDAL_PDF_LAYERS "Graphic_Outline_(display_only)"
  • So I know how to extract the vector and raster layers. My question was how to know which layers are vector and which are raster so that I can extract each individual layer in an automated way. You point out that the substructure naming is lost, which I also point out in my question. Also, the difference in strings between the two calls (underscores vs spaces). I presume that gdalinfo reports the name of some object whereas ogrinfo gives an attribute value. Is there no way to make this uniform, e.g., through a certain api call? I almost take your answer to mean there is no good answer.
    – user55937
    Jul 31, 2015 at 17:26
  • The underscore vs blank does not apply to my example. I guess the GeoPDF driver still needs some developer attention, but there seem to be more important bugs to fix. The automatisation works for vector export into the spaitaöie database, while the raster layers need some handwork.
    – AndreJ
    Jul 31, 2015 at 19:11

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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