Chapter 9. Gestion des données raster, requêtes et applications

Table of Contents
9.1. Chargement et création de rasters
9.1.1. Utilisation de raster2pgsql pour charger des rasters
9.1.2. Création de rasters à l'aide des fonctions raster de PostGIS
9.1.3. Utilisation de rasters "out db" stockés sur le cloud
9.2. Catalogues Raster
9.2.1. Catalogue des colonnes raster
9.2.2. Aperçu des données raster
9.3. Créer des applications personnalisées avec PostGIS Raster
9.3.1. Exemple de sortie PHP utilisant ST_AsPNG avec d'autres fonctions raster
9.3.2. Exemple ASP.NET C# Sortie utilisant ST_AsPNG en conjonction avec d'autres fonctions raster
9.3.3. Application console Java qui produit une requête raster sous forme de fichier image
9.3.4. Utiliser PLPython pour extraire des images via SQL
9.3.5. Sortie de données raster avec PSQL

9.1. Chargement et création de rasters

Dans la plupart des cas, vous créerez des rasters PostGIS en chargeant des fichiers raster existants à l'aide du chargeur de rasters raster2pgsql.

9.1.1. Utilisation de raster2pgsql pour charger des rasters

Le raster2pgsql est un exécutable de chargement de données raster qui charge les formats de données matricielles pris en charge par GDAL en SQL adapté au chargement dans une table raster PostGIS. Il est capable de charger des dossiers de fichiers raster ainsi que de créer des aperçus de rasters.

Comme raster2pgsql est le plus souvent compilé dans le cadre de PostGIS (à moins que vous ne compiliez votre propre bibliothèque GDAL), les types de données raster pris en charge par l'exécutable seront les mêmes que ceux compilés dans la bibliothèque de dépendance GDAL. Pour obtenir une liste des types de données raster que votre raster2pgsql supporte, utilisez l'argument -G.

[Note]

Lors de la création de vues d'ensemble d'un facteur spécifique à partir d'un ensemble de rasters alignés, il est possible que les vues d'ensemble ne soient pas alignées. Consultez http://trac.osgeo.org/postgis/ticket/1764 pour un exemple où les vues d'ensemble ne sont pas alignées.

9.1.1.1. Exemple d'utilisation

Une session d'exemple utilisant le chargeur pour créer un fichier d'entrée et le charger en morceaux de 100 x 100 tuiles peut ressembler à ceci :

# -s use srid 4326
# -I create spatial index
# -C use standard raster constraints
# -M vacuum analyze after load
# *.tif load all these files
# -F include a filename column in the raster table
# -t tile the output 100x100
# public.demelevation load into this table
raster2pgsql -s 4326 -I -C -M -F -t 100x100 *.tif public.demelevation 
> elev.sql

# -d connect to this database
# -f read this file after connecting
psql -d gisdb -f elev.sql
[Note]

Si vous ne spécifiez pas le schéma dans le nom de la table cible, la table sera créée dans le schéma par défaut de la base de données ou de l'utilisateur avec lequel vous vous connectez.

Une conversion et un téléchargement peuvent être effectués en une seule étape à l'aide de commandes UNIX :

raster2pgsql -s 4326 -I -C -M *.tif -F -t 100x100 public.demelevation | psql -d gisdb

Charger les rasters Massachusetts state plane meters aerial tiles dans un schéma appelé aerial et créer une vue complète, des tables d'ensemble à 2 et 4 niveaux, utiliser le mode copy pour l'insertion (pas de fichier intermédiaire juste directement dans la base de données), et -e ne pas forcer tout dans une transaction (bien si vous voulez voir les données dans les tables tout de suite sans attendre). Décomposer les rasters en tuiles de 128x128 pixels et appliquer les contraintes des rasters. Utilisez le mode copy au lieu de l'insertion de table. (-F) Inclure un champ appelé filename pour contenir le nom du fichier à partir duquel les tuiles ont été découpées.

