I am working with Postgres 9.6, PostGIS 2.3 and GDAL 1.11.5. I would like to output the union of some polygons as a single PNG (or other image) file, with the polygons in black on a white background. (Not tiles – I just want an image.)
I know how to query the union of the polygons:
SELECT ST_Union(geom) FROM holdings WHERE town='Macclesfield';
But I don't know how to convert this to a PNG file. I've tried:
SELECT ST_AsPNG(ST_Union(geom)) FROM holdings WHERE town='Macclesfield';
But this errors:
ERROR: function st_aspng(geometry) does not exist
LINE 1: select ST_AsPNG(st_union(geom)) from holdings where town='Ma...
HINT: No function matches the given name and argument types. You might need to add explicit type casts.
I think maybe I need to convert the union into a raster layer first?
Best Answer
The key to this is to recognize that ST_AsPNG returns a bytea, ie a byte array, representing a png. So, you need to somehow convert those bytes to a file on the file system. There are a couple of ways of doing this as shown in the docs.
The oid approach, as outlined by @Stefan, works, but requires psql and is a bit obscure, in my opinion.
The other approach, is to use Pythonu (ie, a Python stored procecure) to convert the bytea to an actual png file.
After which you can do:
which is very clean.
As a note of warning, the Python stored procedure langauge is called plpythonu -- the final u stands for untrusted. As it states in the docs:
so you will want to make sure you use it in an isolated environment, if you go this route.
EDIT: As has been pointed out by @jpmc26, the plpythonu approach will only work server-side, and you will need to install plpythonu (which is not in the standard package), both of which means that you will need to have admin/super user privileges on the server, both of which are reasonable observations. I would argue, however, that if you don't have access to the server, once you have understood that ST_AsPNG returns a byte array, it is would be reasonably straight forward to write something client-side to consume the return value -- which could even be plain vanilla python, via psycopg2 (or anything other programming language that can call a Postgres function and write the resulting byte stream to disk locally).
For anyone wanting to go this route, in Ubuntu/Debian, you need to install the plpythonu extension, and then create the extension, which can be done with (change for your version).
followed by
either within psql, pgadmin, or from a shell prompt of some description.