Nous utilisons des cookies pour vous garantir la meilleure expérience sur notre site. Si vous continuez à utiliser ce dernier, nous considèrerons que vous acceptez l'utilisation des cookies. J'ai compris ! ou En savoir plus !.
banniere

Le portail francophone de la géomatique


Toujours pas inscrit ? Mot de passe oublié ?
Nom d'utilisateur    Mot de passe              Toujours pas inscrit ?   Mot de passe oublié ?

Annonce

Rencontres QGIS 2025

L'appel à participation est ouvert jusqu'au 19 janvier 2025!

#1 Mon 08 June 2009 17:47

jza
Participant occasionnel
Date d'inscription: 8 Jun 2009
Messages: 10

Programme C/C++ et format ECW : GDAL API ou ECW SDK

Bonjour,

si quelqu'un s'y connait vraiment sur l'utilisation d'une de ces deux ensembles de librairies avec le format ECW, j'aimerais savoir ce qu'il conseillerait (niveau performance (vitesse et mémoire), simplicité mais surtout pour commencer les fonctionnalités disponibles).

Le but du programme serait de pouvoir ouvrir un fichier ECW de très grande taille dont on ne connait pas forcément le type de projection à l'avance (par contre on souhaite tout le temps aboutir à une projection de type Lambert-quelque-chose (latitude longitude altitude)), décompresser et afficher uniquement une vue sur ce fichier (jusque là les deux le gèrent) et si nécessaire pouvoir effectuer donc une reprojection en temp réel sur la vue affichée sans pour autant passer par un fichier temporaire décompressé (lourd et lent j'imagine), ce qui me semble malheureusement nécessaire en passant par l'API de GDAL à première vue
A priori, le fait d'effectuer une reprojection totale à l'extérieur du programme ne semble pas exclu...

J'ai programmé la partie gérant l'affichage d'une vue issue d'un gros fichier en utilisant chacune des deux solutions, et pour le moment je dirais que le SDK est plus performant, de plus la fonction GDALRasterIO() ne peut lire d'une seule bande à la fois, ce qui me force à faire fusionner les trois matrices après leur lecture (ai-je raté une possibilité permettant de simplifier ça?)

Concernant la gestion des mosaïques, le SDK s'en occupe "automatiquement" apparement, mais je n'ai rien trouvé dans l'API GDAL

Voilà, je suis ouvert à tout renseignement pouvant m'éclairer davantage sur l'utilisation de l'API GDAL et du SDK dans un programme traitant des fichiers ECW

Merci d'avance, et bonne journée smile

Hors ligne

 

#2 Mon 08 June 2009 21:34

rouault
Participant assidu
Date d'inscription: 26 Apr 2009
Messages: 168

Re: Programme C/C++ et format ECW : GDAL API ou ECW SDK

Pour la reprojection à la volée, vois la Warp API : http://gdal.org/warptut.html. Il y a moyen de créer le "fichier" destination comme étant un Dataset MEM, donc sans passer par le disque dur.

Pour obtenir les 3 bandes à la fois, regarde du côté de GDALDatasetRasterIO. Le format ECW comprend justement une implémentation spécifique de l'API GDALDataset::IRasterIO, et non pas l'implémentation générique par défaut.

Concernant les mosaîques, de quoi parles tu exactement ? De mosaiques de plusieurs fichiers ECW ? Dans ce cas là, un fichier VRT permet de gérer ça de façon transparente. A noter qu'un des "modes" des fichiers VRT permet également la reprojection à la volée (cf VRTWarpedDataset, GDALAutoCreateWarpedVRT(),  GDALCreateWarpedVRT())

Hors ligne

 

#3 Tue 09 June 2009 09:58

jza
Participant occasionnel
Date d'inscription: 8 Jun 2009
Messages: 10

Re: Programme C/C++ et format ECW : GDAL API ou ECW SDK

Ok merci beaucoup pour tous ces renseignements, je vais explorer tout ça smile

Hors ligne

 

#4 Tue 09 June 2009 12:08

jza
Participant occasionnel
Date d'inscription: 8 Jun 2009
Messages: 10

Re: Programme C/C++ et format ECW : GDAL API ou ECW SDK