raster2pgsql -I -C -e -Y -F -s 26986 -t 128x128  -l 2,4 bostonaerials2008/*.jpg aerials.boston | psql -U postgres -d gisdb -h localhost -p 5432
--get a list of raster types supported:
raster2pgsql -G

La commande -G génère une liste du type

Available GDAL raster formats:
  Virtual Raster
  GeoTIFF
  National Imagery Transmission Format
  Raster Product Format TOC format
  ECRG TOC format
  Erdas Imagine Images (.img)
  CEOS SAR Image
  CEOS Image
  ...
  Arc/Info Export E00 GRID
  ZMap Plus Grid
  NOAA NGS Geoid Height Grids

9.1.1.2. options raster2pgsql

-?

Affiche l'écran d'aide. L'aide s'affichera également si vous ne fournissez aucun argument.

-G

Affiche les formats raster pris en charge.

(c|a|d|p) Ces options s'excluent mutuellement :

-c

Créer une nouvelle table et la remplir de données raster, c'est le mode par défaut

-a

Ajouter des données raster à une table existante.

-d

Supprimer la table, en créer une nouvelle et l'alimenter avec des données raster

-p

En mode préparation, ne créez que la table.

Traitement des données raster : Application de contraintes pour un enregistrement correct dans les catalogues de données raster

-C

Appliquer les contraintes du raster -- srid, pixelsize etc. pour s'assurer que le raster est correctement enregistré dans la vue raster_columns.

-x

Désactive la contrainte d'étendue maximale. Ne s'applique que si l'option -C est également utilisée.

-r

Définit les contraintes (espacement unique et tuiles de couverture) pour le blocage régulier. Ne s'applique que si l'option -C est également utilisée.

Traitement des données raster : Paramètres facultatifs utilisés pour manipuler le jeu de données raster d'entrée

-s <SRID>

Attribue au raster de sortie le SRID spécifié. S'il n'est pas fourni ou s'il est égal à zéro, les métadonnées du raster seront vérifiées pour déterminer un SRID approprié.

-b BAND

Indice (basé sur 1) de la bande à extraire du raster. Pour plus d'un indice de bande, séparez-les par une virgule (,). Si rien n'est spécifié, toutes les bandes de l'image seront extraites.

-t TILE_SIZE

Découpe le raster en tuiles qui seront insérées une par une dans la table. TILE_SIZE est exprimée en LARGEURxHAUTEUR ou fixée à la valeur "auto" pour permettre au chargeur de calculer une taille de tuile appropriée en utilisant le premier raster et en l'appliquant à tous les rasters.

-P

Les tuiles les plus à droite et les plus en bas sont remplacées pour garantir que toutes les tuiles ont la même largeur et la même hauteur.

-R, --register

Enregistrer le raster en tant que raster de système de fichiers (out-db).

Seules les métadonnées du raster et le chemin d'accès au raster sont stockés dans la base de données (pas les pixels).

-l OVERVIEW_FACTOR

Créer un aperçu du raster. Pour plus d'un facteur, séparez-les par une virgule (,). Le nom de la table de synthèse suit le modèle o_facteur de synthèse_table, où facteur de synthèse est un espace réservé pour le facteur de synthèse numérique et table est remplacé par le nom de la table de base. La vue d'ensemble créée est stockée dans la base de données et n'est pas affectée par -R. Notez que le fichier sql généré contiendra à la fois la table principale et les tables de synthèse.

-N NODATA

Valeur NODATA à utiliser pour les bandes sans valeur NODATA.

Paramètres facultatifs utilisés pour manipuler les objets de la base de données

-f COLUMN

Spécifier le nom de la colonne raster de destination, la valeur par défaut étant "rast"

-F

Ajouter une colonne avec le nom du fichier

-n COLONNE

Spécifier le nom de la colonne "nom de fichier". Implique -F.

-q

Mettre les identifiants PostgreSQL entre guillemets.

-I

Créer un index GiST sur la colonne raster.

-M

Vacuum analyze la table raster.

-k

Conserve les tuiles vides et saute les vérifications des valeurs NODATA pour chaque bande de données matricielles. Vous gagnez du temps en vérifiant, mais vous risquez de vous retrouver avec beaucoup plus de lignes inutiles dans votre base de données et ces lignes inutiles ne sont pas marquées comme des tuiles vides.

-T tablespace

Spécifier le tablespace pour la nouvelle table. Notez que les index (y compris la clé primaire) utiliseront toujours le tablespace par défaut à moins que l'option -X ne soit également utilisée.

-X tablespace

Spécifier le tablespace pour le nouvel index de la table. Ceci s'applique à la clé primaire et à l'index spatial si l'option -I est utilisée.

-Y max_rows_per_copy=50

Utiliser les instructions de copie au lieu des instructions d'insertion. Spécifier optionnellement max_rows_per_copy ; par défaut 50 si non spécifié.

-e

Exécutez chaque déclaration individuellement, n'utilisez pas de transaction.

-E ENDIAN

Contrôle l'ordre des octets de la sortie binaire générée du raster ; spécifier 0 pour XDR et 1 pour NDR (par défaut) ; seule la sortie NDR est prise en charge actuellement

-V version

Indique la version du format de sortie. La valeur par défaut est 0. Seule la valeur 0 est prise en charge pour l'instant.

9.1.2. Création de rasters à l'aide des fonctions raster de PostGIS

Il arrive souvent que vous souhaitiez créer des rasters et des tables de rasters directement dans la base de données. Il existe une multitude de fonctions pour ce faire. Les étapes générales à suivre.

  1. Créer une table avec une colonne raster pour contenir les nouveaux enregistrements raster, ce qui peut être fait avec :

    CREATE TABLE myrasters(rid serial primary key, rast raster);
  2. Il existe de nombreuses fonctions pour vous aider à atteindre cet objectif. Si vous créez des rasters qui ne sont pas des dérivés d'autres rasters, vous devrez commencer par ST_MakeEmptyRaster, suivi de ST_AddBand

    Vous pouvez également créer des rasters à partir de géométries. Pour ce faire, vous devrez utiliser ST_AsRaster éventuellement accompagné d'autres fonctions telles que ST_Union ou ST_MapAlgebraFct ou n'importe quelle autre fonction d'algèbre de carte.

    Il existe encore bien d'autres options pour créer de nouvelles tables raster à partir de tables existantes. Par exemple, vous pouvez créer une table raster dans une projection différente de celle d'une table existante en utilisant ST_Transform

  3. Une fois que vous avez rempli votre table initialement, vous devez créer un index spatial sur la colonne des données raster avec quelque chose comme :

    CREATE INDEX myrasters_rast_st_convexhull_idx ON myrasters USING gist( ST_ConvexHull(rast) );

    Notez l'utilisation de ST_ConvexHull puisque la plupart des opérateurs de données raster sont basés sur l'enveloppe convexe des données raster.

    [Note]

    Les versions antérieures à la version 2.0 de PostGIS raster étaient basées sur l'enveloppe plutôt que sur l'enveloppe convexe. Pour que les index spatiaux fonctionnent correctement, vous devez les supprimer et les remplacer par des index basés sur l'enveloppe convexe.

  4. Appliquer des contraintes raster en utilisant AddRasterConstraints

9.1.3. Utilisation de rasters "out db" stockés sur le cloud

L'outil raster2pgsql utilise GDAL pour accéder aux données raster et peut tirer parti d'une fonctionnalité clé de GDAL : la possibilité de lire des données raster qui sont stockées à distance dans des "magasins d'objets" en nuage (par exemple AWS S3, Google Cloud Storage).

L'utilisation efficace des rasters stockés dans le cloud nécessite l'utilisation d'un format "optimisé pour le cloud". Le plus connu et le plus largement utilisé est le format "cloud optimized GeoTIFF". L'utilisation d'un format non optimisé pour le cloud, comme un JPEG ou un TIFF non structuré, se traduira par des performances très médiocres, car le système devra télécharger l'intégralité du raster chaque fois qu'il devra accéder à un sous-ensemble.

Tout d'abord, chargez votre raster dans le service de stockage cloud de votre choix. Une fois qu'il est chargé, vous aurez un URI pour y accéder, soit un URI "http", soit parfois un URI spécifique au service (par exemple, "s3://bucket/object") Pour accéder aux buckets non publics, vous devrez fournir des options de configuration GDAL pour authentifier votre connexion. Notez que cette commande lit à partir du raster (stocké dans le cloud) et écrit dans la base de données.

AWS_ACCESS_KEY_ID=xxxxxxxxxxxxxxxxxxxx \
AWS_SECRET_ACCESS_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx \
raster2pgsql \
  -s 990000 \
  -t 256x256 \
  -I \
  -R \
  /vsis3/your.bucket.com/your_file.tif \
  your_table \
  | psql your_db

Une fois la table chargée, vous devez donner à la base de données la permission de lire les rasters distants, en définissant deux permissions, postgis.enable_outdb_rasters et postgis.gdal_enabled_drivers.

SET postgis.enable_outdb_rasters = true;
SET postgis.gdal_enabled_drivers TO 'ENABLE_ALL';
    

Pour que les changements soient durables, définissez-les directement dans votre base de données. Vous devrez vous reconnecter pour bénéficier des nouveaux paramètres.

ALTER DATABASE your_db SET postgis.enable_outdb_rasters = true;
ALTER DATABASE your_db SET postgis.gdal_enabled_drivers TO 'ENABLE_ALL';
    

Pour les rasters non publics, il se peut que vous deviez fournir des clés d'accès pour lire les rasters stockés dans le cloud. Les mêmes clés que vous avez utilisées pour écrire l'appel raster2pgsql peuvent être définies pour être utilisées à l'intérieur de la base de données, avec la configuration postgis.gdal_vsi_options. Notez que plusieurs options peuvent être définies en séparant les paires key=value par des espaces.

SET postgis.gdal_vsi_options = 'AWS_ACCESS_KEY_ID=xxxxxxxxxxxxxxxxxxxx
AWS_SECRET_ACCESS_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';

Une fois les données chargées et les autorisations définies, vous pouvez interagir avec la table raster comme avec n'importe quelle autre table raster, en utilisant les mêmes fonctions. La base de données se chargera de tous les mécanismes de connexion aux données stockées dans le cloud lorsqu'elle aura besoin de lire les données des pixels.

9.2. Catalogues Raster

Deux vues de catalogue raster sont fournies avec PostGIS. Ces deux vues utilisent des informations intégrées dans les contraintes des tables raster. Par conséquent, les vues de catalogue sont toujours cohérentes avec les données raster des tables puisque les contraintes sont appliquées.

  1. raster_columns cette vue répertorie toutes les colonnes des tables raster de votre base de données.

  2. raster_overviews cette vue répertorie toutes les colonnes des tables raster de votre base de données qui servent d'aperçu pour une table plus finement structurée. Les tables de ce type sont générées lorsque vous utilisez le commutateur -l pendant le chargement.

9.2.1. Catalogue des colonnes raster

Le raster_columns est un catalogue de toutes les colonnes des tables raster de votre base de données qui sont de type raster. Il s'agit d'une vue qui utilise les contraintes des tables afin que les informations soient toujours cohérentes, même si vous restaurez une table raster à partir d'une sauvegarde d'une autre base de données. Les colonnes suivantes existent dans le catalogue raster_columns.

Si vous n'avez pas créé vos tables avec le chargeur ou si vous avez oublié de spécifier l'option -C pendant le chargement, vous pouvez appliquer les contraintes après coup en utilisant AddRasterConstraints pour que le catalogue raster_columns enregistre les informations communes sur vos tuiles raster.

  • r_table_catalog La base de données dans laquelle se trouve la table. La lecture se fera toujours dans la base de données actuelle.

  • r_table_schema Schéma de la base de données auquel appartient la table raster.

  • r_table_name table raster

  • r_raster_column la colonne de la table r_table_name qui est de type raster. Rien dans PostGIS ne vous empêche d'avoir plusieurs colonnes raster par table. Il est donc possible d'avoir une table raster listée plusieurs fois avec une colonne raster différente pour chacune d'entre elles.

  • srid L'identifiant de référence spatiale du raster. Il doit s'agir d'une entrée dans le fichier Section 4.5, “Systèmes de référence spatiale”.

  • scale_x L'échelle entre les coordonnées spatiales géométriques et le pixel. Elle n'est disponible que si toutes les tuiles de la colonne raster ont la même scale_x et que cette contrainte est appliquée. Se référer à ST_ScaleX pour plus de détails.

  • scale_y L'échelle entre les coordonnées spatiales géométriques et le pixel. Elle n'est disponible que si toutes les tuiles de la colonne matricielle ont la même scale_y et que la contrainte scale_y est appliquée. Voir ST_ScaleY pour plus de détails.

  • blocksize_x La largeur (nombre de pixels) de chaque tuile raster. Pour plus de détails, voir ST_Width.

  • blocksize_y La largeur (nombre de pixels vers le bas) de chaque tuile raster. Voir ST_Height pour plus de détails.

  • same_alignment Un booléen qui est vrai si toutes les tuiles raster ont le même alignement . Pour plus de détails, voir ST_SameAlignment.

  • regular_blocking Si la colonne de données raster est soumise aux contraintes d'unicité spatiale et de couverture des tuiles, la valeur sera TRUE. Dans le cas contraire, la valeur sera FALSE.

  • num_bands Le nombre de bandes dans chaque tuile de votre jeu de données raster. Il s'agit de la même information que celle fournie par ST_NumBands

  • pixel_types Un tableau définissant le type de pixel pour chaque bande. Le nombre d'éléments de ce tableau est identique au nombre de bandes. Les types de pixels sont l'un des suivants, définis dans ST_BandPixelType.

  • nodata_values Un tableau de nombres en double précision indiquant la nodata_value pour chaque bande. Le nombre d'éléments de ce tableau est égal au nombre de bandes. Ces nombres définissent la valeur du pixel pour chaque bande qui doit être ignorée pour la plupart des opérations. Il s'agit d'informations similaires à celles fournies par ST_BandNoDataValue.

  • out_db Un tableau d'indicateurs booléens indiquant si les données des bandes raster sont conservées en dehors de la base de données. Le nombre d'éléments de ce tableau est égal au nombre de bandes.

  • extent Il s'agit de l'étendue de toutes les lignes de votre jeu de données raster. Si vous prévoyez de charger d'autres données qui modifieront l'étendue de l'ensemble, vous devrez exécuter la fonction DropRasterConstraints avant le chargement, puis réappliquer les contraintes avec AddRasterConstraints après le chargement.

  • spatial_index Un booléen qui est vrai si la colonne raster a un index spatial.

9.2.2. Aperçu des données raster

raster_overviews catalogue des informations sur les colonnes des tables raster utilisées pour les aperçus et des informations supplémentaires à leur sujet qu'il est utile de connaître lors de l'utilisation des aperçus. Les tableaux de synthèse sont catalogués à la fois dans raster_columns et raster_overviews parce qu'il s'agit d'images raster à part entière, mais aussi parce qu'elles servent de caricature à plus faible résolution d'un tableau à plus haute résolution. Elles sont générées en même temps que la table raster principale lorsque vous utilisez le commutateur -l dans le chargement des données raster ou peuvent être générées manuellement en utilisant AddOverviewConstraints.

Les tableaux d'aperçus contiennent les mêmes contraintes que les autres tableaux raster, ainsi que des contraintes supplémentaires spécifiques aux aperçus.

[Note]

Les informations contenues dans raster_overviews ne font pas double emploi avec les informations contenues dans raster_columns. Si vous avez besoin des informations sur un tableau de synthèse présentes dans raster_columns, vous pouvez joindre les raster_overviews et raster_columns pour obtenir l'ensemble des informations dont vous avez besoin.

Les deux principales raisons pour lesquelles les aperçus sont nécessaires sont les suivantes :

  1. Représentation à basse résolution des tables centrales, couramment utilisée pour l'agrandissement rapide des cartes.

  2. Les calculs y sont généralement plus rapides que sur leurs homologues à plus haute résolution, car il y a moins d'enregistrements et chaque pixel couvre un plus grand territoire. Bien que les calculs ne soient pas aussi précis que les tableaux à haute résolution qu'ils supportent, ils peuvent être suffisants pour de nombreux calculs empiriques.

Le catalogue raster_overviews contient les colonnes d'information suivantes.

  • o_table_catalog La base de données dans laquelle se trouve l'aperçu. Il s'agit toujours de la base de données actuelle.

  • o_table_schema Schéma de la base de données auquel appartient l'aperçu de la table raster.

  • o_table_name nom de la table d'aperçu du raster

  • o_raster_column la colonne raster dans le tableau de synthèse.

  • r_table_catalog La base de données dans laquelle se trouve la table raster pour laquelle cette vue d'ensemble est utilisée. Il s'agit toujours de la base de données actuelle.

  • r_table_schema Schéma de la base de données auquel appartient la table raster à laquelle ce service de vue d'ensemble est associé.

  • r_table_name table raster que cet aperçu dessert.

  • r_raster_column la colonne raster que cette colonne d'aperçu dessert.

  • overview_factor - il s'agit du niveau pyramidal de l'aperçu. Plus le nombre est élevé, plus la résolution du tableau est faible. raster2pgsql, s'il reçoit un dossier d'images, calculera la vue d'ensemble de chaque fichier image et le chargera séparément. Le niveau 1 est supposé être le fichier original. Au niveau 2, chaque tuile représente 4 de l'original. Par exemple, si vous avez un dossier de fichiers images de 5000x5000 pixels que vous avez choisi de diviser en 125x125, pour chaque fichier image votre table de base aura (5000*5000)/(125*125) enregistrements = 1600, votre table (l=2) o_2 aura un plafond(1600/Power(2,2)) = 400 lignes, votre (l=3) o_3 aura un plafond(1600/Power(2,3) ) = 200 lignes. Si vos pixels ne sont pas divisibles par la taille de vos tuiles, vous obtiendrez des bouts de tuiles (tuiles non complètement remplies). Notez que chaque tuile d'aperçu générée par raster2pgsql a le même nombre de pixels que son parent, mais a une résolution inférieure, chaque pixel représentant (Puissance(2,facteur_d'aperçu) pixels de l'original).

9.3. Créer des applications personnalisées avec PostGIS Raster

Le fait que PostGIS raster vous fournisse des fonctions SQL pour rendre les rasters dans les formats d'image connus vous donne beaucoup d'options pour les rendre. Par exemple, vous pouvez utiliser OpenOffice / LibreOffice pour le rendu comme démontré dans Rendering PostGIS Raster graphics with LibreOffice Base Reports. En outre, vous pouvez utiliser une grande variété de langages, comme le montre cette section.

9.3.1. Exemple de sortie PHP utilisant ST_AsPNG avec d'autres fonctions raster

Dans cette section, nous allons montrer comment utiliser le driver PHP PostgreSQL et la famille de fonctions ST_AsGDALRaster pour produire les bandes 1,2,3 d'un raster dans un flux de requête PHP qui peut ensuite être incorporé dans une balise html img src.

L'exemple de requête montre comment combiner tout un ensemble de fonctions raster pour récupérer toutes les tuiles qui intersectent une boîte de délimitation wgs 84 particulière, puis unit avec ST_Union les tuiles intersectées en retournant toutes les bandes, transforme en projection spécifiée par l'utilisateur en utilisant ST_Transform, et sort les résultats au format png en utilisant ST_AsPNG.

Vous appellerez la commande ci-dessous en utilisant

http://mywebserver/test_raster.php?srid=2249

pour obtenir l'image raster en pieds de plan de l'État du Massachusetts.

<?php
/** contents of test_raster.php **/
$conn_str ='dbname=mydb host=localhost port=5432 user=myuser password=mypwd';
$dbconn = pg_connect($conn_str);
header('Content-Type: image/png');
/**If a particular projection was requested use it otherwise use mass state plane meters **/
if (!empty( $_REQUEST['srid'] ) && is_numeric( $_REQUEST['srid']) ){
                $input_srid = intval($_REQUEST['srid']);
}
else { $input_srid = 26986; }
/** The set bytea_output may be needed for PostgreSQL 9.0+, but not for 8.4 **/
$sql = "set bytea_output='escape';
SELECT ST_AsPNG(ST_Transform(
                        ST_AddBand(ST_Union(rast,1), ARRAY[ST_Union(rast,2),ST_Union(rast,3)])
                                ,$input_srid) ) As new_rast
 FROM aerials.boston
        WHERE
         ST_Intersects(rast, ST_Transform(ST_MakeEnvelope(-71.1217, 42.227, -71.1210, 42.218,4326),26986) )";
