[GIS] Export GeoTIFF with color table from web service using gdal_translate

colortablegdalgdal-translategdalinfoweb service

The gdal_translate program has an option to define an XML file with the necessary information to download an image using various web map server specifications. I am trying to download a file that should have a specific color table palette with 256 colors associated with it and one band of 8-bit (byte) values. But when I run gdal_translate on an XML file and download the file, the file only appears to have 3-band RGB values with no color table (when I look at the image attributes using gdalinfo).

For example, I have the following XML file I'm using to download an image:

<GDAL_WMS>
     <Service name="AGS">
         <ServerUrl>https://raster.nationalmap.gov/arcgis/rest/services/LandCover/USGS_EROS_LandCover_NLCD/MapServer</ServerUrl>
         <ImageFormat>tiff</ImageFormat>
         <Layers>show:6</Layers>
         <BBoxOrder>xyXY</BBoxOrder>
         <SRS>26917</SRS>
     </Service>
     <DataWindow>
         <UpperLeftX>720586.0306923158900</UpperLeftX>
         <UpperLeftY>3962270.5642631231000</UpperLeftY>
         <LowerRightX>723891.5076759960500</LowerRightX>
         <LowerRightY>3960158.2215603264000</LowerRightY>
         <SizeX>164</SizeX>
         <SizeY>105</SizeY>
     </DataWindow>
     <UnsafeSSL>true</UnsafeSSL>
</GDAL_WMS>

I save this file as "nlcd.xml". Then I run the following command:

gdal_translate -of GTiff "F:\temp\nlcd.xml" "f:\temp\r.nlcd.tif"

The file is downloaded and I am able to view the image using various methods. However, when I run gdalinfo on the image, there are 3 bands with no color table defined:

gdalinfo f:\temp\r.nlcd.tif

Driver: GTiff/GeoTIFF
Files: f:\temp\r.nlcd.tif
Size is 164, 105
Coordinate System is:
PROJCS["NAD83 / UTM zone 17N",
    GEOGCS["NAD83",
        DATUM["North_American_Datum_1983",
            SPHEROID["GRS 1980",6378137,298.257222101,
                AUTHORITY["EPSG","7019"]],
            TOWGS84[0,0,0,0,0,0,0],
            AUTHORITY["EPSG","6269"]],
        PRIMEM["Greenwich",0,
            AUTHORITY["EPSG","8901"]],
        UNIT["degree",0.0174532925199433,
            AUTHORITY["EPSG","9122"]],
        AUTHORITY["EPSG","4269"]],
    PROJECTION["Transverse_Mercator"],
    PARAMETER["latitude_of_origin",0],
    PARAMETER["central_meridian",-81],
    PARAMETER["scale_factor",0.9996],
    PARAMETER["false_easting",500000],
    PARAMETER["false_northing",0],
    UNIT["metre",1,
        AUTHORITY["EPSG","9001"]],
    AXIS["Easting",EAST],
    AXIS["Northing",NORTH],
    AUTHORITY["EPSG","26917"]]
Origin = (720586.030692315890000,3962270.564263123100000)
Pixel Size = (20.155347461464373,-20.117549550444597)
Metadata:
  AREA_OR_POINT=Area
Image Structure Metadata:
  INTERLEAVE=PIXEL