J'ai encore quelques questions concernant la reprojection à la volée, j'ai réussi à l'effectuer en utilisant le driver "MEM" (merci encore), par contre je me demandais s'il est possible de ne reprojeter qu'une seule partie de l'image car sinon les calculs sont très longs...
Première intuition, diminuer le contenu du dataset, par exemple en passant par un fichier VRT ne reprenant qu'une zone de l'image, mais il y a peut être plus simple là encore, par exemple modifier le dataset en lui-même ou en recréer un sans passer par le fichier VRT
(N'ayant pas trouvé de doc sur les classes spécifiques à l'ECW, j'essaye de décortiquer les fichiers cpp directement)

Une alternative pourrait être d'effectuer le reprojection une fois pour toute lors de l'ajout d'une nouvelle carte, mais le SDK qui est appelé par GDAL ne permet pas la compression de fichiers d'une taille > 500 mo, il y a cependant moyen de dépasser ce problème en ajoutant l'option LARGE_OK=YES lors du CreateCopy(), vu qu'il ne s'agit pas d'une compression d'un nouveau fichier ce n'est pas incorrect au niveau de l'éthique, je le précise car je l'ai découvert pendant la rédaction de ce message et ça pourrait également aider ceux qui ont le même problème

Hors ligne

 

#5 Tue 09 June 2009 17:41

jza
Participant occasionnel
Date d'inscription: 8 Jun 2009
Messages: 10

Re: Programme C/C++ et format ECW : GDAL API ou ECW SDK

Je n'ai pas réussi à utiliser GDALCreateWarpedVRT(), et je n'ai pas vraiment trouvé de doc

J'ai essayé de créer un VRT avec Create() (contenu incomplet, la partie <SimpleSource>...</SimpleSource> manque entre autres) et CreateCopy() (ok) mais par la suite en voulant effectuer la reprojection sur ce fichier (comme sur une copie complète en ECW) j'ai une erreur lors de l'appel de GDALWarpOperation::Initialize() => ERROR 5: Destination band 1 appears to be read-only
Puis j'ai une erreur de segmentation sur GDALWarpOperation::ChunkAndWarpImage()

Quelqu'un a une piste?

Hors ligne

 

#6 Wed 10 June 2009 15:01

jza
Participant occasionnel
Date d'inscription: 8 Jun 2009
Messages: 10

Re: Programme C/C++ et format ECW : GDAL API ou ECW SDK

J'ai laissé tombé la reprojection à la volée et les fichiers VRT...

Par contre j'ai quelques soucis avec la fonction GDALDatasetRasterIO sur un fichier ecw, j'ai pourtant vérifié mes paramètres mais le résultat n'est pas une seule image en couleur, mais 9 images en gris (3 lignes et 3 colonnes)...

Code:

GDALDatasetRasterIO( hSrcDS, GF_Read    // dataset à lire/écrire et mode (GF_Read ou GF_Write)
            , start_x, start_y    // coordonnées du point de départ (haut gauche)
            , length_x, length_y    // taille de la vue    
            , ret            // buffer
            , window_x, window_y    // taille de la fenetre d'affichage (et donc du buffer)
            , eDT            // type (GDT_Byte pour ecw)
            , *nb_bands        // nombre de bandes
            , band_list            // tableau référençant les bandes : NULL <=> [1 2 .. *nb_bands]
            , 0, 0, 0        // écart entre pixels/lignes/bandes dans le buffer : 0 <=> valeurs selon le type (GDT_Byte)
            );

Je n'ai pas trouvé de doc sur la classe ECWDataset et je ne sais même pas quel .h ajouter pour pouvoir travailler dessus...

Je bloque un peu...

Merci d'avance pour toute aide

Hors ligne

 

#7 Wed 10 June 2009 21:27

rouault
Participant assidu
Date d'inscription: 26 Apr 2009
Messages: 168

Re: Programme C/C++ et format ECW : GDAL API ou ECW SDK

L'utilisation de l'API C++ de Warping est assez délicate. Ca marche, mais ça demande un peu d'investissement. Le mieux, c'est d'étudier patiemment le code source de gdalwarp.cpp et de copier/coller les bouts nécessaires. Ton erreur de segmentation vient probablement de mauvaises valeurs passées pour le psWarpedOptions.
Pour le fichier VRT, gdalwarp.cpp permet également de créer les fichiers VRT avec un WarpDataset. Quand tu crées ce fichier VRT, effectivement son emprise est celle de la reprojection de l'ensemble du fichier original, mais on n'est pas obligé de tout demander. Il suffit juste de faire les bons GDALRasterIO/GDALDatasetRasterIO sur la fenêtre qui t'intéresse. Le WarpDataset est suffisamment malin pour calculer les blocs de l'image source nécessaires à la reprojection.

Sur ton dernier post, ton appel GDALDatasetRasterIO parait correct à première vue. C'est probablement ton interprétation du buffer retourné qui n'est pas bonne. Avec les paramètres d'espacement 0,0,0, si nb_bands = 3 et band_list = [1, 2, 3] tu devrais obtenir l'organisation suivante :

R11, R12, R13, ... R1w,
R21, R22, R23, ... R2w,
.., .., ..
Rh1, Rh2, Rh3, ... Rhw,
G11, G12, G13, ... G1w,
G21, G22, G23, ... G2w,
.., .., ..
Gh1, Gh2, Gh3, ... Ghw,
B11, B12, B13, ... B1w,
B21, B22, B23, ... B2w,
.., .., ..
Bh1, Bh2, Bh3, ... Bhw

où Rij/Gij/Bij est la composante rouge/verte/bleue du pixel de numéro de ligne i et de colonne j du buffer, h=window_y et w=window_x. A moins d'un bug spécifique de l'implémentation dans ECWDataset...

Il n'y a pas besoin de connaitre l'implémentation spécifique ECWDataset. Ne cherche pas la doc dessus: il n'y en a pas. En fait, si, il s'agit de frmts/ecw/ecwdataset.cpp ;-) C'est déjà bien que l'API, les formats et leurs options soient documentés ;-)