$result = pg_query($sql);
$row = pg_fetch_row($result);
pg_free_result($result);
if ($row === false) return;
echo pg_unescape_bytea($row[0]);
?>

9.3.2. Exemple ASP.NET C# Sortie utilisant ST_AsPNG en conjonction avec d'autres fonctions raster

Dans cette section, nous allons montrer comment utiliser le driver Npgsql PostgreSQL .NET et la famille de fonctions ST_AsGDALRaster pour produire les bandes 1,2,3 d'un raster dans un flux de requête PHP qui peut ensuite être incorporé dans une balise html img src.

Pour cet exercice, vous aurez besoin du driver PostgreSQL npgsql .NET dont vous pouvez obtenir la dernière version sur http://npgsql.projects.postgresql.org/. Il vous suffit de télécharger la dernière version et de la placer dans votre dossier ASP.NET bin.

L'exemple de requête montre comment combiner tout un ensemble de fonctions raster pour récupérer toutes les tuiles qui intersectent une boîte de délimitation wgs 84 particulière, puis unit avec ST_Union les tuiles intersectées en retournant toutes les bandes, transforme en projection spécifiée par l'utilisateur en utilisant ST_Transform, et sort les résultats au format png en utilisant ST_AsPNG.

Il s'agit du même exemple que Section 9.3.1, “Exemple de sortie PHP utilisant ST_AsPNG avec d'autres fonctions raster” sauf qu'il est implémenté en C#.