Corner Coordinates:
Upper Left  (  720586.031, 3962270.564) ( 78d33'34.26"W, 35d46'47.19"N)
Lower Left  (  720586.031, 3960158.222) ( 78d33'36.36"W, 35d45'38.69"N)
Upper Right (  723891.508, 3962270.564) ( 78d31'22.72"W, 35d46'44.50"N)
Lower Right (  723891.508, 3960158.222) ( 78d31'24.85"W, 35d45'36.00"N)
Center      (  722238.769, 3961214.393) ( 78d32'29.55"W, 35d46'11.60"N)
Band 1 Block=164x16 Type=Byte, ColorInterp=Red
Band 2 Block=164x16 Type=Byte, ColorInterp=Green
Band 3 Block=164x16 Type=Byte, ColorInterp=Blue

I expected to see one band with a color table defined-something like the following on a file I previously downloaded using another method:

gdalinfo "F:\temp\nlcd2006.tif"

Driver: GTiff/GeoTIFF
Files: F:\temp\nlcd2006.tif
Size is 1296, 1598
Coordinate System is:
PROJCS["WGS 84 / UTM zone 10N",
    GEOGCS["WGS 84",
        DATUM["WGS_1984",
            SPHEROID["WGS 84",6378137,298.2572235604902,
                AUTHORITY["EPSG","7030"]],
            AUTHORITY["EPSG","6326"]],
        PRIMEM["Greenwich",0],
        UNIT["degree",0.0174532925199433],
        AUTHORITY["EPSG","4326"]],
    PROJECTION["Transverse_Mercator"],
    PARAMETER["latitude_of_origin",0],
    PARAMETER["central_meridian",-123],
    PARAMETER["scale_factor",0.9996],
    PARAMETER["false_easting",500000],
    PARAMETER["false_northing",0],
    UNIT["metre",1,
        AUTHORITY["EPSG","9001"]],
    AUTHORITY["EPSG","32610"]]
Origin = (464430.000000000000000,4363320.000000000000000)
Pixel Size = (30.000000000000000,-30.012515644555695)
Metadata:
  AREA_OR_POINT=Area
Image Structure Metadata:
  COMPRESSION=PACKBITS
  INTERLEAVE=BAND
Corner Coordinates:
Upper Left  (  464430.000, 4363320.000) (123d24'47.61"W, 39d25' 7.21"N)
Lower Left  (  464430.000, 4315360.000) (123d24'38.52"W, 38d59'11.44"N)
Upper Right (  503310.000, 4363320.000) (122d57'41.57"W, 39d25' 9.83"N)
Lower Right (  503310.000, 4315360.000) (122d57'42.41"W, 38d59'14.02"N)
Center      (  483870.000, 4339340.000) (123d11'12.52"W, 39d12'11.43"N)
Band 1 Block=1296x1 Type=Byte, ColorInterp=Palette
  Color Table (RGB with 256 entries)
    0: 0,0,0,255
    1: 0,250,0,255
    2: 0,0,0,255
    3: 0,0,0,255
    4: 0,0,0,255
    5: 0,0,0,255
    6: 0,0,0,255
    7: 0,0,0,255
    8: 0,0,0,255
    9: 0,0,0,255
   10: 0,0,0,255
   11: 71,107,161,255
   12: 209,222,250,255
   13: 0,0,0,255
   14: 0,0,0,255
   15: 0,0,0,255
   16: 0,0,0,255
   17: 0,0,0,255
   18: 0,0,0,255
   19: 0,0,0,255
   20: 0,0,0,255
   21: 222,201,201,255
   22: 217,148,130,255
   23: 237,0,0,255
   24: 171,0,0,255
   25: 0,0,0,255
   26: 0,0,0,255
   27: 0,0,0,255
   28: 0,0,0,255
   29: 0,0,0,255
   30: 0,0,0,255
   31: 179,173,163,255
   32: 250,250,250,255
...

My question is: Is there a way to export a GeoTIFF with a single band and a color palette from a web service using gdal_translate instead of exporting the RGB values in 3 separate bands?

Best Answer

You can now accomplish this with rasterio. From the example at: https://rasterio.readthedocs.io/en/latest/topics/color.html

import rasterio

with rasterio.Env():

    with rasterio.open('tests/data/shade.tif') as src:
        shade = src.read(1)
        meta = src.meta

    with rasterio.open('/tmp/colormap.tif', 'w', **meta) as dst:
        dst.write(shade, indexes=1)
        dst.write_colormap(
            1, {
                0: (255, 0, 0, 255),
              255: (0, 0, 255, 255) })
        cmap = dst.colormap(1)

where you would replace the example's dictionary -- which only has entries for indexes 0 and 255 -- with your own colormap dictionary.

I have found that you can supply a dictionary with 3-member tuples (R, G, B) and rasterio will give the transparency ("A") channel a value of 255.

Related Question