Hors ligne

 

#8 Thu 11 June 2009 10:07

jza
Participant occasionnel
Date d'inscription: 8 Jun 2009
Messages: 10

Re: Programme C/C++ et format ECW : GDAL API ou ECW SDK

Merci beaucoup pour ton aide

Pour le Warping, j'ai justement repris le code des deux premiers exemples de http://gdal.org/warptut.html (le 2ème montre comment créer un nouveau fichier, et le 1er comment effectuer le warping une fois les deux fichiers prêts), je vais suivre ton conseil et analyser le fichier gdalwarp.cpp

Ok pour le buffer je vais me résoudre à le remanier, merci, je pensais que le résultats était directement exploitable car rien n'indiquait le contraire et je n'ai pas trouvé d'exemple de son utilisation, par contre l'image est répétée 9 fois : 3 fois 3, il doit donc rester une subtilité à éclaircir car j'ai aussi testé avec un fichier TIF et l'image résultante n'était divisée qu'en 3, j'espère qu'il n'y a pas de bug (EDIT : ça fonctionne :] )

Merci encore!

EDIT2 : J'ai finalement réussi à trouver le compromis que je cherchais en utilisant un dataset de type MEM que je peux créer sans avoir d'erreur avec la fonction Create() ce qui m'épargne le temps de la copie de CreateCopy(), je peux ensuite afficher ce dataset sans chargement supplémentaire par rapport au cas où j'effectue un affichage direct, pour le moment tout a l'air correct, merci encore une fois ^^