Vous appellerez la commande ci-dessous en utilisant

http://mywebserver/TestRaster.ashx?srid=2249

pour obtenir l'image raster en pieds de plan de l'État du Massachusetts.

-- web.config connection string section --
<connectionStrings>
    <add name="DSN"
        connectionString="server=localhost;database=mydb;Port=5432;User Id=myuser;password=mypwd"/>
</connectionStrings
>
// Code for TestRaster.ashx
<%@ WebHandler Language="C#" Class="TestRaster" %>
using System;
using System.Data;
using System.Web;
using Npgsql;

public class TestRaster : IHttpHandler
{
        public void ProcessRequest(HttpContext context)
        {

                context.Response.ContentType = "image/png";
                context.Response.BinaryWrite(GetResults(context));

        }

        public bool IsReusable {
                get { return false; }
        }

        public byte[] GetResults(HttpContext context)
        {
                byte[] result = null;
                NpgsqlCommand command;
                string sql = null;
                int input_srid = 26986;
        try {
                    using (NpgsqlConnection conn = new NpgsqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["DSN"].ConnectionString)) {
                            conn.Open();

                if (context.Request["srid"] != null)
                {
                    input_srid = Convert.ToInt32(context.Request["srid"]);
                }
                sql = @"SELECT ST_AsPNG(
                            ST_Transform(
                                        ST_AddBand(
                                ST_Union(rast,1), ARRAY[ST_Union(rast,2),ST_Union(rast,3)])
                                                    ,:input_srid) ) As new_rast
                        FROM aerials.boston
                                WHERE
                                    ST_Intersects(rast,
                                    ST_Transform(ST_MakeEnvelope(-71.1217, 42.227, -71.1210, 42.218,4326),26986) )";
                            command = new NpgsqlCommand(sql, conn);
                command.Parameters.Add(new NpgsqlParameter("input_srid", input_srid));


                            result = (byte[]) command.ExecuteScalar();
                conn.Close();
                        }

                }
        catch (Exception ex)
        {
            result = null;
            context.Response.Write(ex.Message.Trim());
        }
                return result;
        }
}

9.3.3. Application console Java qui produit une requête raster sous forme de fichier image

Il s'agit d'une simple application console Java qui prend une requête renvoyant une image et l'envoie dans le fichier spécifié.

Vous pouvez télécharger les derniers drivers JDBC de PostgreSQL à partir de http://jdbc.postgresql.org/download.html

Vous pouvez compiler le code suivant à l'aide d'une commande du type :

set env CLASSPATH .:..\postgresql-9.0-801.jdbc4.jar
javac SaveQueryImage.java
jar cfm SaveQueryImage.jar Manifest.txt *.class

Et l'appeler à partir de la ligne de commande avec quelque chose comme

java -jar SaveQueryImage.jar "SELECT ST_AsPNG(ST_AsRaster(ST_Buffer(ST_Point(1,5),10, 'quad_segs=2'),150, 150, '8BUI',100));" "test.png" 
-- Manifest.txt --
Class-Path: postgresql-9.0-801.jdbc4.jar
Main-Class: SaveQueryImage
// Code for SaveQueryImage.java
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.io.*;

public class SaveQueryImage {
  public static void main(String[] argv) {
      System.out.println("Checking if Driver is registered with DriverManager.");

      try {
        //java.sql.DriverManager.registerDriver (new org.postgresql.Driver());
        Class.forName("org.postgresql.Driver");
      }
      catch (ClassNotFoundException cnfe) {
        System.out.println("Couldn't find the driver!");
        cnfe.printStackTrace();
        System.exit(1);
      }

      Connection conn = null;

      try {
        conn = DriverManager.getConnection("jdbc:postgresql://localhost:5432/mydb","myuser", "mypwd");
        conn.setAutoCommit(false);

        PreparedStatement sGetImg = conn.prepareStatement(argv[0]);

        ResultSet rs = sGetImg.executeQuery();

                FileOutputStream fout;
                try
                {
                        rs.next();
                        /** Output to file name requested by user **/
                        fout = new FileOutputStream(new File(argv[1]) );
                        fout.write(rs.getBytes(1));
                        fout.close();
                }
                catch(Exception e)
                {
                        System.out.println("Can't create file");
                        e.printStackTrace();
                }

        rs.close();
                sGetImg.close();
        conn.close();
      }
      catch (SQLException se) {
        System.out.println("Couldn't connect: print out a stack trace and exit.");
        se.printStackTrace();
        System.exit(1);
      }
  }
}