EDIT3 : Par contre je m'aperçois que c'est encore très lent pour des fichiers de très grande taille, car la reprojection est effectuée sur la totalité du dataset, je me demande donc s'il existe tout simplement un moyen de ne reprojeter qu'une partie de l'image du dataset (celle qu'on affiche dans la vue) même s'il faut refaire le calcul en modifiant la vue à chaque fois, je n'ai pas bien compris si cette possibilité existe (je précise que je n'arrive pas à reprojeter à partir d'un VRT, j'ai une erreur qui me dit que la bande n'est pas accessible en écriture, sur http://www.gdal.org/gdal_vrttut.html j'ai lu "The VRTRawRasterBand supports in place update of the raster, whereas the source based VRTRasterBand is always read-only.", et je n'ai pas trouvé d'info sur les WarpDataset)

Dernière modification par jza (Thu 11 June 2009 12:45)

Hors ligne

 

#9 Thu 11 June 2009 19:37

rouault
Participant assidu
Date d'inscription: 26 Apr 2009
Messages: 168

Re: Programme C/C++ et format ECW : GDAL API ou ECW SDK

Effectivement, il n'y a pas de doc sur les VRTWarpedDataset. Je suppose qu'on attend qu'une âme charitable se dévoue pour l'écrire...

Quand y a pas de doc, rien ne vaut la pratique. Soit un fichier source byte.tif, qu'on souhaite reprojeter en EPSG:4326 : gdalwarp -of VRT -t_srs EPSG:4326 byte.tif byte.vrt.

On peut ensuite lire tranquillement ce fichier VRT par fenêtres d'intérêt. Moyennant une adaptation du code de gdalwarp dans le cas VRT, ce fichier VRT peut être créé en mémoire en utilisant le pseudo système de fichier /vsimem (cf VSIGetMemFileBuffer() et les explications données dans http://gdal.org/cpl__vsi_8h.html#eaf26b … a5e6ce7a).

Petit bémol qui peut t'impacter suivant ton cas d'utilisation : si jamais tu souhaite effectuer la reprojection non pas sur la résolution la plus précise possible du fichier source mais sur un niveau de sous-résolution (par ex si tu souhaites avoir un aperçu au 1/8 de la source après reprojection), le VRTWarpedDataset essaiera quand même de le faire sur la résolution la plus précise.

Hors ligne

 

#10 Fri 12 June 2009 10:20

jza
Participant occasionnel
Date d'inscription: 8 Jun 2009
Messages: 10

Re: Programme C/C++ et format ECW : GDAL API ou ECW SDK

Ok l'utilisation de VRT nécessite quand même de reprojeter toute l'image même si on souhaite l'afficher dans un miniature hmm
Nous allons procéder sans la reprojection à la volée car finalement il semblerait que la solution la plus fiable niveau ressources et performances pour l'ensemble des utilisations possibles, soit de créer lun fichier VRT associé à chaque ECW lors de l'ajout de ce dernier et ce une fois pour toute à l'aide de la commande gdalwap
De cette façon le programme final ouvre ce VRT ce qui nous épargne les calculs de reprojection à chaque session d'utilisation par la suite

Je te remercie encore une fois pour ton aide Rouault wink

Hors ligne

 

#11 Fri 12 June 2009 14:47

jza
Participant occasionnel
Date d'inscription: 8 Jun 2009
Messages: 10

Re: Programme C/C++ et format ECW : GDAL API ou ECW SDK

Encore moi, décidément cette histoire de reprojection pose problème...

En créant un fichier VRT je pensais que la lecture de l'image par la suite ne serait pas plus lente que pour une originale, malheureusement on dirait que le programme doit charger l'image originale puis la reprojeter avant de pouvoir l'afficher sad

J'ai donc deux questions :
- n'y a-t-il pas un moyen dans l'API C/C++ de sauvegarder un dataset MEM (ce serait pour le moment le moyen le plus rapide de créer un fichier ECW totalement reprojeté si on pouvait le conserver à la fin du programme)?
- n'y a-t-il pas sinon un moyen de dépasser la limite des 500 mo en compression dans l'utilitaire gdal? Car c'est possible en précisant une option dans l'API... (EDIT : en fait on peut passer la même option qu'avec l'API :  gdal_translate -of ECW -co "LARGE_OK=YES" entree.truc sortie.ecw donc à priori on reste sur cette méthode...)

Concernant vsimem, je n'ai pas trop compris comment ça fonctionne ce que ça apporterait mais à première vue, le mieux serait de calculer et conserver l'image reprojetée une fois pour toute, le problème est que l'API ne me le permet pas en format VRT ou ECW, et que l'utilitaire bloque sur la taille...

Dernière modification par jza (Fri 12 June 2009 14:59)

Hors ligne

 

#12 Tue 16 June 2009 10:21

jza
Participant occasionnel
Date d'inscription: 8 Jun 2009
Messages: 10

Re: Programme C/C++ et format ECW : GDAL API ou ECW SDK

Je poste la solution trouvée par un collègue au cas où elle pourrait aider quelqu'un :

On prend un dataset duquel on extrait la vue souhaitée puis on crée un dataset temporaire (create() avec driver MEM) auquel on ajoute les données du tableau de pixels extrait
Puis on applique la reprojection uniquement sur ce dataset et de cette façon on contourne le problème des calculs sur la résolution totale et le résultat est très rapide et ne prend pas beaucoup de mémoire au final

En résumé, on utilise simplement un troisième dataset qui sert de source à la reprojection, méthode simple et logique :p

Dernière modification par jza (Tue 16 June 2009 16:34)

Hors ligne

 

Pied de page des forums

Powered by FluxBB