9.3.4. Utiliser PLPython pour extraire des images via SQL

Il s'agit d'une fonction stockée en plpython qui crée un fichier dans le répertoire du serveur pour chaque enregistrement. Nécessite l'installation de plpython. Elle devrait fonctionner correctement avec plpythonu et plpython3u.

CREATE OR REPLACE FUNCTION write_file (param_bytes bytea, param_filepath text)
RETURNS text
AS $$
f = open(param_filepath, 'wb+')
f.write(param_bytes)
return param_filepath
$$ LANGUAGE plpythonu;
--write out 5 images to the PostgreSQL server in varying sizes
-- note the postgresql daemon account needs to have write access to folder
-- this echos back the file names created;
 SELECT write_file(ST_AsPNG(
        ST_AsRaster(ST_Buffer(ST_Point(1,5),j*5, 'quad_segs=2'),150*j, 150*j, '8BUI',100)),
         'C:/temp/slices'|| j || '.png')
         FROM generate_series(1,5) As j;

     write_file
---------------------
 C:/temp/slices1.png
 C:/temp/slices2.png
 C:/temp/slices3.png
 C:/temp/slices4.png
 C:/temp/slices5.png

9.3.5. Sortie de données raster avec PSQL

Malheureusement, PSQL n'a pas de fonctionnalité intégrée facile à utiliser pour produire des binaires. Il s'agit d'une astuce qui s'appuie sur le support des gros objets de PostgreSQL. Pour l'utiliser, lancez d'abord votre ligne de commande psql connectée à votre base de données.

Contrairement à l'approche python, cette approche crée le fichier sur votre ordinateur local.

SELECT oid, lowrite(lo_open(oid, 131072), png) As num_bytes
 FROM
 ( VALUES (lo_create(0),
   ST_AsPNG( (SELECT rast FROM aerials.boston WHERE rid=1) )
  ) ) As v(oid,png);
-- you'll get an output something like --
   oid   | num_bytes
---------+-----------
 2630819 |     74860

-- next note the oid and do this replacing the c:/test.png to file path location
-- on your local computer
 \lo_export 2630819 'C:/temp/aerial_samp.png'

-- this deletes the file from large object storage on db
SELECT lo_unlink(2630819);