diff --git a/.github/release.yml b/.github/release.yml deleted file mode 100644 index c879bf97..00000000 --- a/.github/release.yml +++ /dev/null @@ -1,24 +0,0 @@ -changelog: - exclude: - authors: - - dependabot - - pre-commit-ci - categories: - - title: Correction de bugs 🐛 - labels: - - bug - - title: Améliorations et nouvelles fonctionnalités 🎉 - labels: - - enhancement - - quality - - title: Outillage 🔧 - labels: - - ci-cd - - dependencies - - tooling - - title: Documentation 📖 - labels: - - documentation - - title: Divers - labels: - - "*" diff --git a/.github/workflows/build-and-release.yaml b/.github/workflows/build-and-release.yaml index 21969007..4741e86b 100644 --- a/.github/workflows/build-and-release.yaml +++ b/.github/workflows/build-and-release.yaml @@ -5,7 +5,7 @@ on: tags: - '**' -jobs: +jobs: create_release: name: Create Release @@ -17,6 +17,30 @@ jobs: - name: Checkout project uses: actions/checkout@v3 + - name: Update changelog + uses: thomaseizinger/keep-a-changelog-new-release@v2 + with: + tag: ${{ github.ref_name }} + + - name: Commit changelog + run: | + git config user.name github-actions + git config user.email github-actions@github.com + git add CHANGELOG.md + git commit -m "Versionnement du changelog" + git push + + - name: Get latest release info + id: query_release_info + uses: release-flow/keep-a-changelog-action@v2 + with: + command: query + version: latest + + - name: Write release notes + run: | + echo "echo {{ query_release_info.outputs.release-notes }} >notes.txt" + - name: Create Release id: create_release uses: ncipollo/release-action@v1 @@ -24,7 +48,7 @@ jobs: token: ${{ secrets.GITHUB_TOKEN }} tag: ${{ github.ref_name }} name: Release ${{ github.ref_name }} - generateReleaseNotes: true + bodyFile: notes.txt draft: false prerelease: false diff --git a/CHANGELOG.md b/CHANGELOG.md index cdc34f66..0729b6b4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,189 +1,200 @@ -## 2.0.5 +# Changelog -### [Fixed] +Tous les changements sont consignés dans ce fichier. -* `LibtiffImage` : Gestion des tiff jpeg de photometrie YCbCr avec les tiffs palettes dans le _getline (élargissement du test) +Le format est basé sur [Keep a Changelog](https://keepachangelog.com/) et ce projet respecte le [Semantic Versioning](https://semver.org/). -## 2.0.4 +## [Unreleased] -### [Fixed] +### Added -* `Merge` : correction du nombre de méthode +- `SubsampledImage` : cette classe fille d'Image permet de moyenner les pixels de l'image en entrée, en donnant la taille en X et Y de l'emprise de la moyenne. +- `Terrainrgb` : Ajout d'un style terrainrgb pour transformer les MNT en format Terrain RGB. +- `Style` : Ajout d'une fonction permettant de savoir si une palette existe ou non. +- Ajout du traitement en cas de style terrainrgb. Il doit être l'unique style déclaré pour fonctionner. +- `StyledImage` : Récupération de l'affectation du style au sein de la lib core-cpp. Regroupement des traitements des styles regroupés dans StyledImage. +- `StyledImage` : Ajout du traitement pour gérer le style Terrainrgb. -## 2.0.3 +### Changed -### [Added] +- `Cache` : Export de toutes les classes implémentées dans Cache dans leurs propres fichiers. Les fichiers ajoutés sont : + * `CurlPool` + * `ProjPool` + * `StoragePool` + * `IndexCache` + * `IndexElement` + * `TmsBook` + * `StyleBook` + * `CrsBook` +- `Style` : Vérification de l'existance d'un bloc palette dans le json de style avant la création d'un objet palette. Ce changement nécessite la vérification de l'existance d'une palette qui n'était pas vérifié avant. -* `TiffHeader` : la valeur de nodata est ajoutée dans le header des Geotiff +### Deprecated +### Removed +### Fixed -### [Fixed] +- `LibtiffImage` : correction de la lecture de la dernière tuile ou du dernier strip quand il y en a un nombre entier -* `Style` : gestion d'une valeur par défaut pour la demande de nodata, en entrée et en sortie +### Security -## 2.0.2 +## [2.0.6] - 2025-09-11 -### [Fixed] +### Added -* `TiffDeflateEncoder` : l'encodage du résultat final n'est pas en deflate (seule la donnée dans le tiff l'est, et non le résultat complet) -* `S3Context` : on retourne bien false lorsqu'une erreur est rencontrée lors du flush (close_to_write) +- `S3Context` et `SwiftContext` : possibilité de définir un timeout via la variable d'environnement `ROK4_NETWORK_TIMEOUT` (valeur à fournir en seconde) +### Changed -## 2.0.1 +- Refonte du CHANGELOG au format [Keep a Changelog](https://keepachangelog.com/) -### [Added] +## [2.0.5] - 2025-07-23 -* `Keyword` : ajout d'un exporteur JSON (API Tiles) -* `TileMatrixLimits` : ajout d'un exporteur JSON (API Tiles) +### Fixed -## 2.0.0 +- `LibtiffImage` : Gestion des tiff jpeg de photometrie YCbCr avec les tiffs palettes dans le _getline (élargissement du test) +- `Merge` : correction du nombre de méthode -### [Added] +## [2.0.3] - 2025-04-08 -* Internalisation de la lib json -* Ajout d'exporteur XML (via la lib boost) pour les entités Style, BoundingBox, Keyword, LegendURL, TileMatrixLimit et Style -* Création d'un annuaire pour les CRS pour éviter les créations en double +### Added -### [Changed] +- `TiffHeader` : la valeur de nodata est ajoutée dans le header des Geotiff -* Passage complet en snake case -* Le format de canal contient le nombre de bits d'encodage -* Renommage StyledImage -> PaletteImage -* Renommage lzwEncoder -> LzwCompressor -* Renommage lzwDecoder -> LzwUncompressor -* Renommage pkbEncoder -> PkbCompressor -* Renommage pkbDecoder -> PkbUncompressor +### Fixed -### [Deprecated] +- `Style` : gestion d'une valeur par défaut pour la demande de nodata, en entrée et en sortie -Liste de fonctionnalités dépréciées. +## [2.0.2] - 2025-02-17 -### [Removed] +### Fixed -* Suppression de la notion 'inspire' dans la gestion des styles -* Suppression de la classe ConvertedChannelsImage -* Suppression de la gestion de la compilation avec la librairie Kakadu -* Suppression des factory pour les classes filles de Image -* Suppression de la fonctionnalité de crop dans Rok4Image +- `TiffDeflateEncoder` : l'encodage du résultat final n'est pas en deflate (seule la donnée dans le tiff l'est, et non le résultat complet) +- `S3Context` : on retourne bien false lorsqu'une erreur est rencontrée lors du flush (close_to_write) -### [Fixed] +## [2.0.1] - 2024-10-01 -* Correction du nettoyage des annuaires de TMS et styles +### Added +- `Keyword` : ajout d'un exporteur JSON (API Tiles) +- `TileMatrixLimits` : ajout d'un exporteur JSON (API Tiles) +- Internalisation de la lib json +- Ajout d'exporteur XML (via la lib boost) pour les entités Style, BoundingBox, Keyword, LegendURL, TileMatrixLimit et Style +- Création d'un annuaire pour les CRS pour éviter les créations en double -## 1.4.0 +### Changed -### [Added] +- Passage complet en snake case +- Le format de canal contient le nombre de bits d'encodage +- Renommage StyledImage -> PaletteImage +- Renommage lzwEncoder -> LzwCompressor +- Renommage lzwDecoder -> LzwUncompressor +- Renommage pkbEncoder -> PkbCompressor +- Renommage pkbDecoder -> PkbUncompressor -* Stockage objet (S3, Swift et Ceph) - * Possibilité de définir un nombre de tentatives pour les lectures (1 par défaut) : variable d'environnement `ROK4_OBJECT_READ_ATTEMPTS` - * Possibilité de définir un nombre de tentatives pour les écritures (1 par défaut) : variable d'environnement `ROK4_OBJECT_WRITE_ATTEMPTS` - * Possibilité de définir un temps d'attente, en secondes, entre les tentatives (5 par défaut) : variable d'environnement `ROK4_OBJECT_ATTEMPTS_WAIT` +### Removed + +- Suppression de la notion 'inspire' dans la gestion des styles +- Suppression de la classe ConvertedChannelsImage +- Suppression de la gestion de la compilation avec la librairie Kakadu +- Suppression des factory pour les classes filles de Image +- Suppression de la fonctionnalité de crop dans Rok4Image + +### Fixed + +- Correction du nettoyage des annuaires de TMS et styles -## 1.3.1 +## [1.4.0] - 2024-03-21 -### [Fixed] +### Added -* `S3Context` : pour éviter des conflits dans une utilisation multithreadée, la sortie de la fonction HMAC (openssl) est dédiée. +- Stockage objet (S3, Swift et Ceph) + * Possibilité de définir un nombre de tentatives pour les lectures (1 par défaut) : variable d'environnement `ROK4_OBJECT_READ_ATTEMPTS` + * Possibilité de définir un nombre de tentatives pour les écritures (1 par défaut) : variable d'environnement `ROK4_OBJECT_WRITE_ATTEMPTS` + * Possibilité de définir un temps d'attente, en secondes, entre les tentatives (5 par défaut) : variable d'environnement `ROK4_OBJECT_ATTEMPTS_WAIT` -## 1.3.0 +## [1.3.1] - 2024-03-14 -### [Added] +### Added -* Gestion du multi cluster S3 : +- Gestion du multi cluster S3 : * nom du cluster = hôte du cluster avec le port (pas de protocole) * Pour préciser le cluster auquel on s'adresse, le nom du bucket aura la forme `@` * Les variables d'environnement `ROK4_S3_URL`, `ROK4_S3_KEY` et `ROK4_S3_SECRETKEY` peuvent contenir une liste de valeurs séparées par des virgules * **Dans** les descripteurs de pyramide et leur liste ou les objets symboliques, on peut ne pas préciser le nom du cluster : on sait alors qu'on travaille sur le même cluster que celui de l'objet d'origine -### [Fixed] - -* Attribute : dans les valeurs des attributs, on échappe les éventuelles back quotes - -## 1.2.4 - -### [Fixed] - -* `Cache` : les modifications dans le cache quand il n'est pas par thread (index des dalles, TMS et styles) se font en exclusion mutuelle (mutex lock et unlock) - -## 1.2.3 - -### [Fixed] - -* `Level` : Ajout de pixels de marge lors de la reprojection des données d'un niveau de pyramide - -## 1.2.2 - -### [Fixed] - -* `LibopenjpegImage` : la lecture des images JPEG 2000 tuilées recharge l'image à la lecture de chaque tuile - -## 1.2.1 +### Fixed -### [Fixed] +- `S3Context` : pour éviter des conflits dans une utilisation multithreadée, la sortie de la fonction HMAC (openssl) est dédiée. +- Attribute : dans les valeurs des attributs, on échappe les éventuelles back quotes -* `LegendURL` : la fonction de copie d'une instance recopie bien le format et le href -* `LibtiffImage` : correction du calcul de nombre de tuile dans la largeur lors de la lecture d'une image dont la largeur est un multiple de la taille de la tuile -* `BoundingBox` : lorsque l'on met en phase une bbox, les 4 bords doivent être traités indépendemment les uns des autres (avec un calcul de phase pour chacun) +## [1.2.4] - 2023-12-06 -### [Changed] +### Changed -* La variable d'environnement `ROK4_TMS_NO_CACHE` permet de désactiver le cache de chargement des TMS -* La variable d'environnement `ROK4_STYLES_NO_CACHE` permet de désactiver le cache de chargement des styles +- La variable d'environnement `ROK4_TMS_NO_CACHE` permet de désactiver le cache de chargement des TMS +- La variable d'environnement `ROK4_STYLES_NO_CACHE` permet de désactiver le cache de chargement des styles -## 1.1.2 +### Fixed -### [Changed] +- `Cache` : les modifications dans le cache quand il n'est pas par thread (index des dalles, TMS et styles) se font en exclusion mutuelle (mutex lock et unlock) +- `Level` : Ajout de pixels de marge lors de la reprojection des données d'un niveau de pyramide +- `LibopenjpegImage` : la lecture des images JPEG 2000 tuilées recharge l'image à la lecture de chaque tuile +- `LegendURL` : la fonction de copie d'une instance recopie bien le format et le href +- `LibtiffImage` : correction du calcul de nombre de tuile dans la largeur lors de la lecture d'une image dont la largeur est un multiple de la taille de la tuile +- `BoundingBox` : lorsque l'on met en phase une bbox, les 4 bords doivent être traités indépendemment les uns des autres (avec un calcul de phase pour chacun) -* Le test d'existence d'un objet ou d'un fichier n'est plus une lecture de 1 octet mais une implémentation spécifique à chaque type -* Les TMS et les styles sont cherchés sur le stockage avec et sans extension JSON +## [1.1.2] - 2023-09-14 -### [Fixed] +### Added -* Table - * Correction d'une typo dans l'écriture du metadata.json : filedsCount -> fieldsCount -* Style - * La valeur de nodata en sortie d'un style est la première valeur de la palette (et non la couleur pour la valeur 0) - -## 1.1.1 - -### [Fixed] - -* LibopenjpegImage - * Fixe sur la lecture des images à tuile unique suite au zonage - -## 1.1.0 - -### [Added] - -* LibtiffImage +- LibtiffImage * Capacité à lire des images tuilées * Capacité à lire des images avec palette -### [Changed] +### Changed -* LibopenjpegImage +- Le test d'existence d'un objet ou d'un fichier n'est plus une lecture de 1 octet mais une implémentation spécifique à chaque type +- Les TMS et les styles sont cherchés sur le stockage avec et sans extension JSON +- LibopenjpegImage * Lecture des images à tuile unique par paquet de 256 lignes * Lecture des images tuilées par tuile +### Fixed -## 1.0.3 +- Table + * Correction d'une typo dans l'écriture du metadata.json : filedsCount -> fieldsCount +- Style + * La valeur de nodata en sortie d'un style est la première valeur de la palette (et non la couleur pour la valeur 0) +- LibopenjpegImage + * Fixe sur la lecture des images à tuile unique suite au zonage + +## [1.0.3] - 2023-03-14 Les librairies sont gérées de manière indépendantes, conditionnées pour être installées en tant que dépendance dynamique. Le projet a son propre site, avec toutes les versions et leur documentation. -### [Added] +### Added -* Librairie, partie `utils` : +- Librairie, partie `utils` : * Styles et TMS sont chargés dans un annuaire, qui connait le dossier de stockage des fichiers / objets les définissant * Les pyramide sont chargées depuis leur descripteur, fichier ou objet -* Librairie, partie `storage` : gère un annuaire de contextes de stockages, fichier, Swift, S3 ou Ceph -* Librairie, partie `image` : permet la lecture et le calcul ligne par ligne -* Librairie, partie `datasource` : permet la lecture en une fois d'un buffer de donnée -* Librairie, partie `datasource` : permet la lecture par morceau d'un buffer de donnée -* Librairie, partie `processors` : gère plusieurs noyaux d'interpolation et la conversion de pixel - -* Intégration continue : +- Librairie, partie `storage` : gère un annuaire de contextes de stockages, fichier, Swift, S3 ou Ceph +- Librairie, partie `image` : permet la lecture et le calcul ligne par ligne +- Librairie, partie `datasource` : permet la lecture en une fois d'un buffer de donnée +- Librairie, partie `datasource` : permet la lecture par morceau d'un buffer de donnée +- Librairie, partie `processors` : gère plusieurs noyaux d'interpolation et la conversion de pixel +- Intégration continue : * Compilation du fichier librok4.so et conditionnement dans des paquets debian avec les headers, avec et sans la prise en charge du stockage ceph * Jeu des tests unitaires * Compilation de la documentation et publication sur la branche gh-pages - -* Ajout du mode DEBUG à la compilation \ No newline at end of file +- Ajout du mode DEBUG à la compilation + +[2.0.6]: https://github.com/rok4/core-cpp/compare/2.0.5...HEAD +[2.0.6]: https://github.com/rok4/core-cpp/compare/2.0.5...2.0.6 +[2.0.5]: https://github.com/rok4/core-cpp/compare/2.0.3...2.0.5 +[2.0.3]: https://github.com/rok4/core-cpp/compare/2.0.2...2.0.3 +[2.0.2]: https://github.com/rok4/core-cpp/compare/2.0.1...2.0.2 +[2.0.1]: https://github.com/rok4/core-cpp/compare/1.4.0...2.0.1 +[1.4.0]: https://github.com/rok4/core-cpp/compare/1.3.1...1.4.0 +[1.3.1]: https://github.com/rok4/core-cpp/compare/1.2.4...1.3.1 +[1.2.4]: https://github.com/rok4/core-cpp/compare/1.1.2...1.2.4 +[1.1.2]: https://github.com/rok4/core-cpp/compare/1.0.3...1.1.2 +[1.0.3]: https://github.com/rok4/core-cpp/releases/tag/1.0.3 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4c3895db..8ef75cf2 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -4,32 +4,30 @@ Merci d'envisager de contribuer à ce projet ! ## Pull request -Le titre de la PR est utilisé pour constituer automatiquement les notes de release. Vous pouvez préciser en commentaire de votre PR des détails qui seront ajoutés dans le fichier `CHANGELOG.md` par les mainteneurs du projet. - -Le formalisme du changelog est le suivant, en markdown : +Complétez le fichier `CHANGELOG.md`, dans la partie `[Unreleased]`, en précisant les modifications fonctionnelles apportées. Celles ci seront utilisées pour rédiger le message de release sur GitHub. Le format est basé sur [Keep a Changelog](https://keepachangelog.com/). Les sections sont les suivantes : ```md -### [Added] +### Added Liste de nouvelles fonctionnalités. -### [Changed] +### Changed Liste de fonctionnalités existantes modifiées. -### [Deprecated] +### Deprecated Liste de fonctionnalités dépréciées. -### [Removed] +### Removed Liste de foncitonnalités retirées. -### [Fixed] +### Fixed Liste de corrections fonctionnelles. -### [Security] +### Security Liste de corrections de sécurité. ``` diff --git a/README.md b/README.md index 41dc1860..089caf0a 100644 --- a/README.md +++ b/README.md @@ -66,6 +66,7 @@ Leur définition est contrôlée à l'usage. - `ROK4_SWIFT_TOKEN_FILE` afin de sauvegarder le token d'accès, et ne pas le demander si ce fichier en contient un * Pour configurer l'usage de libcurl (intéraction SWIFT et S3) - `ROK4_SSL_NO_VERIFY` + - `ROK4_NETWORK_TIMEOUT` : temps en secondes d'inactivité d'une requête avant de la stopper. Aucun temps défini côté client si aucune valeur fournie - `HTTP_PROXY` - `HTTPS_PROXY` - `NO_PROXY` @@ -84,7 +85,11 @@ Le programme qui suit charge une pyramide SCAN1000 à partir de son descripteur, #include #include #include -#include "rok4/utils/Cache.h" +#include "rok4/utils/CrsBook.h" +#include "rok4/utils/TmsBook.h" +#include "rok4/utils/ProjPool.h" +#include "rok4/utils/IndexCache.h" +#include "rok4/utils/StoragePool.h" int main( int argc, char *argv[] ) { diff --git a/include/rok4/image/AspectImage.h b/include/rok4/image/AspectImage.h deleted file mode 100644 index 8ec8c7df..00000000 --- a/include/rok4/image/AspectImage.h +++ /dev/null @@ -1,160 +0,0 @@ -/* - * Copyright © (2011) Institut national de l'information - * géographique et forestière - * - * Géoportail SAV - * - * This software is a computer program whose purpose is to publish geographic - * data using OGC WMS and WMTS protocol. - * - * This software is governed by the CeCILL-C license under French law and - * abiding by the rules of distribution of free software. You can use, - * modify and/ or redistribute the software under the terms of the CeCILL-C - * license as circulated by CEA, CNRS and INRIA at the following URL - * "http://www.cecill.info". - * - * As a counterpart to the access to the source code and rights to copy, - * modify and redistribute granted by the license, users are provided only - * with a limited warranty and the software's author, the holder of the - * economic rights, and the successive licensors have only limited - * liability. - * - * In this respect, the user's attention is drawn to the risks associated - * with loading, using, modifying and/or developing or reproducing the - * software by the user in light of its specific status of free software, - * that may mean that it is complicated to manipulate, and that also - * therefore means that it is reserved for developers and experienced - * professionals having in-depth computer knowledge. Users are therefore - * encouraged to load and test the software's suitability as regards their - * requirements in conditions enabling the security of their systems and/or - * data to be ensured and, more generally, to use and operate it in the - * same conditions as regards security. - * - * The fact that you are presently reading this means that you have had - * - * knowledge of the CeCILL-C license and that you accept its terms. - */ - -#pragma once - -#include - -#include "rok4/image/Image.h" -#include "rok4/style/Aspect.h" - - -class AspectImage : public Image { - -private: - - /** \~french - * \brief Image d'origine utilisée pour calculer l'exposition - ** \~english - * \brief Origin image used to compute the aspect - */ - Image* source_image; - - /** \~french - * \brief Nombre de ligne en mémoire - ** \~english - * \brief Memorize lines number - */ - int memorized_source_lines; - - /** \~french - * \brief Buffer contenant les lignes sources - ** \~english - * \brief Source lines memory buffer - */ - float* source_lines_buffer; - - /** \~french - * \brief Numéros des lignes en mémoire - ** \~english - * \brief Memorized lines indexes - */ - int* source_lines; - - /** \~french - * \brief Matrice de convolution - ** \~english - * \brief Convolution matrix - */ - float matrix[9]; - - /** \~french - * \brief Résolution de l'image d'origine et donc finale - ** \~english - * \brief Resolution of the image - */ - float resolution; - - /** \~french - * \brief Configuration de l'aspect - ** \~english - * \brief Aspect configuration - */ - Aspect* aspect; - - /** \~french - * \brief Récupère la ligne - ** \~english - * \brief Get line - */ - template - int _getline ( T* buffer, int line ); - -public: - - /** \~french - * \brief Récupère la ligne - ** \~english - * \brief Get line - */ - virtual int get_line ( float* buffer, int line ); - - /** \~french - * \brief Récupère la ligne - ** \~english - * \brief Get line - */ - virtual int get_line ( uint8_t* buffer, int line ); - - /** \~french - * \brief Récupère la ligne - ** \~english - * \brief Get line - */ - virtual int get_line ( uint16_t* buffer, int line ); - - /** \~french - * \brief Constructeur - ** \~english - * \brief Construtor - */ - AspectImage ( Image* image, Aspect* asp); - - /** \~french - * \brief Destructeur - ** \~english - * \brief Destructor - */ - virtual ~AspectImage(); - - /** \~french - * \brief Sortie des informations sur l'image estompée - ** \~english - * \brief Estompage image description output - */ - void print() { - BOOST_LOG_TRIVIAL(info) << "" ; - BOOST_LOG_TRIVIAL(info) << "------ AspectImage -------" ; - Image::print(); - BOOST_LOG_TRIVIAL(info) << "\t- Algo = " << aspect->algo ; - BOOST_LOG_TRIVIAL(info) << "\t- min Slope = " << aspect->min_slope ; - - BOOST_LOG_TRIVIAL(info) << "" ; - } - -}; - diff --git a/include/rok4/image/EstompageImage.h b/include/rok4/image/EstompageImage.h deleted file mode 100644 index 4d74501d..00000000 --- a/include/rok4/image/EstompageImage.h +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright © (2011) Institut national de l'information - * géographique et forestière - * - * Géoportail SAV - * - * This software is a computer program whose purpose is to publish geographic - * data using OGC WMS and WMTS protocol. - * - * This software is governed by the CeCILL-C license under French law and - * abiding by the rules of distribution of free software. You can use, - * modify and/ or redistribute the software under the terms of the CeCILL-C - * license as circulated by CEA, CNRS and INRIA at the following URL - * "http://www.cecill.info". - * - * As a counterpart to the access to the source code and rights to copy, - * modify and redistribute granted by the license, users are provided only - * with a limited warranty and the software's author, the holder of the - * economic rights, and the successive licensors have only limited - * liability. - * - * In this respect, the user's attention is drawn to the risks associated - * with loading, using, modifying and/or developing or reproducing the - * software by the user in light of its specific status of free software, - * that may mean that it is complicated to manipulate, and that also - * therefore means that it is reserved for developers and experienced - * professionals having in-depth computer knowledge. Users are therefore - * encouraged to load and test the software's suitability as regards their - * requirements in conditions enabling the security of their systems and/or - * data to be ensured and, more generally, to use and operate it in the - * same conditions as regards security. - * - * The fact that you are presently reading this means that you have had - * - * knowledge of the CeCILL-C license and that you accept its terms. - */ - -#pragma once - -#include "rok4/image/Image.h" -#include "rok4/style/Estompage.h" - -class EstompageImage : public Image { -private: - /** \~french - * \brief Image d'origine utilisée pour calculer l'estompage - ** \~english - * \brief Origin image used to compute the estompage - */ - Image* source_image; - - /** \~french - * \brief Nombre de ligne en mémoire - ** \~english - * \brief Memorize lines number - */ - int memorized_source_lines; - - /** \~french - * \brief Buffer contenant les lignes sources - ** \~english - * \brief Source lines memory buffer - */ - float* source_lines_buffer; - - /** \~french - * \brief Numéros des lignes en mémoire - ** \~english - * \brief Memorized lines indexes - */ - int* source_lines; - - /** \~french - * \brief Résolution de l'image en X, en mètre - ** \~english - * \brief Resolution of the image (X), in meter - */ - float resxmeter; - - /** \~french - * \brief Résolution de l'image en Y, en mètre - ** \~english - * \brief Resolution of the image (Y), in meter - */ - float resymeter; - - /** \~french - * \brief Configuration de l'estompage - ** \~english - * \brief Estompage configuration - */ - Estompage* estompage; - - /** \~french - * \brief Calcule la ligne - ** \~english - * \brief Process line - */ - template - int _getline ( T* buffer, int line ); - -public: - virtual int get_line ( float* buffer, int line ); - virtual int get_line ( uint8_t* buffer, int line ); - virtual int get_line ( uint16_t* buffer, int line ); - EstompageImage (Image* image, Estompage* est); - virtual ~EstompageImage(); - - /** \~french - * \brief Sortie des informations sur l'image estompée - ** \~english - * \brief Estompage image description output - */ - void print() { - BOOST_LOG_TRIVIAL(info) << "" ; - BOOST_LOG_TRIVIAL(info) << "------ EstompageImage -------" ; - Image::print(); - BOOST_LOG_TRIVIAL(info) << "\t- Zenith = " << estompage->zenith ; - BOOST_LOG_TRIVIAL(info) << "\t- Azimuth = " << estompage->azimuth ; - BOOST_LOG_TRIVIAL(info) << "\t- Z factor = " << estompage->z_factor ; - - BOOST_LOG_TRIVIAL(info) << "" ; - } -}; - diff --git a/include/rok4/image/Image.h b/include/rok4/image/Image.h index 1a32238f..3ea8ae5c 100644 --- a/include/rok4/image/Image.h +++ b/include/rok4/image/Image.h @@ -47,12 +47,11 @@ #include #include -#include #include +#include #include "rok4/utils/BoundingBox.h" -#include "rok4/utils/CRS.h" -#include "rok4/utils/Cache.h" +#include "rok4/utils/CrsBook.h" #define METER_PER_DEG 111319.492 @@ -72,8 +71,7 @@ */ class Image { -protected: - + protected: /** * \~french \brief Nombre de canaux de l'image * \~english \brief Number of samples per pixel @@ -133,12 +131,11 @@ class Image { * \brief Resolutions calculation, from pixel size and bounding box */ void compute_resolutions() { - resx = ( bbox.xmax - bbox.xmin ) / double ( width ); - resy = ( bbox.ymax - bbox.ymin ) / double ( height ); + resx = (bbox.xmax - bbox.xmin) / double(width); + resy = (bbox.ymax - bbox.ymin) / double(height); } -public: - + public: /** * \~french * \brief Vérifie la cohérence des dimensions d'image fournies @@ -155,21 +152,23 @@ class Image { * \param[in] h Image's height, in pixel * \param[in] bounding_box Image's bounding box */ - static bool are_dimensions_consistent(double resolution_x, double resolution_y, int w, int h, BoundingBox bounding_box) { + static bool are_dimensions_consistent(double resolution_x, double resolution_y, int w, int h, + BoundingBox bounding_box) { // Vérification de la cohérence entre les résolutions et bbox fournies et les dimensions (en pixel) de l'image // Arrondi a la valeur entiere la plus proche - if (resolution_x == 0 || resolution_y == 0) return false; + if (resolution_x == 0 || resolution_y == 0) + return false; - int calcWidth = lround ( ( bounding_box.xmax - bounding_box.xmin ) / ( resolution_x ) ); - int calcHeight = lround ( ( bounding_box.ymax - bounding_box.ymin ) / ( resolution_y ) ); + int calcWidth = lround((bounding_box.xmax - bounding_box.xmin) / (resolution_x)); + int calcHeight = lround((bounding_box.ymax - bounding_box.ymin) / (resolution_y)); - if ( calcWidth != w || calcHeight != h ) { - BOOST_LOG_TRIVIAL(warning) << "height is " << h << " and calculation give " << calcHeight ; - BOOST_LOG_TRIVIAL(warning) << "width is " << w << " and calculation give " << calcWidth ; + if (calcWidth != w || calcHeight != h) { + BOOST_LOG_TRIVIAL(warning) << "height is " << h << " and calculation give " << calcHeight; + BOOST_LOG_TRIVIAL(warning) << "width is " << w << " and calculation give " << calcWidth; return false; } - + return true; } @@ -179,9 +178,7 @@ class Image { * \~english * \brief Define the image as a mask */ - inline void make_mask () { - is_mask = true; - } + inline void make_mask() { is_mask = true; } /** * \~french @@ -191,9 +188,7 @@ class Image { * \brief Return the number of samples per pixel * \return channels */ - virtual int get_channels() { - return channels; - } + virtual int get_channels() { return channels; } /** * \~french @@ -203,9 +198,7 @@ class Image { * \brief Return the image's width * \return width */ - int inline get_width() { - return width; - } + int inline get_width() { return width; } /** * \~french @@ -215,9 +208,7 @@ class Image { * \brief Return the image's height * \return height */ - int inline get_height() { - return height; - } + int inline get_height() { return height; } /** * \~french @@ -227,12 +218,15 @@ class Image { * \brief Define the image's bounding box and calculate resolutions * \param[in] box Image's bounding box */ - inline void set_bbox ( BoundingBox box ) { + inline void set_bbox(BoundingBox box) { bbox = box; if (crs != NULL) { bbox.crs = crs->get_request_code(); } compute_resolutions(); + if (!is_mask && mask != NULL) { + mask->set_bbox(box); + } } /** @@ -243,12 +237,13 @@ class Image { * \brief Define the image's bounding box and calculate resolutions * \param[in] box Image's bounding box */ - inline bool set_dimensions ( int w, int h, BoundingBox box, double rx, double ry ) { + inline bool set_dimensions(int w, int h, BoundingBox box, double rx, double ry) { double calcWidth = (box.xmax - box.xmin) / rx; double calcHeight = (box.ymax - box.ymin) / ry; - - if ( std::abs(calcWidth - w) > 10E-3 || std::abs(calcHeight - h) > 10E-3) return false; - + + if (std::abs(calcWidth - w) > 10E-3 || std::abs(calcHeight - h) > 10E-3) + return false; + width = w; height = h; resx = rx; @@ -266,9 +261,7 @@ class Image { * \brief Return the image's bounding box * \return bounding box */ - BoundingBox inline get_bbox() const { - return bbox; - } + BoundingBox inline get_bbox() const { return bbox; } /** * \~french @@ -279,7 +272,7 @@ class Image { * \brief Define the CRS of the image's bounding box * \param[in] box Image's bounding box */ - void set_crs ( CRS* c ) { + void set_crs(CRS* c) { crs = NULL; if (c != NULL) { @@ -288,6 +281,10 @@ class Image { } else { bbox.crs = ""; } + + if (!is_mask && mask != NULL) { + mask->set_crs(c); + } } /** @@ -298,9 +295,7 @@ class Image { * \brief Return the image's bounding box's CRS * \return CRS */ - CRS* get_crs() const { - return crs; - } + CRS* get_crs() const { return crs; } /** * \~french @@ -310,9 +305,7 @@ class Image { * \brief Return bounding box's xmin * \return xmin */ - double inline get_xmin() const { - return bbox.xmin; - } + double inline get_xmin() const { return bbox.xmin; } /** * \~french * \brief Retourne le ymax de l'emprise rectangulaire @@ -321,9 +314,7 @@ class Image { * \brief Return bounding box's ymax * \return ymax */ - double inline get_ymax() const { - return bbox.ymax; - } + double inline get_ymax() const { return bbox.ymax; } /** * \~french * \brief Retourne le xmax de l'emprise rectangulaire @@ -332,9 +323,7 @@ class Image { * \brief Return bounding box's xmax * \return xmax */ - double inline get_xmax() const { - return bbox.xmax; - } + double inline get_xmax() const { return bbox.xmax; } /** * \~french * \brief Retourne le ymin de l'emprise rectangulaire @@ -343,9 +332,7 @@ class Image { * \brief Return bounding box's ymin * \return ymin */ - double inline get_ymin() const { - return bbox.ymin; - } + double inline get_ymin() const { return bbox.ymin; } /** * \~french @@ -358,7 +345,8 @@ class Image { * \return X resolution */ inline double get_resx(bool force_meter = false) const { - if (force_meter && crs->get_meters_per_unit() != 1.0) return resx * METER_PER_DEG; + if (force_meter && crs->get_meters_per_unit() != 1.0) + return resx * METER_PER_DEG; return resx; } /** @@ -372,7 +360,8 @@ class Image { * \return Y resolution */ inline double get_resy(bool force_meter = false) const { - if (force_meter && crs->get_meters_per_unit() != 1.0) return resy * METER_PER_DEG; + if (force_meter && crs->get_meters_per_unit() != 1.0) + return resy * METER_PER_DEG; return resy; } @@ -384,9 +373,7 @@ class Image { * \brief Return the associated mask * \return mask */ - inline Image* get_mask() { - return mask; - } + inline Image* get_mask() { return mask; } /** * \~french @@ -396,17 +383,17 @@ class Image { * \brief Defined data mask and check consistency * \param[in] new_mask Masque de donnée */ - inline bool set_mask ( Image* new_mask ) { + inline bool set_mask(Image* new_mask) { if (mask != NULL) { // On a déjà un masque associé : on le supprime pour le remplacer par le nouveau delete mask; } - - if ( new_mask->get_width() != width || new_mask->get_height() != height || new_mask->get_channels() != 1 ) { - BOOST_LOG_TRIVIAL(error) << "Unvalid mask" ; - BOOST_LOG_TRIVIAL(error) << "\t - channels have to be 1, it is " << new_mask->get_channels() ; - BOOST_LOG_TRIVIAL(error) << "\t - width have to be " << width << ", it is " << new_mask->get_width() ; - BOOST_LOG_TRIVIAL(error) << "\t - height have to be " << height << ", it is " << new_mask->get_height() ; + + if (new_mask->get_width() != width || new_mask->get_height() != height || new_mask->get_channels() != 1) { + BOOST_LOG_TRIVIAL(error) << "Unvalid mask"; + BOOST_LOG_TRIVIAL(error) << "\t - channels have to be 1, it is " << new_mask->get_channels(); + BOOST_LOG_TRIVIAL(error) << "\t - width have to be " << width << ", it is " << new_mask->get_width(); + BOOST_LOG_TRIVIAL(error) << "\t - height have to be " << height << ", it is " << new_mask->get_height(); return false; } @@ -426,9 +413,7 @@ class Image { * \param[in] x terrain coordinate X * \return column */ - int inline x_to_column ( double x ) { - return floor ( ( x-bbox.xmin ) /resx ); - } + int inline x_to_column(double x) { return floor((x - bbox.xmin) / resx); } /** * \~french * \brief Conversion de l'ordonnée terrain vers l'indice de ligne dans l'image @@ -439,9 +424,7 @@ class Image { * \param[in] y terrain coordinate Y * \return line */ - int inline y_to_line ( double y ) { - return floor ( ( bbox.ymax-y ) /resy ); - } + int inline y_to_line(double y) { return floor((bbox.ymax - y) / resy); } /** * \~french @@ -453,9 +436,7 @@ class Image { * \param[in] c column * \return terrain coordinate X */ - double inline column_to_x ( int c ) { - return ( bbox.xmin + (0.5 + c) * resx ); - } + double inline column_to_x(int c) { return (bbox.xmin + (0.5 + c) * resx); } /** * \~french * \brief Conversion de l'indice de ligne dans l'image vers l'ordonnée terrain du centre du pixel @@ -466,9 +447,7 @@ class Image { * \param[in] l line * \return terrain coordinate Y */ - double inline line_to_y ( int l ) { - return ( bbox.ymax - (0.5 + l) * resy ); - } + double inline line_to_y(int l) { return (bbox.ymax - (0.5 + l) * resy); } /** * \~french @@ -481,9 +460,7 @@ class Image { * \image html phases.png * \return X phasis */ - double inline get_phasex() { - return bbox.get_xmin_phase(resx); - } + double inline get_phasex() { return bbox.get_xmin_phase(resx); } /** * \~french @@ -494,9 +471,7 @@ class Image { * \brief Phasis calculation, Y wise * \return Y phasis */ - double inline get_phasey() { - return bbox.get_ymin_phase(resy); - } + double inline get_phasey() { return bbox.get_ymin_phase(resy); } /** * \~french @@ -520,36 +495,37 @@ class Image { * \param[in] other image to compare * \return compatibility */ - bool compatible ( Image* other ) { + bool compatible(Image* other) { - if ( crs != NULL && crs->is_define() && other->get_crs() != NULL && other->get_crs()->is_define() && ! crs->cmp_request_code(other->get_crs()->get_request_code()) ) { - BOOST_LOG_TRIVIAL(debug) << "Different CRS" ; + if (crs != NULL && crs->is_define() && other->get_crs() != NULL && other->get_crs()->is_define() && + !crs->cmp_request_code(other->get_crs()->get_request_code())) { + BOOST_LOG_TRIVIAL(debug) << "Different CRS"; return false; } - if ( get_channels() != other->get_channels() ) { - BOOST_LOG_TRIVIAL(debug) << "Different channels" ; + if (get_channels() != other->get_channels()) { + BOOST_LOG_TRIVIAL(debug) << "Different channels"; return false; } - double epsilon_x=std::min ( get_resx(), other->get_resx() ) /1000.; - double epsilon_y=std::min ( get_resy(), other->get_resy() ) /1000.; + double epsilon_x = std::min(get_resx(), other->get_resx()) / 1000.; + double epsilon_y = std::min(get_resy(), other->get_resy()) / 1000.; - if ( fabs ( get_resx()-other->get_resx() ) > epsilon_x ) { - BOOST_LOG_TRIVIAL(debug) << "Different X resolutions" ; + if (fabs(get_resx() - other->get_resx()) > epsilon_x) { + BOOST_LOG_TRIVIAL(debug) << "Different X resolutions"; return false; } - if ( fabs ( get_resy()-other->get_resy() ) > epsilon_y ) { - BOOST_LOG_TRIVIAL(debug) << "Different Y resolutions" ; + if (fabs(get_resy() - other->get_resy()) > epsilon_y) { + BOOST_LOG_TRIVIAL(debug) << "Different Y resolutions"; return false; } - if ( fabs ( get_phasex()-other->get_phasex() ) > 0.001 && fabs ( get_phasex()-other->get_phasex() ) < 0.999 ) { - BOOST_LOG_TRIVIAL(debug) << "Different X phasis : " << get_phasex() << " and " << other->get_phasex() ; + if (fabs(get_phasex() - other->get_phasex()) > 0.001 && fabs(get_phasex() - other->get_phasex()) < 0.999) { + BOOST_LOG_TRIVIAL(debug) << "Different X phasis : " << get_phasex() << " and " << other->get_phasex(); return false; } - if ( fabs ( get_phasey()-other->get_phasey() ) > 0.001 && fabs ( get_phasey()-other->get_phasey() ) < 0.999 ) { - BOOST_LOG_TRIVIAL(debug) << "Different Y phasis : " << get_phasey() << " and " << other->get_phasey() ; + if (fabs(get_phasey() - other->get_phasey()) > 0.001 && fabs(get_phasey() - other->get_phasey()) < 0.999) { + BOOST_LOG_TRIVIAL(debug) << "Different Y phasis : " << get_phasey() << " and " << other->get_phasey(); return false; } @@ -574,9 +550,16 @@ class Image { * \param[in] resy Y wise resolution * \param[in] bbox bounding box */ - Image ( int width, int height, int channels, double resx, double resy, BoundingBox bbox ) : - width ( width ), height ( height ), channels ( channels ), resx ( resx ), resy ( resy ), bbox ( bbox ), crs ( NULL ), mask ( NULL ), is_mask(false) - { + Image(int width, int height, int channels, double resx, double resy, BoundingBox bbox) + : width(width), + height(height), + channels(channels), + resx(resx), + resy(resy), + bbox(bbox), + crs(NULL), + mask(NULL), + is_mask(false) { are_dimensions_consistent(resx, resy, width, height, bbox); } @@ -593,7 +576,16 @@ class Image { * \param[in] height image height, in pixel * \param[in] channel number of samples per pixel */ - Image ( int width, int height, int channels ) : width ( width ), height ( height ), channels ( channels ), resx ( 1. ), resy ( 1. ), bbox ( BoundingBox ( 0., 0., ( double ) width, ( double ) height ) ), crs ( NULL ), mask ( NULL ), is_mask ( false ) {} + Image(int width, int height, int channels) + : width(width), + height(height), + channels(channels), + resx(1.), + resy(1.), + bbox(BoundingBox(0., 0., (double)width, (double)height)), + crs(NULL), + mask(NULL), + is_mask(false) {} /** * \~french @@ -610,9 +602,8 @@ class Image { * \param[in] channel number of samples per pixel * \param[in] bbox bounding box */ - Image ( int width, int height, int channels, BoundingBox bbox ) : - width ( width ), height ( height ), channels ( channels ), bbox ( bbox ), crs ( NULL ), mask ( NULL ), is_mask ( false ) - { + Image(int width, int height, int channels, BoundingBox bbox) + : width(width), height(height), channels(channels), bbox(bbox), crs(NULL), mask(NULL), is_mask(false) { compute_resolutions(); } @@ -632,10 +623,16 @@ class Image { * \param[in] resx X wise resolution * \param[in] resy Y wise resolution */ - Image ( int width, int height, int channels, double resx, double resy ) : - width ( width ), height ( height ), channels ( channels ), resx ( resx ), resy ( resy ), - bbox ( BoundingBox ( 0., 0., resx * ( double ) width, resy * ( double ) height ) ), - mask ( NULL ), is_mask ( false ), crs ( NULL ) {} + Image(int width, int height, int channels, double resx, double resy) + : width(width), + height(height), + channels(channels), + resx(resx), + resy(resy), + bbox(BoundingBox(0., 0., resx * (double)width, resy * (double)height)), + mask(NULL), + is_mask(false), + crs(NULL) {} /** * \~french @@ -645,8 +642,8 @@ class Image { * \param[in] line Indice de la ligne à retourner (0 <= line < height) * \return taille utile du buffer, 0 si erreur */ - virtual int get_line ( uint8_t *buffer, int line ) = 0; - + virtual int get_line(uint8_t* buffer, int line) = 0; + /** * \~french * \brief Retourne une ligne en entier 16 bits. @@ -655,7 +652,7 @@ class Image { * \param[in] line Indice de la ligne à retourner (0 <= line < height) * \return taille utile du buffer, 0 si erreur */ - virtual int get_line ( uint16_t *buffer, int line ) = 0; + virtual int get_line(uint16_t* buffer, int line) = 0; /** * \~french @@ -665,7 +662,7 @@ class Image { * \param[in] line Indice de la ligne à retourner (0 <= line < height) * \return taille utile du buffer, 0 si erreur */ - virtual int get_line ( float *buffer, int line ) = 0; + virtual int get_line(float* buffer, int line) = 0; /** * \~french @@ -674,7 +671,8 @@ class Image { * \brief Default destructor */ virtual ~Image() { - if ( mask != NULL ) delete mask; + if (mask != NULL) + delete mask; } /** @@ -684,27 +682,27 @@ class Image { * \brief Image description output */ virtual void print() { - BOOST_LOG_TRIVIAL(info) << "\t- width = " << width << ", height = " << height ; - BOOST_LOG_TRIVIAL(info) << "\t- samples per pixel = " << channels ; + BOOST_LOG_TRIVIAL(info) << "\t- width = " << width << ", height = " << height; + BOOST_LOG_TRIVIAL(info) << "\t- samples per pixel = " << channels; if (crs != NULL) { - BOOST_LOG_TRIVIAL(info) << "\t- CRS = " << crs->get_proj_code() ; + BOOST_LOG_TRIVIAL(info) << "\t- CRS = " << crs->get_proj_code(); } else { - BOOST_LOG_TRIVIAL(info) << "\t- No CRS" ; + BOOST_LOG_TRIVIAL(info) << "\t- No CRS"; } - BOOST_LOG_TRIVIAL(info) << "\t- bbox = " << bbox.to_string() ; - BOOST_LOG_TRIVIAL(info) << "\t- x resolution = " << resx << ", y resolution = " << resy ; - if ( is_mask ) { - BOOST_LOG_TRIVIAL(info) << "\t- Is a mask" ; + BOOST_LOG_TRIVIAL(info) << "\t- bbox = " << bbox.to_string(); + BOOST_LOG_TRIVIAL(info) << "\t- x resolution = " << resx << ", y resolution = " << resy; + if (is_mask) { + BOOST_LOG_TRIVIAL(info) << "\t- Is a mask"; } else { - BOOST_LOG_TRIVIAL(info) << "\t- Is not a mask" ; + BOOST_LOG_TRIVIAL(info) << "\t- Is not a mask"; } - if ( mask ) { - BOOST_LOG_TRIVIAL(info) << "\t- Own a mask\n" ; + if (mask) { + BOOST_LOG_TRIVIAL(info) << "\t- Own a mask\n"; } else { - BOOST_LOG_TRIVIAL(info) << "\t- No mask\n" ; + BOOST_LOG_TRIVIAL(info) << "\t- No mask\n"; } } - + /** * \~french * \brief Sortie du tfw de l'image @@ -712,7 +710,10 @@ class Image { * \brief Image TFW output */ virtual void print_tfw() { - BOOST_LOG_TRIVIAL(info) << "TFW : \n" << resx << "\n-" << resy << "\n0\n0\n" << bbox.xmin+0.5*resx << "\n" << bbox.ymax - 0.5*resy ; + BOOST_LOG_TRIVIAL(info) << "TFW : \n" + << resx << "\n-" << resy << "\n0\n0\n" + << bbox.xmin + 0.5 * resx << "\n" + << bbox.ymax - 0.5 * resy; } /** @@ -723,12 +724,9 @@ class Image { */ virtual float get_mean_resolution() { if (crs->get_meters_per_unit() != 1.0) { - return ((resx+resy)/2.0)*METER_PER_DEG; + return ((resx + resy) / 2.0) * METER_PER_DEG; } else { - return (resx+resy)/2.0; + return (resx + resy) / 2.0; } - } }; - - diff --git a/include/rok4/image/PenteImage.h b/include/rok4/image/StyledImage.h similarity index 58% rename from include/rok4/image/PenteImage.h rename to include/rok4/image/StyledImage.h index 1d4bf42d..05ed1de7 100644 --- a/include/rok4/image/PenteImage.h +++ b/include/rok4/image/StyledImage.h @@ -35,23 +35,39 @@ * knowledge of the CeCILL-C license and that you accept its terms. */ +/** + * \file StyledImage.h + ** \~french + * \brief D�finition de la classe StyledImage + ** \~english + * \brief Define class StyledImage + */ + #pragma once #include "rok4/image/Image.h" -#include "rok4/style/Pente.h" -#include - - -class PenteImage : public Image { +#include "rok4/style/Style.h" +class StyledImage : public Image +{ private: + template + int _getline(T *buffer, int line); + Image *source_image; + Style *style; + /** \~french + * \brief Résolution de l'image en X, en mètre + ** \~english + * \brief Resolution of the image (X), in meter + */ + float resxmeter; /** \~french - * \brief Image d'origine utilisée pour calculer la pente + * \brief Résolution de l'image en Y, en mètre ** \~english - * \brief Origin image used to compute the slope + * \brief Resolution of the image (Y), in meter */ - Image* source_image; + float resymeter; /** \~french * \brief Nombre de ligne en mémoire @@ -75,88 +91,54 @@ class PenteImage : public Image { int* source_lines; /** \~french - * \brief Résolution de l'image en X, en mètre + * \brief Matrice de convolution ** \~english - * \brief Resolution of the image (X), in meter + * \brief Convolution matrix */ - float resxmeter; + float matrix[9]; /** \~french - * \brief Résolution de l'image en Y, en mètre + * \brief Résolution de l'image d'origine et donc finale ** \~english - * \brief Resolution of the image (Y), in meter + * \brief Resolution of the image */ - float resymeter; + float resolution; /** \~french - * \brief Configuration de la pente + * \brief Booléen précisant l'utilisation de buffer pour les traitements multi-lignes ** \~english - * \brief Slope configuration + * \brief Booleen that indicate if buffers are used for multi-line processes */ - Pente* pente; + bool multi_line_buffer; - /** \~french - * \brief Calcule la ligne - ** \~english - * \brief Process line - */ - template - int _getline ( T* buffer, int line ); + StyledImage(Image* image, Style *style, int offset); public: + virtual int get_line(float *buffer, int line); + virtual int get_line(uint16_t *buffer, int line); + virtual int get_line(uint8_t *buffer, int line); + /** \~french - * \brief Récupère la ligne - ** \~english - * \brief Get line - */ - virtual int get_line ( float* buffer, int line ); - - /** \~french - * \brief Récupère la ligne - ** \~english - * \brief Get line - */ - virtual int get_line ( uint8_t* buffer, int line ); - - /** \~french - * \brief Récupère la ligne - ** \~english - * \brief Get line - */ - virtual int get_line ( uint16_t* buffer, int line ); - - /** \~french - * \brief Constructeur - ** \~english - * \brief Construtor - */ - PenteImage (Image* image, Pente* p); - - /** \~french - * \brief Destructeur - ** \~english - * \brief Destructor - */ - virtual ~PenteImage(); + * \brief Teste et calcule les caractéristiques d'une image stylisée et crée un objet StyledImage + * \details Largeur, hauteur, nombre de canaux et bbox sont déduits des composantes de l'image source et des paramètres. On vérifie la superposabilité des images sources. + * \param[in] input_image image source + * \param[in] input_style style source + * \return un pointeur d'objet StyledImage, NULL en cas d'erreur + ** \~english + * \brief Check and calculate styled image components and create an StyledImage object + * \details Height, width, samples' number and bbox are deduced from source image's components and parameters. We check if source images are superimpose. + * \param[in] input_image source images + * \param[in] input_style nodata value + * \return a StyledImage object pointer, NULL if error + */ + static StyledImage* create ( Image* input_image, Style* input_style ); + virtual ~StyledImage(); /** \~french - * \brief Sortie des informations sur l'image estompée + * \brief Sortie des informations sur l'image reprojetée ** \~english - * \brief Estompage image description output + * \brief Reprojected image description output */ - void print() { - BOOST_LOG_TRIVIAL(info) << "" ; - BOOST_LOG_TRIVIAL(info) << "------ PenteImage -------" ; - Image::print(); - BOOST_LOG_TRIVIAL(info) << "\t- Algo = " << pente->algo ; - BOOST_LOG_TRIVIAL(info) << "\t- Unit = " << pente->unit ; - BOOST_LOG_TRIVIAL(info) << "\t- max Slope = " << pente->max_slope ; - BOOST_LOG_TRIVIAL(info) << "\t- Slope nodata = " << pente->slope_nodata_value ; - BOOST_LOG_TRIVIAL(info) << "\t- Image nodata = " << pente->input_nodata_value ; - - BOOST_LOG_TRIVIAL(info) << "" ; - } - + void print(); }; - diff --git a/include/rok4/image/SubsampledImage.h b/include/rok4/image/SubsampledImage.h new file mode 100644 index 00000000..2d9a376e --- /dev/null +++ b/include/rok4/image/SubsampledImage.h @@ -0,0 +1,173 @@ +/* + * Copyright © (2011) Institut national de l'information + * géographique et forestière + * + * Géoportail SAV + * + * This software is a computer program whose purpose is to publish geographic + * data using OGC WMS and WMTS protocol. + * + * This software is governed by the CeCILL-C license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-C + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * + * knowledge of the CeCILL-C license and that you accept its terms. + */ + +/** + * \file SubsampledImage.h + ** \~french + * \brief Définition des classes SubsampledImage + * \details + * \li SubsampledImage : image résultant du sous échantillonnage d'une image source + ** \~english + * \brief Define classes SubsampledImage + * \details + * \li SubsampledImage : image built by source image's sub sampling + */ + +#pragma once + +#include +#include +#include +#include +#include + +#include "rok4/utils/Utils.h" +#include "rok4/image/Image.h" + +/** + * \author Institut national de l'information géographique et forestière + * \~french + * \brief Décimation d'une image, c'est à dire qu'on ne garde qu'un seul pixel tous les N pixels + */ +class SubsampledImage : public Image { + +private: + + /** + * \~french \brief Image source à décimer + * \~english \brief Source image, to decimate + */ + Image* source_image; + + /** + * \~french \brief Facteur de sous échantillonnage dans le sens des X + * \~english \brief Subsampling's factor, widthwise + */ + int ratio_x; + /** + * \~french \brief Facteur de sous échantillonnage dans le sens des Y + * \~english \brief Subsampling's factor, heightwise + */ + int ratio_y; + + /** \~french + * \brief Retourne une ligne, flottante ou entière + * \details Lorsque l'on veut récupérer une ligne d'une image décimée, on ne garde que un pixel tous les #ratio_x de l'image source + * + * \param[in] buffer Tableau contenant au moins width*channels valeurs + * \param[in] line Indice de la ligne à retourner (0 <= line < height) + * \return taille utile du buffer, 0 si erreur + */ + template + int _getline ( T* buffer, int line ); + + /** \~french + * \brief Crée un objet SubsampledImage à partir de tous ses éléments constitutifs + * \details Ce constructeur est privé afin de n'être appelé que par la méthode statique #create, qui fera différents tests et calculs. + * \param[in] width largeur de l'image en pixel + * \param[in] height hauteur de l'image en pixel + * \param[in] channel nombre de canaux par pixel + * \param[in] resx résolution dans le sens des X + * \param[in] resy résolution dans le sens des Y + * \param[in] bbox emprise rectangulaire de l'image + * \param[in] image image source + * \param[in] nd valeur de non-donnée + ** \~english + * \brief Create an SubsampledImage object, from all attributes + * \param[in] width image width, in pixel + * \param[in] height image height, in pixel + * \param[in] channel number of samples per pixel + * \param[in] resx X wise resolution + * \param[in] resy Y wise resolution + * \param[in] bbox bounding box + * \param[in] image source image + * \param[in] nd nodata value + */ + SubsampledImage ( Image* image, int ratio_x, int ratio_y); + +public: + + int get_line ( uint8_t* buffer, int line ); + int get_line ( uint16_t* buffer, int line ); + int get_line ( float* buffer, int line ); + + /** + * \~french + * \brief Destructeur par défaut + * \details Suppression de l'image source de la SubsampledImage + * \~english + * \brief Default destructor + */ + virtual ~SubsampledImage() { + if (! is_mask) { + delete source_image; + } + } + + /** \~french + * \brief Sortie des informations sur l'image composée + ** \~english + * \brief Compounded image description output + */ + void print() { + BOOST_LOG_TRIVIAL(info) << "" ; + BOOST_LOG_TRIVIAL(info) << "------ SubsampledImage -------" ; + Image::print(); + BOOST_LOG_TRIVIAL(info) << "\t- X wise ratio : " << ratio_x; + BOOST_LOG_TRIVIAL(info) << "\t- Y wise ratio : " << ratio_y; + BOOST_LOG_TRIVIAL(info) << "" ; + } + + /** \~french + * \brief Teste et calcule les caractéristiques de l'image sous échantillonnée et crée un objet SubsampledImage + * \details Largeur, hauteur, nombre de canaux et bbox sont déduits des composantes de l'image source et des paramètres. On vérifie que les dimensions sont divisibles par les facteurs. + * \param[in] image image source + * \param[in] ratio_x facteur de sous échantillonnage en X + * \param[in] ratio_y facteur de sous échantillonnage en Y + * \return un pointeur d'objet SubsampledImage, NULL en cas d'erreur + ** \~english + * \brief Check and calculate compounded image components and create an SubsampledImage object + * \details Height, width, samples' number and bbox are deduced from source image's components and parameters. We check if dimensions are multiple of factors. + * \param[in] image source image + * \param[in] ratio_x Widthwise subsampling factor + * \param[in] ratio_y Heightwise subsampling factor + * \return a SubsampledImage object pointer, NULL if error + */ + static SubsampledImage* create ( Image* image, int ratio_x, int ratio_y ); +}; + + diff --git a/include/rok4/processors/Grid.h b/include/rok4/processors/Grid.h index 06dabe0c..cbfc36bd 100644 --- a/include/rok4/processors/Grid.h +++ b/include/rok4/processors/Grid.h @@ -49,6 +49,7 @@ #include "rok4/utils/CRS.h" #include #include +#include "rok4/utils/ProjPool.h" /** * \author Institut national de l'information géographique et forestière diff --git a/include/rok4/storage/Context.h b/include/rok4/storage/Context.h index 554cb6ea..a281f5ba 100644 --- a/include/rok4/storage/Context.h +++ b/include/rok4/storage/Context.h @@ -57,6 +57,7 @@ #define ROK4_OBJECT_READ_ATTEMPTS "ROK4_OBJECT_READ_ATTEMPTS" #define ROK4_OBJECT_WRITE_ATTEMPTS "ROK4_OBJECT_WRITE_ATTEMPTS" #define ROK4_OBJECT_ATTEMPTS_WAIT "ROK4_OBJECT_ATTEMPTS_WAIT" +#define ROK4_NETWORK_TIMEOUT "ROK4_NETWORK_TIMEOUT" /** * \author Institut national de l'information géographique et forestière diff --git a/include/rok4/style/Style.h b/include/rok4/style/Style.h index 766a22d6..f1667c6d 100644 --- a/include/rok4/style/Style.h +++ b/include/rok4/style/Style.h @@ -55,8 +55,10 @@ class Style; #include "rok4/style/Pente.h" #include "rok4/style/Estompage.h" #include "rok4/style/Aspect.h" +#include "rok4/style/Terrainrgb.h" #include "rok4/enums/Interpolation.h" #include "rok4/utils/Configuration.h" +#include "rok4/utils/StoragePool.h" #include "rok4/enums/Format.h" /** @@ -162,6 +164,11 @@ private : * \~english \brief Define wether the server must compute a relief shadow */ Estompage* estompage; + /** + * \~french \brief Définit si un calcul de terrainrgb doit être appliqué + * \~english \brief Define wether the server must compute a RGB terrain + */ + Terrainrgb* terrainrgb; /** * \~french \brief Valeur de nodata attendue dans les données en entrée @@ -219,7 +226,7 @@ private : * \~english \brief Style is allowed ? */ bool handle (int spp) { - if (estompage_defined() || pente_defined() || aspect_defined()) { + if (estompage_defined() || pente_defined() || aspect_defined() || terrainrgb_defined()) { return (spp == 1); } else { return true; @@ -232,12 +239,26 @@ private : */ int get_channels (int orig_channels) { if (palette && ! palette->is_empty()) { - if (palette->is_no_alpha()) { + if (orig_channels ==1){ + if (palette->is_no_alpha()) { + return 3; + } else { + return 4; + } + } + else { + return orig_channels; + } + } + else if (terrainrgb_defined()){ + if (orig_channels ==1){ return 3; - } else { - return 4; } - } else { + else { + return orig_channels; + } + } + else { if (estompage_defined() || pente_defined() || aspect_defined()) { return 1; } else { @@ -245,6 +266,7 @@ private : return orig_channels; } } + } /** @@ -252,7 +274,7 @@ private : * \~english \brief Which sample format after style */ SampleFormat::eSampleFormat get_sample_format (SampleFormat::eSampleFormat sf) { - if (palette && ! palette->is_empty()) { + if ((palette && ! palette->is_empty()) || terrainrgb_defined()) { return SampleFormat::UINT8; } else { return sf; @@ -292,7 +314,7 @@ private : return false; } - if (estompage_defined() || pente_defined() || aspect_defined()) { + if (estompage_defined() || pente_defined() || aspect_defined() || terrainrgb_defined()) { return false; } else { return true; @@ -347,6 +369,17 @@ private : return &legends; } + /** + * \~french + * \brief Détermine si le style décrit une table de correspondance + * \return true si oui + * \~english + * \brief Determine if the style describe a lookup table + * \return true if it does + */ + inline bool palette_defined() { + return (palette != 0); + } /** * \~french * \brief Retourne la table de correspondance @@ -421,6 +454,27 @@ private : inline Aspect* get_aspect() { return aspect; } + + /** + * \~french + * \brief Return vrai si le style est un terrainrgb + * \return bool + * \~english + * \brief Return true if the style is an rgb terrain + * \return bool + */ + inline bool terrainrgb_defined() { + return (terrainrgb != 0); + } + /** + * \~french + * \brief Retourne le terrainrgb + * \~english + * \brief Return rgb terrain + */ + inline Terrainrgb* get_terrainrgb() { + return terrainrgb; + } /** diff --git a/include/rok4/style/Terrainrgb.h b/include/rok4/style/Terrainrgb.h new file mode 100644 index 00000000..58f80ab6 --- /dev/null +++ b/include/rok4/style/Terrainrgb.h @@ -0,0 +1,102 @@ +/* + * Copyright © (2011) Institut national de l'information + * géographique et forestière + * + * Géoportail SAV + * + * This software is a computer program whose purpose is to publish geographic + * data using OGC WMS and WMTS protocol. + * + * This software is governed by the CeCILL-C license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-C + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * + * knowledge of the CeCILL-C license and that you accept its terms. + */ + + /** + * \file Terrainrgb.h + ** \~french + * \brief D�finition de la classe Terrainrgb + ** \~english + * \brief Define class Terrainrgb + */ + + +#pragma once + +#include "rok4/utils/Configuration.h" + +#include +#include +#include +#include + +class Terrainrgb : public Configuration +{ +public: + /** \~french + * \brief min_elevation : élévation minimale à partir de laquelle est calculée la couleur + ** \~english + * \brief min_elevation : minimum elevation from which the color is calculated + */ + float min_elevation; + + /** \~french + * \brief step : résolution verticale + ** \~english + * \brief step : vertical resolution + */ + float step; + + /** \~french + * \brief noData : valeur de nodata pour l'image source + ** \~english + * \brief noData : value of nodata for the source image + */ + float input_nodata_value; + + /** \~french + * \brief noData : valeur de nodata pour le terrainrgb + ** \~english + * \brief noData : value of nodata for the RGB terrain + */ + float terrainrgb_nodata_value; + + /** + * \~french + * \brief Constructeurs avec des arguments + * \~english + * \brief Constructor with arguments + */ + Terrainrgb(json11::Json doc); + + /** + * \~french + * \brief Destructeur + * \~english + * \brief Destructor + */ + virtual ~Terrainrgb(); +}; diff --git a/include/rok4/utils/CRS.h b/include/rok4/utils/CRS.h index ab29e51e..2cf8d0ea 100644 --- a/include/rok4/utils/CRS.h +++ b/include/rok4/utils/CRS.h @@ -47,7 +47,11 @@ #pragma once #include +#include +#include #include "rok4/utils/BoundingBox.h" +#include "rok4/utils/ProjPool.h" +#include "rok4/utils/Utils.h" /** * \~french \brief Code utilisé en cas de non correspondance avec les référentiel de Proj diff --git a/include/rok4/utils/Cache.h b/include/rok4/utils/Cache.h deleted file mode 100644 index 811a7d0e..00000000 --- a/include/rok4/utils/Cache.h +++ /dev/null @@ -1,1096 +0,0 @@ -/* - * Copyright © (2011) Institut national de l'information - * géographique et forestière - * - * Géoportail SAV - * - * This software is a computer program whose purpose is to publish geographic - * data using OGC WMS and WMTS protocol. - * - * This software is governed by the CeCILL-C license under French law and - * abiding by the rules of distribution of free software. You can use, - * modify and/ or redistribute the software under the terms of the CeCILL-C - * license as circulated by CEA, CNRS and INRIA at the following URL - * "http://www.cecill.info". - * - * As a counterpart to the access to the source code and rights to copy, - * modify and redistribute granted by the license, users are provided only - * with a limited warranty and the software's author, the holder of the - * economic rights, and the successive licensors have only limited - * liability. - * - * In this respect, the user's attention is drawn to the risks associated - * with loading, using, modifying and/or developing or reproducing the - * software by the user in light of its specific status of free software, - * that may mean that it is complicated to manipulate, and that also - * therefore means that it is reserved for developers and experienced - * professionals having in-depth computer knowledge. Users are therefore - * encouraged to load and test the software's suitability as regards their - * requirements in conditions enabling the security of their systems and/or - * data to be ensured and, more generally, to use and operate it in the - * same conditions as regards security. - * - * The fact that you are presently reading this means that you have had - * - * knowledge of the CeCILL-C license and that you accept its terms. - */ - -/** - * \file Cache.h - ** \~french - * \brief Définition des classes IndexCache, CurlPool, StoragePool et ProjPool - ** \~english - * \brief Define classes IndexCache, CurlPool, StoragePool and ProjPool - */ - -#pragma once - -#include // pour uint8_t -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -#include "rok4/utils/TileMatrixSet.h" -#include "rok4/style/Style.h" -#include "rok4/utils/Utils.h" -#include "rok4/utils/CRS.h" -#include "rok4/storage/Context.h" - -#define ROK4_TMS_DIRECTORY "ROK4_TMS_DIRECTORY" -#define ROK4_TMS_NO_CACHE "ROK4_TMS_NO_CACHE" -#define ROK4_STYLES_DIRECTORY "ROK4_STYLES_DIRECTORY" -#define ROK4_STYLES_NO_CACHE "ROK4_STYLES_NO_CACHE" - -/** - * \author Institut national de l'information géographique et forestière - * \~french - * \brief Création d'un pool d'environnement Curl - * \details Cette classe est prévue pour être utilisée sans instance - */ -class CurlPool { - -private: - - /** - * \~french \brief Annuaire des objet Curl - * \details La clé est l'identifiant du thread - * \~english \brief Curl object book - * \details Key is the thread's ID - */ - static std::map pool; - - /** - * \~french - * \brief Constructeur - * \~english - * \brief Constructeur - */ - CurlPool(){}; - -public: - - /** - * \~french - * \brief Destructeur - * \~english - * \brief Destructor - */ - ~CurlPool(){}; - - /** - * \~french \brief Retourne un objet Curl propre au thread appelant - * \details Si il n'existe pas encore d'objet curl pour ce tread, on le crée et on l'initialise - * \~english \brief Get the curl object specific to the calling thread - * \details If curl object doesn't exist for this thread, it is created and initialized - */ - static CURL* get_curl_env() { - pthread_t i = pthread_self(); - - std::map::iterator it = pool.find ( i ); - if ( it == pool.end() ) { - CURL* c = curl_easy_init(); - pool.insert ( std::pair(i,c) ); - return c; - } else { - curl_easy_reset(it->second); - return it->second; - } - } - - /** - * \~french \brief Affiche le nombre d'objet curl dans l'annuaire - * \~english \brief Print the number of curl objects in the book - */ - static void print_curls_count () { - BOOST_LOG_TRIVIAL(info) << "Nombre de contextes curl : " << pool.size(); - } - - /** - * \~french \brief Nettoie tous les objets curl dans l'annuaire et le vide - * \~english \brief Clean all curl objects in the book and empty it - */ - static void clean_curls () { - std::map::iterator it; - for (it = pool.begin(); it != pool.end(); ++it) { - curl_easy_cleanup(it->second); - } - pool.clear(); - } - -}; - - -/** - * \author Institut national de l'information géographique et forestière - * \~french - * \brief Création d'un pool de contextes Proj - * \details Cette classe est prévue pour être utilisée sans instance - */ -class ProjPool { - -private: - - /** - * \~french \brief Annuaire des contextes Proj - * \details La clé est l'identifiant du thread - * \~english \brief Proj contexts book - * \details Key is the thread's ID - */ - static std::map pool; - - /** - * \~french - * \brief Constructeur - * \~english - * \brief Constructeur - */ - ProjPool(){}; - -public: - - /** - * \~french - * \brief Destructeur - * \~english - * \brief Destructor - */ - ~ProjPool(){}; - - /** - * \~french \brief Retourne un contexte Proj propre au thread appelant - * \details Si il n'existe pas encore de contexte Proj pour ce tread, on le crée et on l'initialise - * \~english \brief Get the Proj context specific to the calling thread - * \details If Proj context doesn't exist for this thread, it is created and initialized - */ - static PJ_CONTEXT* get_proj_env() { - pthread_t i = pthread_self(); - - std::map::iterator it = pool.find ( i ); - if ( it == pool.end() ) { - PJ_CONTEXT* pjc = proj_context_create(); - proj_log_level(pjc, PJ_LOG_NONE); - pool.insert ( std::pair(i,pjc) ); - return pjc; - } else { - return it->second; - } - } - - /** - * \~french \brief Affiche le nombre de contextes proj dans l'annuaire - * \~english \brief Print the number of proj contexts in the book - */ - static void print_projs_count () { - BOOST_LOG_TRIVIAL(info) << "Nombre de contextes proj : " << pool.size() ; - } - - /** - * \~french \brief Nettoie tous les contextes proj dans l'annuaire et le vide - * \~english \brief Clean all proj objects in the book and empty it - */ - static void clean_projs () { - std::map::iterator it; - for (it = pool.begin(); it != pool.end(); ++it) { - proj_context_destroy(it->second); - } - pool.clear(); - } - -}; - - -/** - * \author Institut national de l'information géographique et forestière - * \~french - * \brief Création d'un pool de contextes de stockage - * \details Cette classe est prévue pour être utilisée sans instance - */ -class StoragePool { - -private: - - /** - * \~french - * \brief Constructeur - * \~english - * \brief Constructeur - */ - StoragePool(){}; - - /** - * \~french \brief Annuaire de contextes - * \details La clé est une paire composée du type de stockage et du contenant du contexte - * \~english \brief Book of contexts - * \details Key is a pair composed of type of storage and the context's bucket - */ - static std::map,Context*> pool; - - -public: - - - /** - * \~french \brief Retourne une chaîne de caracère décrivant l'annuaire - * \~english \brief Return a string describing the pool - */ - static std::string to_string() { - std::ostringstream oss; - oss.setf ( std::ios::fixed,std::ios::floatfield ); - oss << "------ Context pool -------" << std::endl; - oss << "\t- context number = " << pool.size() << std::endl; - - std::map, Context*>::iterator it = pool.begin(); - while (it != pool.end()) { - std::pair key = it->first; - oss << "\t\t- pot = " << key.first << "/" << key.second << std::endl; - oss << it->second->to_string() << std::endl; - it++; - } - - return oss.str() ; - } - - /** - * \~french - * \brief Récupère un contexte de stockage - * \details Si un contexte existe déjà pour ce nom de contenant, on ne crée pas de nouveau contexte et on retourne celui déjà existant. Le nouveau contexte n'est pas connecté. - * \param[in] type type de stockage pour lequel on veut créer un contexte - * \param[in] tray Nom du contenant pour lequel on veut créer un contexte - * \param[in] reference_context Contexte de stockage de référence - - * \brief Get a context storage - * \details If a context already exists for this tray's name, we don't create a new one and the existing is returned. New context is not connected. - * \param[in] type Storage Type for which context is created - * \param[in] tray Tray's name for which context is created - * \param[in] reference_context Reference storage context - - */ - static Context * get_context(ContextType::eContextType type,std::string tray, Context* reference_context = 0) ; - - - /** - * \~french \brief Retourne le nombre de contextes de stockage dans l'annuaire par type - * \param[out] file_count Nombre de contexte de stockage fichier - * \param[out] s3_count Nombre de contexte de stockage S3 - * \param[out] ceph_count Nombre de contexte de stockage Ceph - * \param[out] swift_count Nombre de contexte de stockage Swift - * \~english \brief Return the number of storage contexts in the book per type - * \param[out] file_count File storage context count - * \param[out] s3_count S3 storage context count - * \param[out] ceph_count Ceph storage context count - * \param[out] swift_count Swift storage context count - */ - static void get_storages_count (int& file_count, int& s3_count, int& ceph_count, int& swift_count) { - file_count = 0; - s3_count = 0; - ceph_count = 0; - swift_count = 0; - std::map, Context*>::iterator it = pool.begin(); - while (it != pool.end()) { - std::pair key = it->first; - switch(key.first) { -#if CEPH_ENABLED - case ContextType::CEPHCONTEXT: - ceph_count++; - break; -#endif - case ContextType::SWIFTCONTEXT: - swift_count++; - break; - case ContextType::S3CONTEXT: - s3_count++; - break; - case ContextType::FILECONTEXT: - file_count++; - break; - } - it++; - } - } - - /** - * \~french \brief Obtient l'annuaire de contextes - * \details La clé est une paire composée du type de stockage et du contenant du contexte - * \~english \brief Get book of contexts - * \details Key is a pair composed of type of storage and the context's bucket - */ - static std::map,Context*> get_pool() { - return pool; - } - - /** - * \~french - * \brief Destructeur - * \~english - * \brief Destructor - */ - ~StoragePool() {}; - - /** - * \~french \brief Nettoie tous les contextes de stockage dans l'annuaire et le vide - * \~english \brief Clean all storage context objects in the book and empty it - */ - static void clean_storages () { - std::map,Context*>::iterator it; - for (it=pool.begin(); it!=pool.end(); ++it) { - delete it->second; - it->second = NULL; - } - } - -}; - - -/** - * \author Institut national de l'information géographique et forestière - * \~french - * \brief Élément du cache des index de dalle - */ -class IndexElement { -friend class IndexCache; - -protected: - /** - * \~french \brief Date d'enregistrement dans le cache - * \~english \brief Cache date - */ - std::time_t date; - /** - * \~french \brief Clé sous laquelle l'élément est enregistré dans le cache - * \~english \brief Cache key - */ - std::string key; - /** - * \~french \brief Nom de la dalle dans laquelle lire la donnée - * \~english \brief Data slab to read - */ - std::string name; - /** - * \~french \brief Contexte de stockage de la dalle de donnée - * \~english \brief Data slab storage context - */ - Context* context; - /** - * \~french \brief Offsets des tuiles dans la dalle - * \~english \brief Tiles' offsets - */ - std::vector offsets; - /** - * \~french \brief Tailles des tuiles dans la dalle - * \~english \brief Tiles' sizes - */ - std::vector sizes; - - /** \~french - * \brief Constructeur - * \param[in] k clé d'enregistrement dans le cache - * \param[in] s nom de la dalle - * \param[in] c contexte de stockage de la dalle - * \param[in] tiles_number nombre de tuiles dans la dalles - * \param[in] os offsets bruts des tuiles - * \param[in] ss tailles brutes des tuiles - ** \~english - * \brief Constructor - * \param[in] k cache key - * \param[in] s data slab name - * \param[in] c data slab storage context - * \param[in] tiles_number tiles number - * \param[in] os raw tiles' offsets - * \param[in] ss raw tiles' sizes - */ - IndexElement(std::string k, Context* c, std::string n, int tiles_number, uint8_t* os, uint8_t* ss) { - key = k; - context = c; - name = n; - date = std::time(NULL); - for (int i = 0; i < tiles_number; i++) { - offsets.push_back(*((uint32_t*) (os + i*4))); - sizes.push_back(*((uint32_t*) (ss + i*4))); - } - }; -}; - -/** - * \author Institut national de l'information géographique et forestière - * \~french - * \brief Création d'un cache des index de dalle - * \details Cette classe est prévue pour être utilisée sans instance - */ -class IndexCache { - -private: - - /** - * \~french \brief Liste des éléments en cache - * \~english \brief Cache elements list - */ - static std::list cache; - /** - * \~french \brief Map d'index des éléments du cache - * \~english \brief Cache element index map - */ - static std::unordered_map::iterator> map; - /** - * \~french \brief Taille du cache en nombre d'élément - * \details 100 par défaut - * \~english \brief Cache size - * \details Default value : 100 - */ - static int size; - /** - * \~french \brief Durée de validité en seconde d'un élément du cache - * \details 300 par défaut (5 minutes) - * \~english \brief Cache element's validity period, in seconds - * \details Default value : 300 (5 minutes) - */ - static int validity; - - /** - * \~french \brief Exclusion mutuelle - * \details Pour éviter les modifications concurrentes du cache des index - * \~english \brief Mutual exclusion - * \details To avoid concurrent index cache updates - */ - static std::mutex mtx; - - /** - * \~french - * \brief Constructeur - * \~english - * \brief Constructeur - */ - IndexCache(){}; - -public: - - /** - * \~french - * \brief Destructeur - * \~english - * \brief Destructor - */ - ~IndexCache(){}; - - /** \~french - * \brief Définit la taille du cache - * \param[in] s taille du cache - ** \~english - * \brief Define cache size - * \param[in] s cache size - */ - static void setCacheSize(int s) { - size = s; - }; - - /** \~french - * \brief Définit la durée de validité - * \param[in] s durée de validité du cache, en secondes - ** \~english - * \brief Define cache validity - * \param[in] s cache validity, in seconds - */ - static void set_validity(int v) { - validity = v; - }; - - /** \~french - * \brief Ajoute un élément au cache - * \param[in] origin_slab_name nom d'interrogation de la dalle - * \param[in] data_context contexte de stockage de la dalle de donnée - * \param[in] data_slab_name nom de la dalle réelle contenant les données - * \param[in] tiles_number nombre de tuiles dans la dalles - * \param[in] os offsets bruts des tuiles - * \param[in] ss tailles brutes des tuiles - ** \~english - * \brief Add element to cache - * \param[in] origin_slab_name Slab request name - * \param[in] data_context data slab storage context - * \param[in] data_slab_name data slab name - * \param[in] tiles_number tiles number - * \param[in] os raw tiles' offsets - * \param[in] ss raw tiles' sizes - */ - static void add_slab_infos(std::string origin_slab_name, Context* data_context, std::string data_slab_name, int tiles_number, uint8_t* offsets, uint8_t* sizes) { - // On utilise le nom original de la dalle (celle à lire a priori) comme clé dans la map - // Potentiellement ce nom est différent de la vraie dalle contenant la donnée (dans le cas d'une dalle symbolique) - // mais c'est via cette dalle symbolique que la donnée est a priori requêtée - // donc c'est ce nom qu'on utilisera pour l'interrogation du cache - - mtx.lock(); - - IndexElement* elem = new IndexElement(origin_slab_name, data_context, data_slab_name, tiles_number, offsets, sizes); - - // L'information n'est a priori pas dans le cache car - // Soit elle était dans le cache et valide, alors on aurait utilisé ce cache et on n'aurait pas fait appel à cet ajout - // Soit elle était dans le cache mais obsolète, alors on l'aurait déjà supprimé du cache - - if (cache.size() == size) { - // On récupère le dernier élément du cache - IndexElement* last = cache.back(); - // On le vire du cache - cache.pop_back(); - // On le déréférence de la map d'accès - map.erase(last->key); - delete last; - } - - // update reference - cache.push_front(elem); - map[origin_slab_name] = cache.begin(); - - mtx.unlock(); - }; - - /** \~french - * \brief Demande un élément du cache - * \param[in] key nom d'interrogation de la dalle - * \param[in] tile_number numéro de la tuile voulue - * \param[out] data_context contexte de stockage de la dalle de donnée - * \param[out] data_slab_name nom de la dalle contenant les données - * \param[out] offset offset de la tuile - * \param[out] size taille de la tuile - ** \~english - * \brief Ask element from cache - * \param[in] key Slab request name - * \param[in] tile_number tile indice - * \param[out] data_context data slab storage context - * \param[out] data_slab_name Real data slab - * \param[out] offset tile's offset - * \param[out] size tile's size - */ - static bool get_slab_infos(std::string key, int tile_number, Context** data_context, std::string* data_slab_name, uint32_t* offset, uint32_t* size) { - std::unordered_map::iterator>::iterator it = map.find ( key ); - if ( it == map.end() ) { - return false; - } else { - // Gestion de la péremption du cache (une heure max) - std::time_t now = std::time(NULL); - if (now - (*(it->second))->date > validity) { - mtx.lock(); - - // on le cherche à nouveau pour vérifier qu'il n'a pas déjà été supprimé par un thread concurrent - it = map.find ( key ); - - if ( it != map.end() ) { - delete *(it->second); - cache.erase(it->second); - map.erase(it); - } - - mtx.unlock(); - - return false; - } - - *data_slab_name = (*(it->second))->name; - *data_context = (*(it->second))->context; - *offset = (*(it->second))->offsets.at(tile_number); - *size = (*(it->second))->sizes.at(tile_number); - - // On fait le choix de ne pas remettre en tête du cache cet élément, même s'il vient d'être accéder - // C'est parce qu'en plus d'avoir une taille limite, les élément cachés ont une date de péromption - // Il serait donc dommage de remettre en avant (donc plus loin d'une suppression par taille de cache atteinte) - // un élément qui va de toute manière finir par être obsolète. - // C'est une différence avec une cache LRU classique - - return true; - } - }; - - /** - * \~french \brief Nettoie tous les objets dans le cache - * \~english \brief Clean all element from the cache - */ - static void clean_indexes () { - mtx.lock(); - std::list::iterator it; - for (it = cache.begin(); it != cache.end(); ++it) { - delete *it; - } - cache.clear(); - mtx.unlock(); - } -}; - - -/** - * \author Institut national de l'information géographique et forestière - * \~french - * \brief Création d'un annuaire de Tile Matrix Sets - * \details Cette classe est prévue pour être utilisée sans instance - */ -class TmsBook { - -private: - - /** - * \~french - * \brief Constructeur - * \~english - * \brief Constructeur - */ - TmsBook(){}; - - /** - * \~french - * \brief Répertoire de stockage des TMS - * \~english - * \brief TMS storage directory - */ - static std::string directory; - - /** - * \~french \brief Annuaire de TMS - * \details La clé est l'identifiant du TMS - * \~english \brief Book of TMS - * \details Key is a the TMS identifier - */ - static std::map book; - - /** - * \~french \brief Corbeille de TMS à supprimer - * \~english \brief TMS trash to delete - */ - static std::vector trash; - - /** - * \~french \brief Exclusion mutuelle - * \details Pour éviter les modifications concurrentes du cache de TMS - * \~english \brief Mutual exclusion - * \details To avoid concurrent TMS cache updates - */ - static std::mutex mtx; - -public: - - - /** - * \~french \brief Vide l'annuaire et met le contenu à la corbeille - * \~english \brief Empty book and put content into trash - */ - static void send_to_trash () { - mtx.lock(); - std::map::iterator it; - for (it = book.begin(); it != book.end(); ++it) { - trash.push_back(it->second); - } - book.clear(); - mtx.unlock(); - } - - /** - * \~french \brief Vide la corbeille - * \~english \brief Empty trash - */ - static void empty_trash () { - mtx.lock(); - for (int i = 0; i < trash.size(); i++) { - delete trash.at(i); - } - trash.clear(); - mtx.unlock(); - } - - - /** - * \~french \brief Renseigne le répertoire des TMS - * \~english \brief Set TMS directory - */ - static void set_directory (std::string d) { - // Suppression du slash final - if (d.compare ( d.size()-1,1,"/" ) == 0) { - d.pop_back(); - } - directory = d; - } - - /** - * \~french \brief Retourne l'ensemble de l'annuaire - * \~english \brief Return the book - */ - static std::map get_book () { - return book; - } - - /** - * \~french - * \brief Retourne le TMS d'après son identifiant - * \details Si le TMS demandé n'est pas encore dans l'annuaire, ou que l'on ne veut pas de cache, il est recherché dans le répertoire connu et chargé - * \param[in] id Identifiant du TMS voulu - - * \brief Return the TMS according to its identifier - * \details If TMS is still not in the book, or cache is disabled, it is searched in the known directory and loaded - * \param[in] id Wanted TMS identifier - */ - static TileMatrixSet* get_tms(std::string id) { - std::map::iterator it = book.find ( id ); - if ( it != book.end() ) { - return it->second; - } - - std::string d; - if (directory.empty()) { - char* e = getenv (ROK4_TMS_DIRECTORY); - if (e == NULL) { - d.assign("/usr/share/rok4/tilematrixsets"); - } else { - d.assign(e); - } - } else { - d = directory; - } - - std::string tms_path = d + "/" + id; - - mtx.lock(); - // Si on fait du cache de TMS, on revérifie que ce TMS n'a pas déjà été ajouté par un thread concurrent entre temps - if(getenv (ROK4_TMS_NO_CACHE) == NULL) { - if ( it != book.end() ) { - // On a effectivement depuis déjà enregistré ce TMS - return it->second; - } - } - - TileMatrixSet* tms = new TileMatrixSet(tms_path); - if ( ! tms->is_ok() ) { - BOOST_LOG_TRIVIAL(error) << tms->get_error_message(); - delete tms; - mtx.unlock(); - return NULL; - } - - if(getenv (ROK4_TMS_NO_CACHE) == NULL) { - // On veut utiliser le cache, on met donc ce nouveau TMS dans l'annuaire pour le trouver la prochaine fois - book.insert ( std::pair(id, tms) ); - } else { - // On met le TMS directement dans la corbeille, pour que le nettoyage se fasse bien - trash.push_back(tms); - } - - mtx.unlock(); - - return tms; - } - - /** - * \~french \brief Retourne le nombre de TMS dans l'annuaire - * \~english \brief Return the number of TMS in the book - */ - static int get_tms_count () { - return book.size(); - } - - /** - * \~french - * \brief Destructeur - * \~english - * \brief Destructor - */ - ~TmsBook() {}; - -}; - - -/** - * \author Institut national de l'information géographique et forestière - * \~french - * \brief Création d'un annuaire de styles - * \details Cette classe est prévue pour être utilisée sans instance - */ -class StyleBook { - -private: - - /** - * \~french - * \brief Constructeur - * \~english - * \brief Constructeur - */ - StyleBook(){}; - - /** - * \~french - * \brief Répertoire de stockage des styles - * \~english - * \brief TMS storage directory - */ - static std::string directory; - - /** - * \~french \brief Annuaire de styles - * \details La clé est l'identifiant du style - * \~english \brief Book of styles - * \details Key is a the style identifier - */ - static std::map book; - - /** - * \~french \brief Corbeille de styles à supprimer - * \~english \brief Styles trash to delete - */ - static std::vector trash; - - /** - * \~french \brief Exclusion mutuelle - * \details Pour éviter les modifications concurrentes du cache de styles - * \~english \brief Mutual exclusion - * \details To avoid concurrent styles cache updates - */ - static std::mutex mtx; - -public: - - - /** - * \~french \brief Vide l'annuaire et met le contenu à la corbeille - * \~english \brief Empty book and put content into trash - */ - static void send_to_trash () { - mtx.lock(); - std::map::iterator it; - for (it = book.begin(); it != book.end(); ++it) { - trash.push_back(it->second); - } - book.clear(); - mtx.unlock(); - } - - /** - * \~french \brief Vide la corbeille - * \~english \brief Empty trash - */ - static void empty_trash () { - mtx.lock(); - for (int i = 0; i < trash.size(); i++) { - delete trash.at(i); - } - trash.clear(); - mtx.unlock(); - } - - - /** - * \~french \brief Renseigne le répertoire des style - * \~english \brief Set styles directory - */ - static void set_directory (std::string d) { - // Suppression du slash final - if (d.compare ( d.size()-1,1,"/" ) == 0) { - d.pop_back(); - } - directory = d; - } - - /** - * \~french \brief Retourne l'ensemble de l'annuaire - * \~english \brief Return the book - */ - static std::map get_book () { - return book; - } - - /** - * \~french - * \brief Retourne le style d'après son identifiant - * \details Si le style demandé n'est pas encore dans l'annuaire, ou que l'on ne veut pas de cache, il est recherché dans le répertoire connu et chargé - * \param[in] id Identifiant du style voulu - - * \brief Return the style according to its identifier - * \details If style is still not in the book, or cache is disabled, it is searched in the known directory and loaded - * \param[in] id Wanted style identifier - */ - static Style* get_style(std::string id) { - - std::map::iterator it = book.find ( id ); - if ( it != book.end() ) { - return it->second; - } - - std::string d; - if (directory.empty()) { - char* e = getenv (ROK4_STYLES_DIRECTORY); - if (e == NULL) { - d.assign("/usr/share/rok4/styles"); - } else { - d.assign(e); - } - } else { - d = directory; - } - - std::string style_path = d + "/" + id; - - mtx.lock(); - // Si on fait du cache de style, on revérifie que ce style n'a pas déjà été ajouté par un thread concurrent entre temps - if(getenv (ROK4_STYLES_NO_CACHE) == NULL) { - if ( it != book.end() ) { - // On a effectivement depuis déjà enregistré ce style - return it->second; - } - } - - Style* style = new Style(style_path); - if ( ! style->is_ok() ) { - BOOST_LOG_TRIVIAL(error) << style->get_error_message(); - delete style; - mtx.unlock(); - return NULL; - } - - if ( contain_chars(style->get_identifier(), "<>") ) { - BOOST_LOG_TRIVIAL(error) << "Style identifier contains forbidden chars" ; - delete style; - mtx.unlock(); - return NULL; - } - - if(getenv (ROK4_STYLES_NO_CACHE) == NULL) { - // On veut utiliser le cache, on met donc ce nouveau style dans l'annuaire pour le trouver la porchaine fois - book.insert ( std::pair(id, style) ); - } else { - // On met le style directement dans la corbeille, pour que le nettoyage se fasse bien - trash.push_back(style); - } - - mtx.unlock(); - return style; - } - - /** - * \~french \brief Retourne le nombre de styles dans l'annuaire - * \~english \brief Return the number of styles in the book - */ - static int get_styles_count () { - return book.size(); - } - - /** - * \~french - * \brief Destructeur - * \~english - * \brief Destructor - */ - ~StyleBook() {}; - -}; - - -/** - * \author Institut national de l'information géographique et forestière - * \~french - * \brief Création d'un annuaire de CRS - * \details Cette classe est prévue pour être utilisée sans instance - */ -class CrsBook { - -private: - - /** - * \~french - * \brief Constructeur - * \~english - * \brief Constructeur - */ - CrsBook(){}; - - /** - * \~french \brief Annuaire de styles - * \details La clé est l'identifiant du style - * \~english \brief Book of styles - * \details Key is a the style identifier - */ - static std::map book; - - /** - * \~french \brief Exclusion mutuelle - * \details Pour éviter les modifications concurrentes du cache de CRS - * \~english \brief Mutual exclusion - * \details To avoid concurrent CRS cache updates - */ - static std::mutex mtx; - -public: - - - /** - * \~french - * \brief Retourne le CRS d'après son identifiant (code de requête) - * \param[in] id Identifiant du CRS voulu - - * \brief Return the style according to its identifier - * \param[in] id Wanted style identifier - */ - static CRS* get_crs(std::string id) { - - id = to_upper_case(id); - - std::map::iterator it = book.find ( id ); - if ( it != book.end() ) { - return it->second; - } - - mtx.lock(); - - CRS* crs = new CRS(id); - // Le CRS est potentiellement non défini (si il n'est pas valide), on le mémorise pour ne pas réessayer la prochaine fois - book.emplace(id, crs); - - mtx.unlock(); - return crs; - } - - /** - * \~french \brief Nettoie tous les CRS dans l'annuaire et le vide - * \~english \brief Clean all CRS objects in the book and empty it - */ - static void clean_crss () { - mtx.lock(); - std::map::iterator it; - for (it = book.begin(); it != book.end(); ++it) { - delete it->second; - } - book.clear(); - mtx.unlock(); - } - - /** - * \~french - * \brief Destructeur - * \~english - * \brief Destructor - */ - ~CrsBook() {}; - -}; - - diff --git a/include/rok4/utils/CrsBook.h b/include/rok4/utils/CrsBook.h new file mode 100644 index 00000000..6c608760 --- /dev/null +++ b/include/rok4/utils/CrsBook.h @@ -0,0 +1,117 @@ +/* + * Copyright © (2011) Institut national de l'information + * géographique et forestière + * + * Géoportail SAV + * + * This software is a computer program whose purpose is to publish geographic + * data using OGC WMS and WMTS protocol. + * + * This software is governed by the CeCILL-C license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-C + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * + * knowledge of the CeCILL-C license and that you accept its terms. + */ + +/** + * \file CrsBook.h + ** \~french + * \brief Définition de la classe CrsBook + ** \~english + * \brief Define classe CrsBook + */ + +#pragma once + +#include +#include +#include +#include + +#include "rok4/utils/CRS.h" +/** + * \author Institut national de l'information géographique et forestière + * \~french + * \brief Création d'un annuaire de CRS + * \details Cette classe est prévue pour être utilisée sans instance + */ +class CrsBook { + +private: + + /** + * \~french + * \brief Constructeur + * \~english + * \brief Constructeur + */ + CrsBook(); + + /** + * \~french \brief Annuaire de styles + * \details La clé est l'identifiant du style + * \~english \brief Book of styles + * \details Key is a the style identifier + */ + static std::map book; + + /** + * \~french \brief Exclusion mutuelle + * \details Pour éviter les modifications concurrentes du cache de CRS + * \~english \brief Mutual exclusion + * \details To avoid concurrent CRS cache updates + */ + static std::mutex mtx; + +public: + + + /** + * \~french + * \brief Retourne le CRS d'après son identifiant (code de requête) + * \param[in] id Identifiant du CRS voulu + + * \brief Return the style according to its identifier + * \param[in] id Wanted style identifier + */ + static CRS* get_crs(std::string id); + + /** + * \~french \brief Nettoie tous les CRS dans l'annuaire et le vide + * \~english \brief Clean all CRS objects in the book and empty it + */ + static void clean_crss (); + + /** + * \~french + * \brief Destructeur + * \~english + * \brief Destructor + */ + ~CrsBook(); + +}; + + diff --git a/include/rok4/utils/CurlPool.h b/include/rok4/utils/CurlPool.h new file mode 100644 index 00000000..0f239b18 --- /dev/null +++ b/include/rok4/utils/CurlPool.h @@ -0,0 +1,101 @@ +/* + * Copyright © (2011) Institut national de l'information + * géographique et forestière + * + * Géoportail SAV + * + * This software is a computer program whose purpose is to publish geographic + * data using OGC WMS and WMTS protocol. + * + * This software is governed by the CeCILL-C license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-C + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * + * knowledge of the CeCILL-C license and that you accept its terms. + */ + +#pragma once + +#include +#include +#include +#include + +/** + * \author Institut national de l'information géographique et forestière + * \~french + * \brief Création d'un pool d'environnement Curl + * \details Cette classe est prévue pour être utilisée sans instance + */ +class CurlPool { + +private: + + /** + * \~french \brief Annuaire des objet Curl + * \details La clé est l'identifiant du thread + * \~english \brief Curl object book + * \details Key is the thread's ID + */ + static std::map pool; + + /** + * \~french + * \brief Constructeur + * \~english + * \brief Constructeur + */ + CurlPool(){}; + +public: + + /** + * \~french + * \brief Destructeur + * \~english + * \brief Destructor + */ + ~CurlPool(); + + /** + * \~french \brief Retourne un objet Curl propre au thread appelant + * \details Si il n'existe pas encore d'objet curl pour ce tread, on le crée et on l'initialise + * \~english \brief Get the curl object specific to the calling thread + * \details If curl object doesn't exist for this thread, it is created and initialized + */ + static CURL* get_curl_env(); + + /** + * \~french \brief Affiche le nombre d'objet curl dans l'annuaire + * \~english \brief Print the number of curl objects in the book + */ + static void print_curls_count (); + + /** + * \~french \brief Nettoie tous les objets curl dans l'annuaire et le vide + * \~english \brief Clean all curl objects in the book and empty it + */ + static void clean_curls (); + +}; diff --git a/include/rok4/utils/IndexCache.h b/include/rok4/utils/IndexCache.h new file mode 100644 index 00000000..37080b9f --- /dev/null +++ b/include/rok4/utils/IndexCache.h @@ -0,0 +1,182 @@ +/* + * Copyright © (2011) Institut national de l'information + * géographique et forestière + * + * Géoportail SAV + * + * This software is a computer program whose purpose is to publish geographic + * data using OGC WMS and WMTS protocol. + * + * This software is governed by the CeCILL-C license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-C + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * + * knowledge of the CeCILL-C license and that you accept its terms. + */ + +/** + * \file IndexCache.h + ** \~french + * \brief Définition de la classes IndexCache + ** \~english + * \brief Define classe IndexCache + */ + +#pragma once + +#include // pour uint8_t +#include +#include +#include +#include +#include +#include +#include + +#include "rok4/utils/IndexElement.h" +#include "rok4/storage/Context.h" + +/** + * \author Institut national de l'information géographique et forestière + * \~french + * \brief Création d'un cache des index de dalle + * \details Cette classe est prévue pour être utilisée sans instance + */ +class IndexCache { + +private: + + /** + * \~french \brief Liste des éléments en cache + * \~english \brief Cache elements list + */ + static std::list cache; + /** + * \~french \brief Map d'index des éléments du cache + * \~english \brief Cache element index map + */ + static std::unordered_map::iterator> map; + /** + * \~french \brief Taille du cache en nombre d'élément + * \details 100 par défaut + * \~english \brief Cache size + * \details Default value : 100 + */ + static int size; + /** + * \~french \brief Durée de validité en seconde d'un élément du cache + * \details 300 par défaut (5 minutes) + * \~english \brief Cache element's validity period, in seconds + * \details Default value : 300 (5 minutes) + */ + static int validity; + + /** + * \~french \brief Exclusion mutuelle + * \details Pour éviter les modifications concurrentes du cache des index + * \~english \brief Mutual exclusion + * \details To avoid concurrent index cache updates + */ + static std::mutex mtx; + + /** + * \~french + * \brief Constructeur + * \~english + * \brief Constructeur + */ + IndexCache(); + +public: + + /** + * \~french + * \brief Destructeur + * \~english + * \brief Destructor + */ + ~IndexCache(); + + /** \~french + * \brief Définit la taille du cache + * \param[in] s taille du cache + ** \~english + * \brief Define cache size + * \param[in] s cache size + */ + static void setCacheSize(int s); + + /** \~french + * \brief Définit la durée de validité + * \param[in] s durée de validité du cache, en secondes + ** \~english + * \brief Define cache validity + * \param[in] s cache validity, in seconds + */ + static void set_validity(int v); + + /** \~french + * \brief Ajoute un élément au cache + * \param[in] origin_slab_name nom d'interrogation de la dalle + * \param[in] data_context contexte de stockage de la dalle de donnée + * \param[in] data_slab_name nom de la dalle réelle contenant les données + * \param[in] tiles_number nombre de tuiles dans la dalles + * \param[in] os offsets bruts des tuiles + * \param[in] ss tailles brutes des tuiles + ** \~english + * \brief Add element to cache + * \param[in] origin_slab_name Slab request name + * \param[in] data_context data slab storage context + * \param[in] data_slab_name data slab name + * \param[in] tiles_number tiles number + * \param[in] os raw tiles' offsets + * \param[in] ss raw tiles' sizes + */ + static void add_slab_infos(std::string origin_slab_name, Context* data_context, std::string data_slab_name, int tiles_number, uint8_t* offsets, uint8_t* sizes); + + /** \~french + * \brief Demande un élément du cache + * \param[in] key nom d'interrogation de la dalle + * \param[in] tile_number numéro de la tuile voulue + * \param[out] data_context contexte de stockage de la dalle de donnée + * \param[out] data_slab_name nom de la dalle contenant les données + * \param[out] offset offset de la tuile + * \param[out] size taille de la tuile + ** \~english + * \brief Ask element from cache + * \param[in] key Slab request name + * \param[in] tile_number tile indice + * \param[out] data_context data slab storage context + * \param[out] data_slab_name Real data slab + * \param[out] offset tile's offset + * \param[out] size tile's size + */ + static bool get_slab_infos(std::string key, int tile_number, Context** data_context, std::string* data_slab_name, uint32_t* offset, uint32_t* size); + + /** + * \~french \brief Nettoie tous les objets dans le cache + * \~english \brief Clean all element from the cache + */ + static void clean_indexes (); +}; \ No newline at end of file diff --git a/include/rok4/utils/IndexElement.h b/include/rok4/utils/IndexElement.h new file mode 100644 index 00000000..591619cb --- /dev/null +++ b/include/rok4/utils/IndexElement.h @@ -0,0 +1,112 @@ +/* + * Copyright © (2011) Institut national de l'information + * géographique et forestière + * + * Géoportail SAV + * + * This software is a computer program whose purpose is to publish geographic + * data using OGC WMS and WMTS protocol. + * + * This software is governed by the CeCILL-C license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-C + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * + * knowledge of the CeCILL-C license and that you accept its terms. + */ + +/** + * \file IndexElement.h + ** \~french + * \brief Définition de la classe IndexElement + ** \~english + * \brief Define classe IndexElement + */ + +#pragma once + +#include +#include +#include + +#include "rok4/storage/Context.h" + +/** + * \author Institut national de l'information géographique et forestière + * \~french + * \brief Élément du cache des index de dalle + */ +class IndexElement { +friend class IndexCache; + +protected: + /** + * \~french \brief Date d'enregistrement dans le cache + * \~english \brief Cache date + */ + std::time_t date; + /** + * \~french \brief Clé sous laquelle l'élément est enregistré dans le cache + * \~english \brief Cache key + */ + std::string key; + /** + * \~french \brief Nom de la dalle dans laquelle lire la donnée + * \~english \brief Data slab to read + */ + std::string name; + /** + * \~french \brief Contexte de stockage de la dalle de donnée + * \~english \brief Data slab storage context + */ + Context* context; + /** + * \~french \brief Offsets des tuiles dans la dalle + * \~english \brief Tiles' offsets + */ + std::vector offsets; + /** + * \~french \brief Tailles des tuiles dans la dalle + * \~english \brief Tiles' sizes + */ + std::vector sizes; + + /** \~french + * \brief Constructeur + * \param[in] k clé d'enregistrement dans le cache + * \param[in] s nom de la dalle + * \param[in] c contexte de stockage de la dalle + * \param[in] tiles_number nombre de tuiles dans la dalles + * \param[in] os offsets bruts des tuiles + * \param[in] ss tailles brutes des tuiles + ** \~english + * \brief Constructor + * \param[in] k cache key + * \param[in] s data slab name + * \param[in] c data slab storage context + * \param[in] tiles_number tiles number + * \param[in] os raw tiles' offsets + * \param[in] ss raw tiles' sizes + */ + IndexElement(std::string k, Context* c, std::string n, int tiles_number, uint8_t* os, uint8_t* ss); +}; \ No newline at end of file diff --git a/include/rok4/utils/Level.h b/include/rok4/utils/Level.h index f7735902..f695597e 100644 --- a/include/rok4/utils/Level.h +++ b/include/rok4/utils/Level.h @@ -53,7 +53,6 @@ class Level; #include "rok4/utils/Configuration.h" #include "rok4/utils/Level.h" #include "rok4/utils/Table.h" -#include "rok4/utils/Cache.h" /** */ diff --git a/include/rok4/utils/LibcurlStruct.h b/include/rok4/utils/LibcurlStruct.h index 4948f594..2d7ae56d 100644 --- a/include/rok4/utils/LibcurlStruct.h +++ b/include/rok4/utils/LibcurlStruct.h @@ -49,6 +49,10 @@ #define ROK4_SSL_NO_VERIFY "ROK4_SSL_NO_VERIFY" #endif +#ifndef ROK4_NETWORK_TIMEOUT +#define ROK4_NETWORK_TIMEOUT "ROK4_NETWORK_TIMEOUT" +#endif + #include struct HeaderStruct { @@ -131,4 +135,13 @@ static bool get_ssl_no_verify() { return getenv(ROK4_SSL_NO_VERIFY) != NULL; } +static int get_timeout() { + + int t; + char* e = getenv (ROK4_NETWORK_TIMEOUT); + if (e == NULL || sscanf ( e, "%d", &t ) != 1 ) { + t = 0; + } + return t; +} diff --git a/include/rok4/utils/ProjPool.h b/include/rok4/utils/ProjPool.h new file mode 100644 index 00000000..71a83385 --- /dev/null +++ b/include/rok4/utils/ProjPool.h @@ -0,0 +1,99 @@ +/* + * Copyright © (2011) Institut national de l'information + * géographique et forestière + * + * Géoportail SAV + * + * This software is a computer program whose purpose is to publish geographic + * data using OGC WMS and WMTS protocol. + * + * This software is governed by the CeCILL-C license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-C + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * + * knowledge of the CeCILL-C license and that you accept its terms. + */ + +#pragma once + +#include +#include +#include + +/** + * \author Institut national de l'information géographique et forestière + * \~french + * \brief Création d'un pool de contextes Proj + * \details Cette classe est prévue pour être utilisée sans instance + */ +class ProjPool { + +private: + + /** + * \~french \brief Annuaire des contextes Proj + * \details La clé est l'identifiant du thread + * \~english \brief Proj contexts book + * \details Key is the thread's ID + */ + static std::map pool; + + /** + * \~french + * \brief Constructeur + * \~english + * \brief Constructeur + */ + ProjPool(); + +public: + + /** + * \~french + * \brief Destructeur + * \~english + * \brief Destructor + */ + ~ProjPool(); + + /** + * \~french \brief Retourne un contexte Proj propre au thread appelant + * \details Si il n'existe pas encore de contexte Proj pour ce tread, on le crée et on l'initialise + * \~english \brief Get the Proj context specific to the calling thread + * \details If Proj context doesn't exist for this thread, it is created and initialized + */ + static PJ_CONTEXT* get_proj_env(); + + /** + * \~french \brief Affiche le nombre de contextes proj dans l'annuaire + * \~english \brief Print the number of proj contexts in the book + */ + static void print_projs_count (); + + /** + * \~french \brief Nettoie tous les contextes proj dans l'annuaire et le vide + * \~english \brief Clean all proj objects in the book and empty it + */ + static void clean_projs (); +}; diff --git a/include/rok4/utils/Pyramid.h b/include/rok4/utils/Pyramid.h index 42149baa..ea05370f 100644 --- a/include/rok4/utils/Pyramid.h +++ b/include/rok4/utils/Pyramid.h @@ -49,7 +49,7 @@ class Pyramid; #include "rok4/style/Style.h" #include "rok4/enums/Interpolation.h" #include "rok4/utils/Configuration.h" -#include "rok4/utils/Cache.h" +#include "rok4/utils/TmsBook.h" #include "rok4/storage/Context.h" #define DEFAULT_NODATAVALUE 255 diff --git a/include/rok4/utils/StoragePool.h b/include/rok4/utils/StoragePool.h new file mode 100644 index 00000000..c3f6e04e --- /dev/null +++ b/include/rok4/utils/StoragePool.h @@ -0,0 +1,136 @@ +/* + * Copyright © (2011) Institut national de l'information + * géographique et forestière + * + * Géoportail SAV + * + * This software is a computer program whose purpose is to publish geographic + * data using OGC WMS and WMTS protocol. + * + * This software is governed by the CeCILL-C license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-C + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * + * knowledge of the CeCILL-C license and that you accept its terms. + */ + +#pragma once + +#include "rok4/utils/StyleBook.h" +#include "rok4/storage/Context.h" + +#if CEPH_ENABLED + #include "storage/ceph/CephPoolContext.h" +#endif + +/** + * \author Institut national de l'information géographique et forestière + * \~french + * \brief Création d'un pool de contextes de stockage + * \details Cette classe est prévue pour être utilisée sans instance + */ +class StoragePool { + +private: + + /** + * \~french + * \brief Constructeur + * \~english + * \brief Constructeur + */ + StoragePool(); + + /** + * \~french \brief Annuaire de contextes + * \details La clé est une paire composée du type de stockage et du contenant du contexte + * \~english \brief Book of contexts + * \details Key is a pair composed of type of storage and the context's bucket + */ + static std::map,Context*> pool; + + +public: + + + /** + * \~french \brief Retourne une chaîne de caracère décrivant l'annuaire + * \~english \brief Return a string describing the pool + */ + static std::string to_string(); + + /** + * \~french + * \brief Récupère un contexte de stockage + * \details Si un contexte existe déjà pour ce nom de contenant, on ne crée pas de nouveau contexte et on retourne celui déjà existant. Le nouveau contexte n'est pas connecté. + * \param[in] type type de stockage pour lequel on veut créer un contexte + * \param[in] tray Nom du contenant pour lequel on veut créer un contexte + * \param[in] reference_context Contexte de stockage de référence + + * \brief Get a context storage + * \details If a context already exists for this tray's name, we don't create a new one and the existing is returned. New context is not connected. + * \param[in] type Storage Type for which context is created + * \param[in] tray Tray's name for which context is created + * \param[in] reference_context Reference storage context + + */ + static Context * get_context(ContextType::eContextType type,std::string tray, Context* reference_context = 0) ; + + + /** + * \~french \brief Retourne le nombre de contextes de stockage dans l'annuaire par type + * \param[out] file_count Nombre de contexte de stockage fichier + * \param[out] s3_count Nombre de contexte de stockage S3 + * \param[out] ceph_count Nombre de contexte de stockage Ceph + * \param[out] swift_count Nombre de contexte de stockage Swift + * \~english \brief Return the number of storage contexts in the book per type + * \param[out] file_count File storage context count + * \param[out] s3_count S3 storage context count + * \param[out] ceph_count Ceph storage context count + * \param[out] swift_count Swift storage context count + */ + static void get_storages_count (int& file_count, int& s3_count, int& ceph_count, int& swift_count); + + /** + * \~french \brief Obtient l'annuaire de contextes + * \details La clé est une paire composée du type de stockage et du contenant du contexte + * \~english \brief Get book of contexts + * \details Key is a pair composed of type of storage and the context's bucket + */ + static std::map,Context*> get_pool(); + + /** + * \~french + * \brief Destructeur + * \~english + * \brief Destructor + */ + ~StoragePool(); + + /** + * \~french \brief Nettoie tous les contextes de stockage dans l'annuaire et le vide + * \~english \brief Clean all storage context objects in the book and empty it + */ + static void clean_storages (); +}; \ No newline at end of file diff --git a/include/rok4/utils/StyleBook.h b/include/rok4/utils/StyleBook.h new file mode 100644 index 00000000..53e6c95a --- /dev/null +++ b/include/rok4/utils/StyleBook.h @@ -0,0 +1,164 @@ +/* + * Copyright © (2011) Institut national de l'information + * géographique et forestière + * + * Géoportail SAV + * + * This software is a computer program whose purpose is to publish geographic + * data using OGC WMS and WMTS protocol. + * + * This software is governed by the CeCILL-C license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-C + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * + * knowledge of the CeCILL-C license and that you accept its terms. + */ + +/** + * \file StyleBook.h + ** \~french + * \brief Définition de la classe StyleBook + ** \~english + * \brief Define classe StyleBook + */ + +#pragma once + +#include +#include +#include +#include +#include +#include + +#include "rok4/style/Style.h" +#include "rok4/utils/Utils.h" + +#define ROK4_STYLES_DIRECTORY "ROK4_STYLES_DIRECTORY" +#define ROK4_STYLES_NO_CACHE "ROK4_STYLES_NO_CACHE" + + +/** + * \author Institut national de l'information géographique et forestière + * \~french + * \brief Création d'un annuaire de styles + * \details Cette classe est prévue pour être utilisée sans instance + */ +class StyleBook { + +private: + + /** + * \~french + * \brief Constructeur + * \~english + * \brief Constructeur + */ + StyleBook(); + + /** + * \~french + * \brief Répertoire de stockage des styles + * \~english + * \brief TMS storage directory + */ + static std::string directory; + + /** + * \~french \brief Annuaire de styles + * \details La clé est l'identifiant du style + * \~english \brief Book of styles + * \details Key is a the style identifier + */ + static std::map book; + + /** + * \~french \brief Corbeille de styles à supprimer + * \~english \brief Styles trash to delete + */ + static std::vector trash; + + /** + * \~french \brief Exclusion mutuelle + * \details Pour éviter les modifications concurrentes du cache de styles + * \~english \brief Mutual exclusion + * \details To avoid concurrent styles cache updates + */ + static std::mutex mtx; + +public: + + + /** + * \~french \brief Vide l'annuaire et met le contenu à la corbeille + * \~english \brief Empty book and put content into trash + */ + static void send_to_trash (); + + /** + * \~french \brief Vide la corbeille + * \~english \brief Empty trash + */ + static void empty_trash (); + + + /** + * \~french \brief Renseigne le répertoire des style + * \~english \brief Set styles directory + */ + static void set_directory (std::string d); + + /** + * \~french \brief Retourne l'ensemble de l'annuaire + * \~english \brief Return the book + */ + static std::map get_book (); + + /** + * \~french + * \brief Retourne le style d'après son identifiant + * \details Si le style demandé n'est pas encore dans l'annuaire, ou que l'on ne veut pas de cache, il est recherché dans le répertoire connu et chargé + * \param[in] id Identifiant du style voulu + + * \brief Return the style according to its identifier + * \details If style is still not in the book, or cache is disabled, it is searched in the known directory and loaded + * \param[in] id Wanted style identifier + */ + static Style* get_style(std::string id); + + /** + * \~french \brief Retourne le nombre de styles dans l'annuaire + * \~english \brief Return the number of styles in the book + */ + static int get_styles_count (); + + /** + * \~french + * \brief Destructeur + * \~english + * \brief Destructor + */ + ~StyleBook(); + +}; \ No newline at end of file diff --git a/include/rok4/utils/TileMatrixSet.h b/include/rok4/utils/TileMatrixSet.h index fd6ea72b..18f1616c 100644 --- a/include/rok4/utils/TileMatrixSet.h +++ b/include/rok4/utils/TileMatrixSet.h @@ -52,9 +52,8 @@ #include #include "rok4/utils/TileMatrix.h" -#include "rok4/utils/CRS.h" -#include "rok4/utils/Keyword.h" -#include "rok4/utils/Configuration.h" +#include "rok4/utils/CrsBook.h" +#include "rok4/utils/StoragePool.h" typedef std::function, std::pair)> ComparatorTileMatrix; @@ -96,6 +95,7 @@ typedef std::function, std::pair + * + * This software is a computer program whose purpose is to publish geographic + * data using OGC WMS and WMTS protocol. + * + * This software is governed by the CeCILL-C license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-C + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * + * knowledge of the CeCILL-C license and that you accept its terms. + */ + +/** + * \file TmsBook.h + ** \~french + * \brief Définition de la classe TmsBook + ** \~english + * \brief Define classe TmsBook + */ + +#pragma once + +#include +#include +#include +#include +#include + +#include "rok4/utils/TileMatrixSet.h" + +#define ROK4_TMS_DIRECTORY "ROK4_TMS_DIRECTORY" +#define ROK4_TMS_NO_CACHE "ROK4_TMS_NO_CACHE" + +/** + * \author Institut national de l'information géographique et forestière + * \~french + * \brief Création d'un annuaire de Tile Matrix Sets + * \details Cette classe est prévue pour être utilisée sans instance + */ +class TmsBook { + +private: + + /** + * \~french + * \brief Constructeur + * \~english + * \brief Constructeur + */ + TmsBook(); + + /** + * \~french + * \brief Répertoire de stockage des TMS + * \~english + * \brief TMS storage directory + */ + static std::string directory; + + /** + * \~french \brief Annuaire de TMS + * \details La clé est l'identifiant du TMS + * \~english \brief Book of TMS + * \details Key is a the TMS identifier + */ + static std::map book; + + /** + * \~french \brief Corbeille de TMS à supprimer + * \~english \brief TMS trash to delete + */ + static std::vector trash; + + /** + * \~french \brief Exclusion mutuelle + * \details Pour éviter les modifications concurrentes du cache de TMS + * \~english \brief Mutual exclusion + * \details To avoid concurrent TMS cache updates + */ + static std::mutex mtx; + +public: + + + /** + * \~french \brief Vide l'annuaire et met le contenu à la corbeille + * \~english \brief Empty book and put content into trash + */ + static void send_to_trash (); + + /** + * \~french \brief Vide la corbeille + * \~english \brief Empty trash + */ + static void empty_trash (); + + + /** + * \~french \brief Renseigne le répertoire des TMS + * \~english \brief Set TMS directory + */ + static void set_directory (std::string d); + + /** + * \~french \brief Retourne l'ensemble de l'annuaire + * \~english \brief Return the book + */ + static std::map get_book (); + + /** + * \~french + * \brief Retourne le TMS d'après son identifiant + * \details Si le TMS demandé n'est pas encore dans l'annuaire, ou que l'on ne veut pas de cache, il est recherché dans le répertoire connu et chargé + * \param[in] id Identifiant du TMS voulu + + * \brief Return the TMS according to its identifier + * \details If TMS is still not in the book, or cache is disabled, it is searched in the known directory and loaded + * \param[in] id Wanted TMS identifier + */ + static TileMatrixSet* get_tms(std::string id); + + /** + * \~french \brief Retourne le nombre de TMS dans l'annuaire + * \~english \brief Return the number of TMS in the book + */ + static int get_tms_count (); + + /** + * \~french + * \brief Destructeur + * \~english + * \brief Destructor + */ + ~TmsBook(); + +}; \ No newline at end of file diff --git a/src/datasource/StoreDataSource.cpp b/src/datasource/StoreDataSource.cpp index d60e7fa2..b9c9f19a 100644 --- a/src/datasource/StoreDataSource.cpp +++ b/src/datasource/StoreDataSource.cpp @@ -52,7 +52,6 @@ #include #include #include -#include "utils/Cache.h" #include "enums/Format.h" #include "storage/Context.h" diff --git a/src/datasource/StoreDataSource.h b/src/datasource/StoreDataSource.h index 79e916e0..0421fc9e 100644 --- a/src/datasource/StoreDataSource.h +++ b/src/datasource/StoreDataSource.h @@ -54,6 +54,8 @@ #include "datasource/DataSource.h" #include "storage/Context.h" +#include "rok4/utils/StoragePool.h" +#include "rok4/utils/IndexCache.h" /** * \author Institut national de l'information géographique et forestière diff --git a/src/image/AspectImage.cpp b/src/image/AspectImage.cpp deleted file mode 100644 index ba01edc1..00000000 --- a/src/image/AspectImage.cpp +++ /dev/null @@ -1,184 +0,0 @@ -/* - * Copyright © (2011) Institut national de l'information - * géographique et forestière - * - * Géoportail SAV - * - * This software is a computer program whose purpose is to publish geographic - * data using OGC WMS and WMTS protocol. - * - * This software is governed by the CeCILL-C license under French law and - * abiding by the rules of distribution of free software. You can use, - * modify and/ or redistribute the software under the terms of the CeCILL-C - * license as circulated by CEA, CNRS and INRIA at the following URL - * "http://www.cecill.info". - * - * As a counterpart to the access to the source code and rights to copy, - * modify and redistribute granted by the license, users are provided only - * with a limited warranty and the software's author, the holder of the - * economic rights, and the successive licensors have only limited - * liability. - * - * In this respect, the user's attention is drawn to the risks associated - * with loading, using, modifying and/or developing or reproducing the - * software by the user in light of its specific status of free software, - * that may mean that it is complicated to manipulate, and that also - * therefore means that it is reserved for developers and experienced - * professionals having in-depth computer knowledge. Users are therefore - * encouraged to load and test the software's suitability as regards their - * requirements in conditions enabling the security of their systems and/or - * data to be ensured and, more generally, to use and operate it in the - * same conditions as regards security. - * - * The fact that you are presently reading this means that you have had - * - * knowledge of the CeCILL-C license and that you accept its terms. - */ - -#include "image/AspectImage.h" - -#include - -#include "utils/Utils.h" -#include -#include -#define DEG_TO_RAD .0174532925199432958 -#include - -int AspectImage::get_line ( float* buffer, int line ) { - return _getline ( buffer, line ); -} - -int AspectImage::get_line ( uint16_t* buffer, int line ) { - return _getline ( buffer, line ); -} - -int AspectImage::get_line ( uint8_t* buffer, int line ) { - return _getline ( buffer, line ); -} - -//definition des variables -AspectImage::AspectImage (Image* image, Aspect* asp) : - Image ( image->get_width() - 2, image->get_height() - 2, 1 ), - source_image ( image ), resolution (image->get_mean_resolution()), aspect(asp) - { - - // On réduit la bbox d'un pixel de chaque côté - BoundingBox bb = source_image->get_bbox(); - bb.xmin += source_image->get_resx(); - bb.ymin += source_image->get_resy(); - bb.xmax -= source_image->get_resx(); - bb.ymax -= source_image->get_resy(); - set_bbox(bb); - - set_crs(source_image->get_crs()); - - // Buffer de lignes sources - memorized_source_lines = 3; - - source_lines = new int[memorized_source_lines]; - for (int i = 0; i < memorized_source_lines; i++) { - source_lines[i] = -1; - } - source_lines_buffer = new float[source_image->get_width() * memorized_source_lines]; - - matrix[0] = 1 / (8.0*resolution) ; - matrix[1] = 2 / (8.0*resolution) ; - matrix[2] = 1 / (8.0*resolution) ; - - matrix[3] = 2 / (8.0*resolution) ; - matrix[4] = 0 ; - matrix[5] = 2 / (8.0*resolution) ; - - matrix[6] = 1 / (8.0*resolution) ; - matrix[7] = 2 / (8.0*resolution) ; - matrix[8] = 1 / (8.0*resolution) ; -} - -AspectImage::~AspectImage() { - delete source_image; - delete[] source_lines; - delete[] source_lines_buffer; -} - - -template -int AspectImage::_getline ( T* buffer, int line ) { - // L'image source fait une ligne de plus en haut et en bas (ligne 0 de l'image estompée = ligne 1 de l'image source) - // et une colonne de plus à gauche et à droite - // Pour obtenir la ligne 0 de l'image aspect, on a besoin des lignes 0, 1 et 2 de l'image source - // Plus généralement, pour avoir la ligne n de l'image aspect, on a besoin des lignes - // n, n+1 et n+2 de l'image source - - // On range les lignes sources dans un buffer qui peut en stocker 3 - // La ligne source n est stockée en (n % memorized_source_lines) ème position - - // calcul des emplacements dans le buffer des 3 lignes sources nécessaires - float* line1 = source_lines_buffer + (line % memorized_source_lines) * source_image->get_width(); - float* line2 = source_lines_buffer + ((line + 1) % memorized_source_lines) * source_image->get_width(); - float* line3 = source_lines_buffer + ((line + 2) % memorized_source_lines) * source_image->get_width(); - - // ligne du dessus - if (source_lines[line % memorized_source_lines] != line) { - // la ligne source 'line' n'est pas celle stockée dans le buffer, on doit la lire - source_image->get_line (line1 , line); - source_lines[line % memorized_source_lines] = line; - } - // ligne du milieu - if (source_lines[(line + 1) % memorized_source_lines] != line + 1) { - // la ligne source 'line + 1' n'est pas celle stockée dans le buffer, on doit la lire - source_image->get_line (line2 , line + 1); - source_lines[(line + 1) % memorized_source_lines] = line + 1; - } - // ligne du dessous - if (source_lines[(line + 2) % memorized_source_lines] != line + 2) { - // la ligne source 'line + 2' n'est pas celle stockée dans le buffer, on doit la lire - source_image->get_line (line3 , line + 2); - source_lines[(line + 2) % memorized_source_lines] = line + 2; - } - - //on commence a la premiere colonne - int columnOrig = 1; - int column = 0; - //creation de la variable sur laquelle on travaille pour trouver le seuil - double value,value1,value2,slope; - float a,b,c,d,e,f,g,h,i; - - //calcul de la variable sur toutes les autres colonnes - while ( column < width ) { - - a = ( * ( line1+columnOrig-1 ) ); - b = ( * ( line1+columnOrig ) ); - c = ( * ( line1+columnOrig+1 ) ); - d = ( * ( line2+columnOrig-1 ) ); - e = ( * ( line2+columnOrig ) ); - f = ( * ( line2+columnOrig+1 ) ); - g = ( * ( line3+columnOrig-1 ) ); - h = ( * ( line3+columnOrig ) ); - i = ( * ( line3+columnOrig+1 ) ); - - if (a == aspect->input_nodata_value || b == aspect->input_nodata_value || c == aspect->input_nodata_value || d == aspect->input_nodata_value || e == aspect->input_nodata_value || - f == aspect->input_nodata_value || g == aspect->input_nodata_value || h == aspect->input_nodata_value || i == aspect->input_nodata_value) { - value = aspect->aspect_nodata_value; - } else { - - value1 = (matrix[2] * c + matrix[5] * f + matrix[8] * i - matrix[0] * a - matrix[3] * d - matrix[6] * g); - value2 = (matrix[0] * a + matrix[1] * b + matrix[2] * c - matrix[6] * g - matrix[7] * h - matrix[8] * i); - - //calcul de la pente pour ne pas afficher l'exposition en dessous d'une certaine valeur de pente - slope = sqrt(pow(value1,2.0)+pow(value2,2.0)); - if (slope < aspect->min_slope) { - value = aspect->aspect_nodata_value; - } else { - value = (atan2(value1,value2) + M_PI) * 180 / M_PI; - } - } - - * ( buffer + ( column++ ) ) = (T) ( value ); - columnOrig++; - } - - return width * sizeof(T); - -} - diff --git a/src/image/EstompageImage.cpp b/src/image/EstompageImage.cpp deleted file mode 100644 index 524a0966..00000000 --- a/src/image/EstompageImage.cpp +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Copyright © (2011) Institut national de l'information - * géographique et forestière - * - * Géoportail SAV - * - * This software is a computer program whose purpose is to publish geographic - * data using OGC WMS and WMTS protocol. - * - * This software is governed by the CeCILL-C license under French law and - * abiding by the rules of distribution of free software. You can use, - * modify and/ or redistribute the software under the terms of the CeCILL-C - * license as circulated by CEA, CNRS and INRIA at the following URL - * "http://www.cecill.info". - * - * As a counterpart to the access to the source code and rights to copy, - * modify and redistribute granted by the license, users are provided only - * with a limited warranty and the software's author, the holder of the - * economic rights, and the successive licensors have only limited - * liability. - * - * In this respect, the user's attention is drawn to the risks associated - * with loading, using, modifying and/or developing or reproducing the - * software by the user in light of its specific status of free software, - * that may mean that it is complicated to manipulate, and that also - * therefore means that it is reserved for developers and experienced - * professionals having in-depth computer knowledge. Users are therefore - * encouraged to load and test the software's suitability as regards their - * requirements in conditions enabling the security of their systems and/or - * data to be ensured and, more generally, to use and operate it in the - * same conditions as regards security. - * - * The fact that you are presently reading this means that you have had - * - * knowledge of the CeCILL-C license and that you accept its terms. - */ - -#include "image/EstompageImage.h" - -#include - -#include "utils/Utils.h" -#include -#include - - -int EstompageImage::get_line ( float* buffer, int line ) { - return _getline ( buffer, line ); -} - -int EstompageImage::get_line ( uint16_t* buffer, int line ) { - return _getline ( buffer, line ); -} - -int EstompageImage::get_line ( uint8_t* buffer, int line ) { - return _getline ( buffer, line ); -} - -EstompageImage::EstompageImage (Image *image, Estompage* est) : - Image ( image->get_width() - 2, image->get_height() - 2, 1), - source_image ( image ), estompage (est) { - - // On réduit la bbox d'un pixel de chaque côté - BoundingBox bb = source_image->get_bbox(); - bb.xmin += source_image->get_resx(); - bb.ymin += source_image->get_resy(); - bb.xmax -= source_image->get_resx(); - bb.ymax -= source_image->get_resy(); - set_bbox(bb); - - set_crs(source_image->get_crs()); - - // On calcule une seule fois la résolution en mètre - resxmeter = get_resx(true); - resymeter = get_resy(true); - - // Buffer de lignes sources - memorized_source_lines = 3; - - source_lines = new int[memorized_source_lines]; - for (int i = 0; i < memorized_source_lines; i++) { - source_lines[i] = -1; - } - source_lines_buffer = new float[source_image->get_width() * memorized_source_lines]; -} - -EstompageImage::~EstompageImage() { - delete source_image; - delete[] source_lines; - delete[] source_lines_buffer; -} - - -template -int EstompageImage::_getline ( T* buffer, int line ) { - // L'image source fait une ligne de plus en haut et en bas (ligne 0 de l'image estompée = ligne 1 de l'image source) - // et une colonne de plus à gauche et à droite - // Pour obtenir la ligne 0 de l'image estompée, on a besoin des lignes 0, 1 et 2 de l'image source - // Plus généralement, pour avoir la ligne n de l'image estompée, on a besoin des lignes - // n, n+1 et n+2 de l'image source - - // On range les lignes sources dans un buffer qui peut en stocker 3 - // La ligne source n est stockée en (n % memorized_source_lines) ème position - - // calcul des emplacements dans le buffer des 3 lignes sources nécessaires - float* line1 = source_lines_buffer + (line % memorized_source_lines) * source_image->get_width(); - float* line2 = source_lines_buffer + ((line + 1) % memorized_source_lines) * source_image->get_width(); - float* line3 = source_lines_buffer + ((line + 2) % memorized_source_lines) * source_image->get_width(); - - // ligne du dessus - if (source_lines[line % memorized_source_lines] != line) { - // la ligne source 'line' n'est pas celle stockée dans le buffer, on doit la lire - source_image->get_line (line1 , line); - source_lines[line % memorized_source_lines] = line; - } - // ligne du milieu - if (source_lines[(line + 1) % memorized_source_lines] != line + 1) { - // la ligne source 'line + 1' n'est pas celle stockée dans le buffer, on doit la lire - source_image->get_line (line2 , line + 1); - source_lines[(line + 1) % memorized_source_lines] = line + 1; - } - // ligne du dessous - if (source_lines[(line + 2) % memorized_source_lines] != line + 2) { - // la ligne source 'line + 2' n'est pas celle stockée dans le buffer, on doit la lire - source_image->get_line (line3 , line + 2); - source_lines[(line + 2) % memorized_source_lines] = line + 2; - } - - int column_orig = 1; - int column = 0; - double value; - float dzdx,dzdy,slope,aspect; - float a,b,c,d,e,f,g,h,i; - - while ( column < width ) { - - a = ( * ( line1+column_orig-1 ) ); - b = ( * ( line1+column_orig ) ); - c = ( * ( line1+column_orig+1 ) ); - d = ( * ( line2+column_orig-1 ) ); - e = ( * ( line2+column_orig ) ); - f = ( * ( line2+column_orig+1 ) ); - g = ( * ( line3+column_orig-1 ) ); - h = ( * ( line3+column_orig ) ); - i = ( * ( line3+column_orig+1 ) ); - - if (a == estompage->input_nodata_value || b == estompage->input_nodata_value || c == estompage->input_nodata_value || d == estompage->input_nodata_value || e == estompage->input_nodata_value || - f == estompage->input_nodata_value || g == estompage->input_nodata_value || h == estompage->input_nodata_value || i == estompage->input_nodata_value) { - value = estompage->estompage_nodata_value; - } else { - - dzdx = ((c + 2*f + i) - (a + 2*d + g)) / (8 * resxmeter); - dzdy = ((g + 2*h + i) - (a + 2*b + c)) / (8 * resymeter); - - slope = atan(estompage->z_factor * sqrt(dzdx*dzdx+dzdy*dzdy)); - - if (dzdx != 0) { - aspect = atan2(dzdy,-dzdx); - if (aspect < 0) { - aspect = 2 * M_PI + aspect; - } - } else { - if (dzdy > 0) { - aspect = M_PI_2; - } else { - aspect = 2 * M_PI - M_PI_2; - } - } - - value = 255.0 * ((cos(estompage->zenith) * cos(slope)) + (sin(estompage->zenith) * sin(slope) * cos(estompage->azimuth - aspect))); - if (value < 0) {value = estompage->estompage_nodata_value;} - } - - * ( buffer + ( column++ ) ) = ( T ) ( value ); - column_orig++; - } - - return width * sizeof(T); -} \ No newline at end of file diff --git a/src/image/ExtendedCompoundImage.cpp b/src/image/ExtendedCompoundImage.cpp index 0bf329b2..37f6907b 100644 --- a/src/image/ExtendedCompoundImage.cpp +++ b/src/image/ExtendedCompoundImage.cpp @@ -166,6 +166,7 @@ bool ExtendedCompoundImage::add_mirrors ( int mirrorSize ) { } } + // On met les mirroirs au début pour ne pas écraser de la vraie donnée source_images.insert ( source_images.begin(),mirrorImages.begin(),mirrorImages.end() ); mirrors_count = mirrorImages.size(); diff --git a/src/image/PaletteImage.cpp b/src/image/PaletteImage.cpp deleted file mode 100644 index 48439647..00000000 --- a/src/image/PaletteImage.cpp +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright © (2011) Institut national de l'information - * géographique et forestière - * - * Géoportail SAV - * - * This software is a computer program whose purpose is to publish geographic - * data using OGC WMS and WMTS protocol. - * - * This software is governed by the CeCILL-C license under French law and - * abiding by the rules of distribution of free software. You can use, - * modify and/ or redistribute the software under the terms of the CeCILL-C - * license as circulated by CEA, CNRS and INRIA at the following URL - * "http://www.cecill.info". - * - * As a counterpart to the access to the source code and rights to copy, - * modify and redistribute granted by the license, users are provided only - * with a limited warranty and the software's author, the holder of the - * economic rights, and the successive licensors have only limited - * liability. - * - * In this respect, the user's attention is drawn to the risks associated - * with loading, using, modifying and/or developing or reproducing the - * software by the user in light of its specific status of free software, - * that may mean that it is complicated to manipulate, and that also - * therefore means that it is reserved for developers and experienced - * professionals having in-depth computer knowledge. Users are therefore - * encouraged to load and test the software's suitability as regards their - * requirements in conditions enabling the security of their systems and/or - * data to be ensured and, more generally, to use and operate it in the - * same conditions as regards security. - * - * The fact that you are presently reading this means that you have had - * - * knowledge of the CeCILL-C license and that you accept its terms. - */ - -#include "image/PaletteImage.h" - -#include - -int PaletteImage::get_line ( float* buffer, int line ) { - if ( source_image->get_channels() == 1 && ! palette->is_empty() ) { - return _getline ( buffer, line ); - } else { - return source_image->get_line ( buffer, line ); - } -} - -int PaletteImage::get_line ( uint16_t* buffer, int line ) { - if ( source_image->get_channels() == 1 && ! palette->is_empty() ) { - return _getline ( buffer, line ); - } else { - return source_image->get_line ( buffer, line ); - } -} - -int PaletteImage::get_line ( uint8_t* buffer, int line ) { - if ( source_image->get_channels() == 1 && ! palette->is_empty() ) { - return _getline ( buffer, line ); - } else { - return source_image->get_line ( buffer, line ); - } -} - -PaletteImage::PaletteImage ( Image* image, Palette* palette ) : Image ( image->get_width(), image->get_height(), 1, image->get_bbox() ), source_image ( image ), palette ( palette ) { - // Il n'y aura application de la palette et modification des canaux que si - // - la palette n'est pas nulle et pas vide - // - l'image source est sur un canal - if ( source_image->get_channels() == 1 && this->palette != NULL && ! this->palette->is_empty() ) { - if (this->palette->is_no_alpha()) { - channels = 3; - } else { - channels = 4; - } - } else { - channels = image->get_channels(); - } -} - -PaletteImage::~PaletteImage() { - delete source_image; -} - -template -int PaletteImage::_getline ( T* buffer, int line ) { - float* source = new float[source_image->get_width() * source_image->get_channels()]; - source_image->get_line ( source, line ); - switch ( channels ) { - case 4: - for (int i = 0; i < source_image->get_width() ; i++ ) { - Colour iColour = palette->get_colour ( * ( source+i ) ); - * ( buffer+i*4 ) = (T) iColour.r; - * ( buffer+i*4+1 ) = (T) iColour.g; - * ( buffer+i*4+2 ) = (T) iColour.b; - * ( buffer+i*4+3 ) = (T) iColour.a; - } - break; - - case 3: - for (int i = 0; i < source_image->get_width() ; i++ ) { - Colour iColour = palette->get_colour ( * ( source+i ) ); - * ( buffer+i*3 ) = (T) iColour.r; - * ( buffer+i*3+1 ) = (T) iColour.g; - * ( buffer+i*3+2 ) = (T) iColour.b; - } - break; - } - - - - delete[] source; - return width * sizeof ( T ) * channels; -} diff --git a/src/image/PenteImage.cpp b/src/image/PenteImage.cpp deleted file mode 100644 index ea62c56c..00000000 --- a/src/image/PenteImage.cpp +++ /dev/null @@ -1,202 +0,0 @@ -/* - * Copyright © (2011) Institut national de l'information - * géographique et forestière - * - * Géoportail SAV - * - * This software is a computer program whose purpose is to publish geographic - * data using OGC WMS and WMTS protocol. - * - * This software is governed by the CeCILL-C license under French law and - * abiding by the rules of distribution of free software. You can use, - * modify and/ or redistribute the software under the terms of the CeCILL-C - * license as circulated by CEA, CNRS and INRIA at the following URL - * "http://www.cecill.info". - * - * As a counterpart to the access to the source code and rights to copy, - * modify and redistribute granted by the license, users are provided only - * with a limited warranty and the software's author, the holder of the - * economic rights, and the successive licensors have only limited - * liability. - * - * In this respect, the user's attention is drawn to the risks associated - * with loading, using, modifying and/or developing or reproducing the - * software by the user in light of its specific status of free software, - * that may mean that it is complicated to manipulate, and that also - * therefore means that it is reserved for developers and experienced - * professionals having in-depth computer knowledge. Users are therefore - * encouraged to load and test the software's suitability as regards their - * requirements in conditions enabling the security of their systems and/or - * data to be ensured and, more generally, to use and operate it in the - * same conditions as regards security. - * - * The fact that you are presently reading this means that you have had - * - * knowledge of the CeCILL-C license and that you accept its terms. - */ - -#include "image/PenteImage.h" - -#include - -#include "utils/Utils.h" -#include -#include -#define DEG_TO_RAD .0174532925199432958 -#include - -int PenteImage::get_line ( float* buffer, int line ) { - return _getline ( buffer, line ); -} - -int PenteImage::get_line ( uint16_t* buffer, int line ) { - return _getline ( buffer, line ); -} - -int PenteImage::get_line ( uint8_t* buffer, int line ) { - return _getline ( buffer, line ); -} - -//definition des variables -PenteImage::PenteImage (Image* image, Pente* p) : - Image ( image->get_width() - 2, image->get_height() - 2, 1), - source_image ( image ), pente (p) - { - - // On réduit la bbox d'un pixel de chaque côté - BoundingBox bb = source_image->get_bbox(); - bb.xmin += source_image->get_resx(); - bb.ymin += source_image->get_resy(); - bb.xmax -= source_image->get_resx(); - bb.ymax -= source_image->get_resy(); - set_bbox(bb); - - set_crs(source_image->get_crs()); - - // On calcule une seule fois la résolution en mètre - resxmeter = get_resx(true); - resymeter = get_resy(true); - - // Buffer de lignes sources - memorized_source_lines = 3; - - source_lines = new int[memorized_source_lines]; - for (int i = 0; i < memorized_source_lines; i++) { - source_lines[i] = -1; - } - source_lines_buffer = new float[source_image->get_width() * memorized_source_lines]; - -} - - -PenteImage::~PenteImage() { - delete source_image; - delete[] source_lines; - delete[] source_lines_buffer; -} - - -template -int PenteImage::_getline ( T* buffer, int line ) { - // L'image source fait une ligne de plus en haut et en bas (ligne 0 de l'image estompée = ligne 1 de l'image source) - // et une colonne de plus à gauche et à droite - // Pour obtenir la ligne 0 de l'image estompée, on a besoin des lignes 0, 1 et 2 de l'image source - // Plus généralement, pour avoir la ligne n de l'image estompée, on a besoin des lignes - // n, n+1 et n+2 de l'image source - - // On range les lignes sources dans un buffer qui peut en stocker "memorized_source_lines" - // La ligne source n est stockée en (n % memorized_source_lines) ème position - - // calcul des emplacements dans le buffer des 3 lignes sources nécessaires - float* line1 = source_lines_buffer + (line % memorized_source_lines) * source_image->get_width(); - float* line2 = source_lines_buffer + ((line + 1) % memorized_source_lines) * source_image->get_width(); - float* line3 = source_lines_buffer + ((line + 2) % memorized_source_lines) * source_image->get_width(); - - // ligne du dessus - if (source_lines[line % memorized_source_lines] != line) { - // la ligne source 'line' n'est pas celle stockée dans le buffer, on doit la lire - source_image->get_line (line1 , line); - source_lines[line % memorized_source_lines] = line; - } - // ligne du milieu - if (source_lines[(line + 1) % memorized_source_lines] != line + 1) { - // la ligne source 'line + 1' n'est pas celle stockée dans le buffer, on doit la lire - source_image->get_line (line2 , line + 1); - source_lines[(line + 1) % memorized_source_lines] = line + 1; - } - // ligne du dessous - if (source_lines[(line + 2) % memorized_source_lines] != line + 2) { - // la ligne source 'line + 2' n'est pas celle stockée dans le buffer, on doit la lire - source_image->get_line (line3 , line + 2); - source_lines[(line + 2) % memorized_source_lines] = line + 2; - } - - //on commence a la premiere colonne - int columnOrig = 1; - int column = 0; - //creation de la variable sur laquelle on travaille pour trouver le seuil - double dzdx,dzdy,rise,slope; - float a,b,c,d,e,f,g,h,i; - float resx,resy; - - if (pente->algo == "H") { - resx = 8.0 * resxmeter; - resy = 8.0 * resymeter; - } else if (pente->algo == "Z") { - resx = 2.0 * resxmeter; - resy = 2.0 * resymeter; - } - - //calcul de la variable sur toutes les autres colonnes - while ( column < width ) { - - a = ( * ( line1+columnOrig-1 ) ); - b = ( * ( line1+columnOrig ) ); - c = ( * ( line1+columnOrig+1 ) ); - d = ( * ( line2+columnOrig-1 ) ); - e = ( * ( line2+columnOrig ) ); - f = ( * ( line2+columnOrig+1 ) ); - g = ( * ( line3+columnOrig-1 ) ); - h = ( * ( line3+columnOrig ) ); - i = ( * ( line3+columnOrig+1 ) ); - - if (a == pente->input_nodata_value || b == pente->input_nodata_value || c == pente->input_nodata_value || d == pente->input_nodata_value || e == pente->input_nodata_value || - f == pente->input_nodata_value || g == pente->input_nodata_value || h == pente->input_nodata_value || i == pente->input_nodata_value) { - slope = pente->slope_nodata_value; - } else { - - if (pente->algo == "H") { - dzdx = (( c + 2.0 * f + i) - (a + 2.0 * d + g)) / resx; - dzdy = (( g + 2.0 * h + i) - (a + 2.0 * b + c)) / resy; - } else if (pente->algo == "Z" ) { - dzdx = (f - d) / resx; - dzdy = (h - b) / resy; - } else { - - } - - - if (pente->unit == "pourcent") { - slope = sqrt(pow(dzdx,2.0) + pow(dzdy,2.0)) * 100.0; - } else if (pente->unit == "degree") { - rise = sqrt(pow(dzdx,2.0) + pow(dzdy,2.0)); - - slope = atan(rise) * 180.0 / M_PI; - if (slope>90.0){slope = 180.0-slope;} - } else { - slope = 0; - } - - if (slope > pente->max_slope) { - slope = pente->max_slope; - } - - } - - * ( buffer + ( column++ ) ) = ( T ) ( slope ); - columnOrig++; - - } - - return width * sizeof(T); -} \ No newline at end of file diff --git a/src/image/StyledImage.cpp b/src/image/StyledImage.cpp new file mode 100644 index 00000000..5c355a50 --- /dev/null +++ b/src/image/StyledImage.cpp @@ -0,0 +1,578 @@ +/* + * Copyright © (2011) Institut national de l'information + * géographique et forestière + * + * Géoportail SAV + * + * This software is a computer program whose purpose is to publish geographic + * data using OGC WMS and WMTS protocol. + * + * This software is governed by the CeCILL-C license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-C + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * + * knowledge of the CeCILL-C license and that you accept its terms. + */ + +/** + * \file StyledImage.cpp + * \~french + * \brief Implémentation de la classe StyledImage permettant l'application des styles à une image. + * \~english + * \brief Implement the StyledImage Class handling computing every style to an image. + */ +#include "image/StyledImage.h" +#include + +int StyledImage::get_line(float *buffer, int line) { + if (style != NULL && !style->is_identity()) { + return _getline(buffer, line); + } + else { + return source_image->get_line(buffer, line); + } +} + +int StyledImage::get_line(uint16_t *buffer, int line) { + if (style != NULL && !style->is_identity()) { + return _getline(buffer, line); + } + else { + return source_image->get_line(buffer, line); + } +} + +int StyledImage::get_line(uint8_t *buffer, int line) { + if (style != NULL && !style->is_identity()) { + return _getline(buffer, line); + } + else { + return source_image->get_line(buffer, line); + } +} + +StyledImage::StyledImage(Image *input_image, Style *input_style, int offset) : Image(input_image->get_width() - offset, input_image->get_height() - offset, input_style->get_channels(input_image->get_channels()), input_image->get_bbox()), multi_line_buffer(false) { + style = input_style; + source_image = input_image; + + if (style->estompage_defined()){ + // On réduit la bbox d'un pixel de chaque côté + BoundingBox bb = source_image->get_bbox(); + bb.xmin += source_image->get_resx(); + bb.ymin += source_image->get_resy(); + bb.xmax -= source_image->get_resx(); + bb.ymax -= source_image->get_resy(); + set_bbox(bb); + + set_crs(source_image->get_crs()); + + // On calcule une seule fois la résolution en mètre + resxmeter = get_resx(true); + resymeter = get_resy(true); + + // Buffer de lignes sources + memorized_source_lines = 3; + + source_lines = new int[memorized_source_lines]; + for (int i = 0; i < memorized_source_lines; i++) { + source_lines[i] = -1; + } + source_lines_buffer = new float[source_image->get_width() * memorized_source_lines]; + } + + else if (style->pente_defined()) { + // On réduit la bbox d'un pixel de chaque côté + BoundingBox bb = source_image->get_bbox(); + bb.xmin += source_image->get_resx(); + bb.ymin += source_image->get_resy(); + bb.xmax -= source_image->get_resx(); + bb.ymax -= source_image->get_resy(); + set_bbox(bb); + + set_crs(source_image->get_crs()); + + // On calcule une seule fois la résolution en mètre + resxmeter = get_resx(true); + resymeter = get_resy(true); + + // Buffer de lignes sources + memorized_source_lines = 3; + + source_lines = new int[memorized_source_lines]; + for (int i = 0; i < memorized_source_lines; i++) { + source_lines[i] = -1; + } + source_lines_buffer = new float[source_image->get_width() * memorized_source_lines]; + } + + else if (style->aspect_defined()) { + resolution = (input_image->get_mean_resolution()); + + // On réduit la bbox d'un pixel de chaque côté + BoundingBox bb = source_image->get_bbox(); + bb.xmin += source_image->get_resx(); + bb.ymin += source_image->get_resy(); + bb.xmax -= source_image->get_resx(); + bb.ymax -= source_image->get_resy(); + set_bbox(bb); + + set_crs(source_image->get_crs()); + + // Buffer de lignes sources + memorized_source_lines = 3; + + source_lines = new int[memorized_source_lines]; + for (int i = 0; i < memorized_source_lines; i++) { + source_lines[i] = -1; + } + source_lines_buffer = new float[source_image->get_width() * memorized_source_lines]; + + matrix[0] = 1 / (8.0*resolution) ; + matrix[1] = 2 / (8.0*resolution) ; + matrix[2] = 1 / (8.0*resolution) ; + + matrix[3] = 2 / (8.0*resolution) ; + matrix[4] = 0 ; + matrix[5] = 2 / (8.0*resolution) ; + + matrix[6] = 1 / (8.0*resolution) ; + matrix[7] = 2 / (8.0*resolution) ; + matrix[8] = 1 / (8.0*resolution) ; + } + + else if (style->terrainrgb_defined()) { + if (source_image->get_channels() == 1) { + channels = 3; + } else { + channels = input_image->get_channels(); + } + } + + if (style->palette_defined()){ + // Il n'y aura application de la palette et modification des canaux que si + // - la palette n'est pas nulle et pas vide + // - l'image source est sur un canal + if ( source_image->get_channels() == 1 && style->get_palette() != NULL && ! style->get_palette()->is_empty() ) { + if (style->get_palette()->is_no_alpha()) { + channels = 3; + } else { + channels = 4; + } + } else { + channels = source_image->get_channels(); + } + } +} + +template +int StyledImage::_getline(T *buffer, int line) { + int space; + float *source = new float[source_image->get_width() * source_image->get_channels()]; + source_image->get_line(source, line); + + if (style->estompage_defined()) { + // L'image source fait une ligne de plus en haut et en bas (ligne 0 de l'image estompée = ligne 1 de l'image source) + // et une colonne de plus à gauche et à droite + // Pour obtenir la ligne 0 de l'image estompée, on a besoin des lignes 0, 1 et 2 de l'image source + // Plus généralement, pour avoir la ligne n de l'image estompée, on a besoin des lignes + // n, n+1 et n+2 de l'image source + + // On range les lignes sources dans un buffer qui peut en stocker 3 + // La ligne source n est stockée en (n % memorized_source_lines) ème position + + multi_line_buffer = true; + // calcul des emplacements dans le buffer des 3 lignes sources nécessaires + float *line1 = source_lines_buffer + (line % memorized_source_lines) * source_image->get_width(); + float *line2 = source_lines_buffer + ((line + 1) % memorized_source_lines) * source_image->get_width(); + float *line3 = source_lines_buffer + ((line + 2) % memorized_source_lines) * source_image->get_width(); + + // ligne du dessus + if (source_lines[line % memorized_source_lines] != line) { + // la ligne source 'line' n'est pas celle stockée dans le buffer, on doit la lire + source_image->get_line(line1, line); + source_lines[line % memorized_source_lines] = line; + } + // ligne du milieu + if (source_lines[(line + 1) % memorized_source_lines] != line + 1) { + // la ligne source 'line + 1' n'est pas celle stockée dans le buffer, on doit la lire + source_image->get_line(line2, line + 1); + source_lines[(line + 1) % memorized_source_lines] = line + 1; + } + // ligne du dessous + if (source_lines[(line + 2) % memorized_source_lines] != line + 2) { + // la ligne source 'line + 2' n'est pas celle stockée dans le buffer, on doit la lire + source_image->get_line(line3, line + 2); + source_lines[(line + 2) % memorized_source_lines] = line + 2; + } + + int column_orig = 1; + int column = 0; + double value; + float dzdx, dzdy, slope, aspect; + float a, b, c, d, e, f, g, h, i; + + while (column < width) { + a = (*(line1 + column_orig - 1)); + b = (*(line1 + column_orig)); + c = (*(line1 + column_orig + 1)); + d = (*(line2 + column_orig - 1)); + e = (*(line2 + column_orig)); + f = (*(line2 + column_orig + 1)); + g = (*(line3 + column_orig - 1)); + h = (*(line3 + column_orig)); + i = (*(line3 + column_orig + 1)); + + if (a == style->get_estompage()->input_nodata_value || b == style->get_estompage()->input_nodata_value || c == style->get_estompage()->input_nodata_value || d == style->get_estompage()->input_nodata_value || e == style->get_estompage()->input_nodata_value || + f == style->get_estompage()->input_nodata_value || g == style->get_estompage()->input_nodata_value || h == style->get_estompage()->input_nodata_value || i == style->get_estompage()->input_nodata_value) { + value = style->get_estompage()->estompage_nodata_value; + } + else { + + dzdx = ((c + 2 * f + i) - (a + 2 * d + g)) / (8 * resxmeter); + dzdy = ((g + 2 * h + i) - (a + 2 * b + c)) / (8 * resymeter); + + slope = atan(style->get_estompage()->z_factor * sqrt(dzdx * dzdx + dzdy * dzdy)); + + if (dzdx != 0) { + aspect = atan2(dzdy, -dzdx); + if (aspect < 0) { + aspect = 2 * M_PI + aspect; + } + } + else { + if (dzdy > 0) { + aspect = M_PI_2; + } + else { + aspect = 2 * M_PI - M_PI_2; + } + } + + value = 255.0 * ((cos(style->get_estompage()->zenith) * cos(slope)) + (sin(style->get_estompage()->zenith) * sin(slope) * cos(style->get_estompage()->azimuth - aspect))); + if (value < 0) { + value = style->get_estompage()->estompage_nodata_value; + } + } + + *(buffer + (column++)) = (T)(value); + column_orig++; + } + + space = width * sizeof(T); + } + + else if (style->pente_defined()) { + // L'image source fait une ligne de plus en haut et en bas (ligne 0 de l'image estompée = ligne 1 de l'image source) + // et une colonne de plus à gauche et à droite + // Pour obtenir la ligne 0 de l'image estompée, on a besoin des lignes 0, 1 et 2 de l'image source + // Plus généralement, pour avoir la ligne n de l'image estompée, on a besoin des lignes + // n, n+1 et n+2 de l'image source + + // On range les lignes sources dans un buffer qui peut en stocker "memorized_source_lines" + // La ligne source n est stockée en (n % memorized_source_lines) ème position + + multi_line_buffer = true; + + // calcul des emplacements dans le buffer des 3 lignes sources nécessaires + float* line1 = source_lines_buffer + (line % memorized_source_lines) * source_image->get_width(); + float* line2 = source_lines_buffer + ((line + 1) % memorized_source_lines) * source_image->get_width(); + float* line3 = source_lines_buffer + ((line + 2) % memorized_source_lines) * source_image->get_width(); + + // ligne du dessus + if (source_lines[line % memorized_source_lines] != line) { + // la ligne source 'line' n'est pas celle stockée dans le buffer, on doit la lire + source_image->get_line (line1 , line); + source_lines[line % memorized_source_lines] = line; + } + // ligne du milieu + if (source_lines[(line + 1) % memorized_source_lines] != line + 1) { + // la ligne source 'line + 1' n'est pas celle stockée dans le buffer, on doit la lire + source_image->get_line (line2 , line + 1); + source_lines[(line + 1) % memorized_source_lines] = line + 1; + } + // ligne du dessous + if (source_lines[(line + 2) % memorized_source_lines] != line + 2) { + // la ligne source 'line + 2' n'est pas celle stockée dans le buffer, on doit la lire + source_image->get_line (line3 , line + 2); + source_lines[(line + 2) % memorized_source_lines] = line + 2; + } + + //on commence a la premiere colonne + int columnOrig = 1; + int column = 0; + //creation de la variable sur laquelle on travaille pour trouver le seuil + double dzdx,dzdy,rise,slope; + float a,b,c,d,e,f,g,h,i; + float resx,resy; + + if (style->get_pente()->algo == "H") { + resx = 8.0 * resxmeter; + resy = 8.0 * resymeter; + } else if (style->get_pente()->algo == "Z") { + resx = 2.0 * resxmeter; + resy = 2.0 * resymeter; + } + + //calcul de la variable sur toutes les autres colonnes + while ( column < width ) { + + a = ( * ( line1+columnOrig-1 ) ); + b = ( * ( line1+columnOrig ) ); + c = ( * ( line1+columnOrig+1 ) ); + d = ( * ( line2+columnOrig-1 ) ); + e = ( * ( line2+columnOrig ) ); + f = ( * ( line2+columnOrig+1 ) ); + g = ( * ( line3+columnOrig-1 ) ); + h = ( * ( line3+columnOrig ) ); + i = ( * ( line3+columnOrig+1 ) ); + + if (a == style->get_pente()->input_nodata_value || b == style->get_pente()->input_nodata_value || c == style->get_pente()->input_nodata_value || d == style->get_pente()->input_nodata_value || e == style->get_pente()->input_nodata_value || + f == style->get_pente()->input_nodata_value || g == style->get_pente()->input_nodata_value || h == style->get_pente()->input_nodata_value || i == style->get_pente()->input_nodata_value) { + slope = style->get_pente()->slope_nodata_value; + } else { + + if (style->get_pente()->algo == "H") { + dzdx = (( c + 2.0 * f + i) - (a + 2.0 * d + g)) / resx; + dzdy = (( g + 2.0 * h + i) - (a + 2.0 * b + c)) / resy; + } else if (style->get_pente()->algo == "Z" ) { + dzdx = (f - d) / resx; + dzdy = (h - b) / resy; + } else { + + } + + + if (style->get_pente()->unit == "pourcent") { + slope = sqrt(pow(dzdx,2.0) + pow(dzdy,2.0)) * 100.0; + } else if (style->get_pente()->unit == "degree") { + rise = sqrt(pow(dzdx,2.0) + pow(dzdy,2.0)); + + slope = atan(rise) * 180.0 / M_PI; + if (slope>90.0){slope = 180.0-slope;} + } else { + slope = 0; + } + + if (slope > style->get_pente()->max_slope) { + slope = style->get_pente()->max_slope; + } + + } + + * ( buffer + ( column++ ) ) = ( T ) ( slope ); + columnOrig++; + + } + + space = width * sizeof(T); + } + + else if (style->aspect_defined()) { + // L'image source fait une ligne de plus en haut et en bas (ligne 0 de l'image estompée = ligne 1 de l'image source) + // et une colonne de plus à gauche et à droite + // Pour obtenir la ligne 0 de l'image aspect, on a besoin des lignes 0, 1 et 2 de l'image source + // Plus généralement, pour avoir la ligne n de l'image aspect, on a besoin des lignes + // n, n+1 et n+2 de l'image source + + // On range les lignes sources dans un buffer qui peut en stocker 3 + // La ligne source n est stockée en (n % memorized_source_lines) ème position + + multi_line_buffer = true; + + // calcul des emplacements dans le buffer des 3 lignes sources nécessaires + float* line1 = source_lines_buffer + (line % memorized_source_lines) * source_image->get_width(); + float* line2 = source_lines_buffer + ((line + 1) % memorized_source_lines) * source_image->get_width(); + float* line3 = source_lines_buffer + ((line + 2) % memorized_source_lines) * source_image->get_width(); + + // ligne du dessus + if (source_lines[line % memorized_source_lines] != line) { + // la ligne source 'line' n'est pas celle stockée dans le buffer, on doit la lire + source_image->get_line (line1 , line); + source_lines[line % memorized_source_lines] = line; + } + // ligne du milieu + if (source_lines[(line + 1) % memorized_source_lines] != line + 1) { + // la ligne source 'line + 1' n'est pas celle stockée dans le buffer, on doit la lire + source_image->get_line (line2 , line + 1); + source_lines[(line + 1) % memorized_source_lines] = line + 1; + } + // ligne du dessous + if (source_lines[(line + 2) % memorized_source_lines] != line + 2) { + // la ligne source 'line + 2' n'est pas celle stockée dans le buffer, on doit la lire + source_image->get_line (line3 , line + 2); + source_lines[(line + 2) % memorized_source_lines] = line + 2; + } + + //on commence a la premiere colonne + int columnOrig = 1; + int column = 0; + //creation de la variable sur laquelle on travaille pour trouver le seuil + double value,value1,value2,slope; + float a,b,c,d,e,f,g,h,i; + + //calcul de la variable sur toutes les autres colonnes + while ( column < width ) { + + a = ( * ( line1+columnOrig-1 ) ); + b = ( * ( line1+columnOrig ) ); + c = ( * ( line1+columnOrig+1 ) ); + d = ( * ( line2+columnOrig-1 ) ); + e = ( * ( line2+columnOrig ) ); + f = ( * ( line2+columnOrig+1 ) ); + g = ( * ( line3+columnOrig-1 ) ); + h = ( * ( line3+columnOrig ) ); + i = ( * ( line3+columnOrig+1 ) ); + + if (a == style->get_aspect()->input_nodata_value || b == style->get_aspect()->input_nodata_value || c == style->get_aspect()->input_nodata_value || d == style->get_aspect()->input_nodata_value || e == style->get_aspect()->input_nodata_value || + f == style->get_aspect()->input_nodata_value || g == style->get_aspect()->input_nodata_value || h == style->get_aspect()->input_nodata_value || i == style->get_aspect()->input_nodata_value) { + value = style->get_aspect()->aspect_nodata_value; + } else { + + value1 = (matrix[2] * c + matrix[5] * f + matrix[8] * i - matrix[0] * a - matrix[3] * d - matrix[6] * g); + value2 = (matrix[0] * a + matrix[1] * b + matrix[2] * c - matrix[6] * g - matrix[7] * h - matrix[8] * i); + + //calcul de la pente pour ne pas afficher l'exposition en dessous d'une certaine valeur de pente + slope = sqrt(pow(value1,2.0)+pow(value2,2.0)); + if (slope < style->get_aspect()->min_slope) { + value = style->get_aspect()->aspect_nodata_value; + } else { + value = (atan2(value1,value2) + M_PI) * 180 / M_PI; + } + } + + * ( buffer + ( column++ ) ) = (T) ( value ); + columnOrig++; + } + + space = width * sizeof(T); + } + + else if (style->terrainrgb_defined()) { + switch ( channels ) { + case 3: + for (int i = 0; i < source_image->get_width() ; i++ ) { + + // découpage de l'altitude en RGB suivant la formule suivante : height = min_elevation + ((Red * 256 * 256 + Green * 256 + Blue) * step) + int base = (std::max( *(source+i), style->get_terrainrgb()->min_elevation) - style->get_terrainrgb()->min_elevation) / style->get_terrainrgb()->step; + int red = (base / (256 * 256) % 256); + int green = ((base - red * 256 * 256) / 256 % 256); + int blue = (base - red * 256 * 256 - green * 256); + + * ( buffer+i*3 ) = (T) red; + * ( buffer+i*3+1 ) = (T) green; + * ( buffer+i*3+2 ) = (T) blue; + } + break; + } + + space = width * sizeof ( T ) * channels; + } + + if (style->palette_defined()){ + switch ( channels ) { + case 4: + for (int i = 0; i < source_image->get_width() ; i++ ) { + Colour iColour = style->get_palette()->get_colour ( * ( source+i ) ); + * ( buffer+i*4 ) = (T) iColour.r; + * ( buffer+i*4+1 ) = (T) iColour.g; + * ( buffer+i*4+2 ) = (T) iColour.b; + * ( buffer+i*4+3 ) = (T) iColour.a; + } + break; + + case 3: + for (int i = 0; i < source_image->get_width() ; i++ ) { + Colour iColour = style->get_palette()->get_colour ( * ( source+i ) ); + * ( buffer+i*3 ) = (T) iColour.r; + * ( buffer+i*3+1 ) = (T) iColour.g; + * ( buffer+i*3+2 ) = (T) iColour.b; + } + break; + } + + space = width * sizeof ( T ) * channels; + } + + delete[] source; + return space; +} + +StyledImage *StyledImage::create(Image *input_image, Style *input_style) { + int offset=0; + if (input_style->estompage_defined() || input_style->pente_defined() || input_style->aspect_defined()) { + if (input_image->get_width()<=2 && input_image->get_height()<=2){ + BOOST_LOG_TRIVIAL(error)<<"L'image source est trop petite pour appliquer ce style"; + return NULL; + } + if (input_image->get_channels()!=1){ + BOOST_LOG_TRIVIAL(error)<<"Ce style ne s'applique que sur une image source à un canal"; + return NULL; + } + offset=2; + } + if (input_style->terrainrgb_defined() && input_style->palette_defined()) { + BOOST_LOG_TRIVIAL(error)<<"Les styles terrainrgb et palette ne sont pas compatibles"; + return NULL; + } + if (input_style->terrainrgb_defined()){ + if (input_image->get_channels()!=1){ + BOOST_LOG_TRIVIAL(error)<<"Ce style ne s'applique que sur une image source à un canal"; + return NULL; + } + } + return new StyledImage(input_image,input_style,offset); + +} + +StyledImage::~StyledImage() { + + + if (multi_line_buffer) { + delete[] source_lines; + delete[] source_lines_buffer; + } + delete source_image; +} + +void StyledImage::print() { + BOOST_LOG_TRIVIAL(info) << "" ; + BOOST_LOG_TRIVIAL(info) << "--------- StyledImage -----------" ; + if (style->aspect_defined()){ + BOOST_LOG_TRIVIAL(info) << "--------- Aspect -----------" ; + } + if (style->estompage_defined()){ + BOOST_LOG_TRIVIAL(info) << "--------- Estompage -----------" ; + } + if (style->pente_defined()){ + BOOST_LOG_TRIVIAL(info) << "--------- Pente -----------" ; + } + if (style->terrainrgb_defined()){ + BOOST_LOG_TRIVIAL(info) << "--------- Terrainrgb -----------" ; + } + if (style->palette_defined()){ + BOOST_LOG_TRIVIAL(info) << "--------- Palette -----------" ; + } + Image::print(); + BOOST_LOG_TRIVIAL(info) << "" ; +} diff --git a/src/image/SubsampledImage.cpp b/src/image/SubsampledImage.cpp new file mode 100644 index 00000000..04f5949c --- /dev/null +++ b/src/image/SubsampledImage.cpp @@ -0,0 +1,171 @@ +/* + * Copyright © (2011) Institut national de l'information + * géographique et forestière + * + * Géoportail SAV + * + * This software is a computer program whose purpose is to publish geographic + * data using OGC WMS and WMTS protocol. + * + * This software is governed by the CeCILL-C license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-C + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * + * knowledge of the CeCILL-C license and that you accept its terms. + */ + +/** + * \file SubsampledImage.cpp + ** \~french + * \brief Implémentation des classes SubsampledImage, DecimatedMask + * \details + * \li SubsampledImage : image calculée à d'images compatibles, superposables + * \li DecimatedMask : masque composé, associé à une image composée + ** \~english + * \brief Implement classes SubsampledImage, DecimatedMask + * \details + * \li SubsampledImage : image compounded with superimpose images + * \li DecimatedMask : compounded mask, associated with a compounded image + */ + +#include "image/SubsampledImage.h" +#include +#include "utils/Utils.h" + + +/********************************************** SubsampledImage ************************************************/ + +template +int SubsampledImage::_getline ( T* buffer, int line ) { + + // On a besoin de récupérer ratio_y lignes dans l'image source + T* source_image_lines = new T[ratio_y * source_image->get_width() * source_image->get_channels()]; + uint8_t* source_mask_lines = NULL; + + for ( int i = 0; i < ratio_y; i++ ) { + if (source_image->get_line ( source_image_lines + i * source_image->get_width() * source_image->get_channels(), line * ratio_y + i ) == 0) { + BOOST_LOG_TRIVIAL(error) << "Cannot read line " << line * ratio_y + i << "from source to process SubsampledImage's line " << line ; + return 0; + } + } + + // On récupère les lignes de masques si il est présent + bool mask = false; + if (source_image->get_mask() != NULL) { + mask = true; + source_mask_lines = new uint8_t[ratio_y * source_image->get_width()]; + for ( int i = 0; i < ratio_y; i++ ) { + if (source_image->get_mask()->get_line ( source_mask_lines + i * source_image->get_width(), line * ratio_y + i ) == 0) { + BOOST_LOG_TRIVIAL(error) << "Cannot read mask line " << line * ratio_y + i << "from source to process SubsampledImage's line " << line ; + return 0; + } + } + } + + for (int pixel = 0; pixel < width; pixel++) { + + int data_count; + + for (int band = 0; band < channels; band++) { + data_count = 0; + float value = 0; + + for (int x = 0; x < ratio_x; x++) { + for (int y = 0; y < ratio_y; y++) { + + if (mask && source_mask_lines[source_image->get_width() * y + pixel * ratio_x + x] == 0) { + // ce n'est pas un pixel de donnée, on passe + continue; + } + + data_count++; + value += source_image_lines[source_image->get_width() * channels * y + pixel * ratio_x * channels + x * channels + band]; + } + } + + buffer[pixel * channels + band] = (T) (value / data_count); + } + + if (data_count == 0) { + // On avait aucun pixel de donnée, on va mettre la valeur du premier pixel de la zone, considéré comme le nodata de l'image en entrée + for (int band = 0; band < channels; band++) { + buffer[pixel * channels + band] = source_image_lines[pixel * ratio_x * channels + band]; + } + } + } + + delete [] source_image_lines; + if (source_mask_lines != 0) { + delete [] source_mask_lines; + } + + return width * channels; +} + + +/* Implementation de get_line pour les uint8_t */ +int SubsampledImage::get_line ( uint8_t* buffer, int line ) { + return _getline ( buffer, line ); +} + +/* Implementation de get_line pour les float */ +int SubsampledImage::get_line ( uint16_t* buffer, int line ) { + return _getline ( buffer, line ); +} + +/* Implementation de get_line pour les float */ +int SubsampledImage::get_line ( float* buffer, int line ) { + return _getline ( buffer, line ); +} + +SubsampledImage::SubsampledImage ( Image* image, int ratio_x, int ratio_y ) : + Image ( image->get_width() / ratio_x, image->get_height() / ratio_y, image->get_channels(), image->get_bbox() ), + source_image ( image ), ratio_x (ratio_x), ratio_y (ratio_y) { + +} + +SubsampledImage* SubsampledImage::create ( Image* image, int ratio_x, int ratio_y ) { + + if ( image == NULL ) { + BOOST_LOG_TRIVIAL(error) << "No source image to define subsampled image" ; + return NULL; + } + + // On vérifie que les facteur de sous échantillonnage + + if (image->get_width() % ratio_x != 0) { + BOOST_LOG_TRIVIAL(error) << "Width have to be a multiple of widthwise subsampling factor" ; + return NULL; + } + + if (image->get_height() % ratio_y != 0) { + BOOST_LOG_TRIVIAL(error) << "Height have to be a multiple of heightwise subsampling factor" ; + return NULL; + } + + SubsampledImage* sub = new SubsampledImage ( image, ratio_x, ratio_y); + + return sub; +} + diff --git a/src/image/file/LibtiffImage.cpp b/src/image/file/LibtiffImage.cpp index 9d546f5a..19fb2547 100644 --- a/src/image/file/LibtiffImage.cpp +++ b/src/image/file/LibtiffImage.cpp @@ -544,15 +544,16 @@ int LibtiffImage::_getline ( T* buffer, int line ) { TIFFGetField(tif, TIFFTAG_TILELENGTH, &tile_height); int tilenumber_widthwise = width / tile_width; + int tile_size = tile_width * tile_height * pixel_size; + int tile_row_size = tile_width * pixel_size; + int last_tile_row_size = tile_width * pixel_size; + + // Si la largeur n'est pas un nombre entier de tuiles, on a une tuile incomplète en plus, de largeur différente if (width % tile_width != 0) { - // On ajoute la tuile incomplète tilenumber_widthwise++; + last_tile_row_size = (width % tile_width) * pixel_size; } - int tile_size = tile_width * tile_height * pixel_size; - int tile_row_size = tile_width * pixel_size; - int last_tile_row_size = (width % tile_width) * pixel_size; - int row_size = width * pixel_size; tdata_t tile_buf = _TIFFmalloc(tile_size); @@ -622,9 +623,9 @@ int LibtiffImage::_getline ( T* buffer, int line ) { } else if (channels == 3) { // On ne doit pas garder le dernier octet de chaque entier sur 32 bits (canal alpha non présent) - // on va calculer le nombre de ligne dans le strip : pour le dernier, on peut avoir moins de lignes + // on va calculer le nombre de ligne dans le strip : pour le dernier, si il n'y a pas un nombre entier de strip, on a moins de lignes int rows_count = rowsperstrip; - if (line / rowsperstrip == (height - 1) / rowsperstrip) { + if (height % rowsperstrip != 0 && line / rowsperstrip == (height - 1) / rowsperstrip) { rows_count = height % rowsperstrip; } diff --git a/src/image/file/Rok4Image.cpp b/src/image/file/Rok4Image.cpp index 0bae3420..5abd7202 100644 --- a/src/image/file/Rok4Image.cpp +++ b/src/image/file/Rok4Image.cpp @@ -56,7 +56,6 @@ #include #include "utils/Utils.h" #include "datasource/DataSource.h" -#include "utils/Cache.h" #include #include #include diff --git a/src/processors/Grid.cpp b/src/processors/Grid.cpp index 0a6d8b34..bb99d8fa 100644 --- a/src/processors/Grid.cpp +++ b/src/processors/Grid.cpp @@ -48,8 +48,6 @@ #include "processors/Grid.h" #include -#include "utils/Cache.h" - #include #include diff --git a/src/storage/S3Context.cpp b/src/storage/S3Context.cpp index c994523c..4261c985 100644 --- a/src/storage/S3Context.cpp +++ b/src/storage/S3Context.cpp @@ -49,22 +49,17 @@ #include "storage/S3Context.h" -#include #include -#include #include #include -#include "S3Context.h" -#include "utils/Cache.h" -#include "utils/LibcurlStruct.h" - std::vector S3Context::env_hosts; std::vector S3Context::env_keys; std::vector S3Context::env_secret_keys; std::vector S3Context::env_cluster_names; std::vector S3Context::env_urls; bool S3Context::ssl_no_verify = false; +int S3Context::timeout = 0; bool S3Context::load_env() { if (!env_hosts.empty()) { @@ -133,6 +128,7 @@ bool S3Context::load_env() { } ssl_no_verify = get_ssl_no_verify(); + timeout = get_timeout(); // Analyse des valeurs @@ -348,6 +344,11 @@ int S3Context::read(uint8_t *data, int offset, int size, std::string name) { curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, data_callback); curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&chunk); + if (timeout) { + curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, timeout); + curl_easy_setopt(curl, CURLOPT_TIMEOUT, timeout); + } + BOOST_LOG_TRIVIAL(debug) << "S3 READ START (" << size << ") " << pthread_self(); res = curl_easy_perform(curl); BOOST_LOG_TRIVIAL(debug) << "S3 READ END (" << size << ") " << pthread_self(); @@ -448,6 +449,11 @@ uint8_t *S3Context::read_full(int &size, std::string name) { curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, data_callback); curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&chunk); + if (timeout) { + curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, timeout); + curl_easy_setopt(curl, CURLOPT_TIMEOUT, timeout); + } + res = curl_easy_perform(curl); curl_slist_free_all(list); @@ -627,6 +633,11 @@ bool S3Context::close_to_write(std::string name) { curl_easy_setopt(curl, CURLOPT_POSTFIELDS, &((*(it1->second))[0])); curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, it1->second->size()); + if (timeout) { + curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, timeout); + curl_easy_setopt(curl, CURLOPT_TIMEOUT, timeout); + } + res = curl_easy_perform(curl); curl_slist_free_all(list); @@ -712,6 +723,11 @@ bool S3Context::exists(std::string name) { curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); } + if (timeout) { + curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, timeout); + curl_easy_setopt(curl, CURLOPT_TIMEOUT, timeout); + } + res = curl_easy_perform(curl); curl_slist_free_all(list); diff --git a/src/storage/S3Context.h b/src/storage/S3Context.h index 39d2c5f3..e49bc152 100644 --- a/src/storage/S3Context.h +++ b/src/storage/S3Context.h @@ -53,6 +53,7 @@ #include #include "storage/Context.h" #include "utils/LibcurlStruct.h" +#include "utils/CurlPool.h" #define ROK4_S3_URL "ROK4_S3_URL" #define ROK4_S3_KEY "ROK4_S3_KEY" @@ -103,6 +104,12 @@ class S3Context : public Context { */ static bool ssl_no_verify; + /** + * \~french \brief Temps avant timeout en secondes + * \~english \brief Timeout value, in seconds + */ + static int timeout; + /** * \~french \brief Charge les informations S3 depuis les variables d'environnement * \~english \brief Load S3 informations from environment variables diff --git a/src/storage/SwiftContext.cpp b/src/storage/SwiftContext.cpp index ce425dbc..8c557d41 100644 --- a/src/storage/SwiftContext.cpp +++ b/src/storage/SwiftContext.cpp @@ -48,10 +48,7 @@ */ #include "storage/SwiftContext.h" -#include "utils/LibcurlStruct.h" -#include #include -#include "utils/Cache.h" #include SwiftContext::SwiftContext (std::string cont) : Context(), ssl_no_verify(false), keystone_auth(false), container_name(cont), use_token_from_file(true) { @@ -89,6 +86,7 @@ SwiftContext::SwiftContext (std::string cont) : Context(), ssl_no_verify(false), } ssl_no_verify = get_ssl_no_verify(); + timeout = get_timeout(); } bool SwiftContext::connection() { @@ -175,6 +173,11 @@ bool SwiftContext::connection() { curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, data_callback); curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *) &chunk); + if (timeout) { + curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, timeout); + curl_easy_setopt(curl, CURLOPT_TIMEOUT, timeout); + } + res = curl_easy_perform(curl); if( CURLE_OK != res) { BOOST_LOG_TRIVIAL(error) << "Cannot authenticate to Keystone"; @@ -253,6 +256,11 @@ bool SwiftContext::connection() { curl_easy_setopt(curl, CURLOPT_HEADERDATA, (void*) &authHdr); curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, header_callback); + if (timeout) { + curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, timeout); + curl_easy_setopt(curl, CURLOPT_TIMEOUT, timeout); + } + res = curl_easy_perform(curl); if( CURLE_OK != res) { BOOST_LOG_TRIVIAL(error) << "Cannot authenticate to Swift"; @@ -325,6 +333,11 @@ int SwiftContext::read(uint8_t* data, int offset, int size, std::string name) { curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, data_callback); curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *) &chunk); + if (timeout) { + curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, timeout); + curl_easy_setopt(curl, CURLOPT_TIMEOUT, timeout); + } + BOOST_LOG_TRIVIAL(debug) << "SWIFT READ START (" << size << ") " << pthread_self(); res = curl_easy_perform(curl); BOOST_LOG_TRIVIAL(debug) << "SWIFT READ END (" << size << ") " << pthread_self(); @@ -412,6 +425,11 @@ uint8_t* SwiftContext::read_full(int& size, std::string name) { curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, data_callback); curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *) &chunk); + if (timeout) { + curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, timeout); + curl_easy_setopt(curl, CURLOPT_TIMEOUT, timeout); + } + res = curl_easy_perform(curl); curl_slist_free_all(list); @@ -562,6 +580,11 @@ bool SwiftContext::close_to_write(std::string name) { curl_easy_setopt(curl, CURLOPT_POSTFIELDS, &((*(it1->second))[0])); curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, it1->second->size()); + if (timeout) { + curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, timeout); + curl_easy_setopt(curl, CURLOPT_TIMEOUT, timeout); + } + res = curl_easy_perform(curl); curl_slist_free_all(list); @@ -646,6 +669,11 @@ bool SwiftContext::exists(std::string name) { curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); } + if (timeout) { + curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, timeout); + curl_easy_setopt(curl, CURLOPT_TIMEOUT, timeout); + } + res = curl_easy_perform(curl); curl_slist_free_all(list); diff --git a/src/storage/SwiftContext.h b/src/storage/SwiftContext.h index 34137d21..ffb30706 100644 --- a/src/storage/SwiftContext.h +++ b/src/storage/SwiftContext.h @@ -54,6 +54,7 @@ #include "storage/Context.h" #include "utils/LibcurlStruct.h" #include +#include "utils/CurlPool.h" #define ROK4_SWIFT_AUTHURL "ROK4_SWIFT_AUTHURL" @@ -144,6 +145,12 @@ class SwiftContext : public Context{ */ bool ssl_no_verify; + /** + * \~french \brief Temps avant timeout en secondes + * \~english \brief Timeout value, in seconds + */ + int timeout; + public: diff --git a/src/style/Style.cpp b/src/style/Style.cpp index fd2c65c2..2d0ef49b 100644 --- a/src/style/Style.cpp +++ b/src/style/Style.cpp @@ -50,7 +50,6 @@ #include #include #include -#include "utils/Cache.h" #include "storage/Context.h" @@ -62,6 +61,7 @@ bool Style::parse(json11::Json& doc) { aspect = 0; estompage = 0; palette = 0; + terrainrgb = 0; input_nodata_value = NULL; output_nodata_value = NULL; @@ -106,10 +106,12 @@ bool Style::parse(json11::Json& doc) { legends.push_back(leg); } - palette = new Palette(doc["palette"].object_items()); - if (! palette->is_ok()) { - error_message = "Palette issue for style " + id + ": " + palette->get_error_message(); + if (doc["palette"].is_object()) { + palette = new Palette(doc["palette"].object_items()); + if (! palette->is_ok()) { + error_message = "Palette issue for style " + id + ": " + palette->get_error_message(); return false; + } } if (doc["estompage"].is_object()) { @@ -144,6 +146,17 @@ bool Style::parse(json11::Json& doc) { } } + if (doc["terrainrgb"].is_object()) { + if (estompage != 0 || pente != 0 || aspect !=0 || palette !=0) { + error_message = "Style " + id + " define exposition, estompage, pente or palette rules"; + return false; + } + terrainrgb = new Terrainrgb(doc["terrainrgb"].object_items()); + if (! terrainrgb->is_ok()) { + error_message = "Terrainrgb issue for style " + id + ": " + terrainrgb->get_error_message(); + return false; + } + } return true; } @@ -153,6 +166,7 @@ Style::Style ( std::string path ) : Configuration(path) { estompage = 0; palette = 0; aspect = 0; + terrainrgb = 0; input_nodata_value = NULL; output_nodata_value = NULL; @@ -219,7 +233,11 @@ Style::Style ( std::string path ) : Configuration(path) { else if (pente_defined()) { input_nodata_value = new int[1]; input_nodata_value[0] = (int) pente->input_nodata_value; - } + } + else if (terrainrgb_defined()) { + input_nodata_value = new int[1]; + input_nodata_value[0] = (int) terrainrgb->input_nodata_value; + } else if (palette && ! palette->is_empty()) { input_nodata_value = new int[1]; input_nodata_value[0] = (int) palette->get_colours_map()->begin()->first; @@ -242,8 +260,8 @@ Style::Style ( std::string path ) : Configuration(path) { } } else if (estompage_defined()) { - output_nodata_value = new int[1]; - output_nodata_value[0] = (int) estompage->estompage_nodata_value; + output_nodata_value = new int[1]; + output_nodata_value[0] = (int) estompage->estompage_nodata_value; } else if (aspect_defined()) { output_nodata_value = new int[1]; @@ -253,6 +271,12 @@ Style::Style ( std::string path ) : Configuration(path) { output_nodata_value = new int[1]; output_nodata_value[0] = (int) pente->slope_nodata_value; } + else if (terrainrgb_defined()) { + output_nodata_value = new int[3]; + output_nodata_value[0] = 0; + output_nodata_value[1] = 0; + output_nodata_value[2] = 0; + } } Style::~Style() { @@ -268,6 +292,9 @@ Style::~Style() { if (aspect != 0) { delete aspect; } + if (terrainrgb != 0) { + delete terrainrgb; + } if (input_nodata_value != NULL) { delete[] input_nodata_value; } diff --git a/src/style/Terrainrgb.cpp b/src/style/Terrainrgb.cpp new file mode 100644 index 00000000..c0992d8e --- /dev/null +++ b/src/style/Terrainrgb.cpp @@ -0,0 +1,70 @@ +/* + * Copyright © (2011) Institut national de l'information + * géographique et forestière + * + * Géoportail SAV + * + * This software is a computer program whose purpose is to publish geographic + * data using OGC WMS and WMTS protocol. + * + * This software is governed by the CeCILL-C license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-C + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * + * knowledge of the CeCILL-C license and that you accept its terms. + */ + + /** + * \file Terrainrgb.cpp + * \~french + * \brief Implémentation de la classe Terrainrgb modélisant un terrainrgb. + * \~english + * \brief Implement the Terrainrgb Class handling RGB terrain definition. + */ + +#include "style/Terrainrgb.h" +#include +#include "zlib.h" +#include +#include "byteswap.h" +#include + +Terrainrgb::Terrainrgb(json11::Json doc) : Configuration() +{ + + if (doc["min_elevation"].is_number()) { + min_elevation = doc["min_elevation"].number_value(); + } else { + min_elevation = -10000; + } + if (doc["step"].is_number()) { + step = doc["step"].number_value(); + } else { + step = 0.1; + } + input_nodata_value=min_elevation; +} + +Terrainrgb::~Terrainrgb() { +} diff --git a/src/utils/BoundingBox.cpp b/src/utils/BoundingBox.cpp index ffd68382..bc63d8a4 100644 --- a/src/utils/BoundingBox.cpp +++ b/src/utils/BoundingBox.cpp @@ -45,7 +45,6 @@ #include "utils/BoundingBox.h" #include "utils/CRS.h" -#include "utils/Cache.h" template bool BoundingBox::is_in_crs_area(CRS* c) { diff --git a/src/utils/CRS.cpp b/src/utils/CRS.cpp index 187acf0f..e4268e1a 100644 --- a/src/utils/CRS.cpp +++ b/src/utils/CRS.cpp @@ -43,12 +43,7 @@ * \brief implement the reference systems handler */ -#include -#include - #include "utils/CRS.h" -#include "utils/Cache.h" -#include "utils/Utils.h" CRS CRS::epsg4326; diff --git a/include/rok4/image/PaletteImage.h b/src/utils/CrsBook.cpp similarity index 65% rename from include/rok4/image/PaletteImage.h rename to src/utils/CrsBook.cpp index 0df6ccce..00e54047 100644 --- a/include/rok4/image/PaletteImage.h +++ b/src/utils/CrsBook.cpp @@ -35,38 +35,49 @@ * knowledge of the CeCILL-C license and that you accept its terms. */ -#pragma once +/** + * \file CrsBook.cpp + ** \~french + * \brief Implémentation de la classe CrsBook + ** \~english + * \brief Implements classe CrsBook + */ + + +#include "rok4/utils/CrsBook.h" -#include "rok4/image/Image.h" -#include "rok4/style/Palette.h" +CrsBook::CrsBook(){ -class PaletteImage : public Image { -private: - Image* source_image; - Palette* palette; +} - template - int _getline ( T* buffer, int line ); -public: - virtual int get_line ( float* buffer, int line ); - virtual int get_line ( uint16_t* buffer, int line ); - virtual int get_line ( uint8_t* buffer, int line ); - PaletteImage ( Image* image, Palette* palette ); - virtual ~PaletteImage(); +CRS* CrsBook::get_crs(std::string id) { + id = to_upper_case(id); + std::map::iterator it = book.find ( id ); + if ( it != book.end() ) { + return it->second; + } + mtx.lock(); + CRS* crs = new CRS(id); + // Le CRS est potentiellement non défini (si il n'est pas valide), on le mémorise pour ne pas réessayer la prochaine fois + book.emplace(id, crs); + mtx.unlock(); + return crs; +} - /** \~french - * \brief Sortie des informations sur l'image estompée - ** \~english - * \brief Estompage image description output - */ - void print() { - BOOST_LOG_TRIVIAL(info) << "" ; - BOOST_LOG_TRIVIAL(info) << "------ PaletteImage -------" ; - Image::print(); - BOOST_LOG_TRIVIAL(info) << "\t- Palette colours' number = " << palette->get_colours_map()->size() ; - - BOOST_LOG_TRIVIAL(info) << "" ; +void CrsBook::clean_crss () { + mtx.lock(); + std::map::iterator it; + for (it = book.begin(); it != book.end(); ++it) { + delete it->second; } -}; + book.clear(); + mtx.unlock(); +} + +CrsBook::~CrsBook() { + +} +std::map CrsBook::book; +std::mutex CrsBook::mtx; diff --git a/src/utils/CurlPool.cpp b/src/utils/CurlPool.cpp new file mode 100644 index 00000000..246a3282 --- /dev/null +++ b/src/utils/CurlPool.cpp @@ -0,0 +1,78 @@ +/* + * Copyright © (2011) Institut national de l'information + * géographique et forestière + * + * Géoportail SAV + * + * This software is a computer program whose purpose is to publish geographic + * data using OGC WMS and WMTS protocol. + * + * This software is governed by the CeCILL-C license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-C + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * + * knowledge of the CeCILL-C license and that you accept its terms. + */ + + /** + * \file CurlPool.cpp + ** \~french + * \brief Implémentation de la classe CurlPool + ** \~english + * \brief Implements classe CurlPool + */ + +#include "utils/CurlPool.h" + +CurlPool::~CurlPool(){ + +} + +CURL *CurlPool::get_curl_env() { + pthread_t i = pthread_self(); + + std::map::iterator it = pool.find ( i ); + if ( it == pool.end() ) { + CURL* c = curl_easy_init(); + pool.insert ( std::pair(i,c) ); + return c; + } else { + curl_easy_reset(it->second); + return it->second; + } +} + +void CurlPool::print_curls_count() { + BOOST_LOG_TRIVIAL(info) << "Nombre de contextes curl : " << pool.size(); +} + +void CurlPool::clean_curls() { + std::map::iterator it; + for (it = pool.begin(); it != pool.end(); ++it) { + curl_easy_cleanup(it->second); + } + pool.clear(); +} + +std::map CurlPool::pool; diff --git a/src/utils/IndexCache.cpp b/src/utils/IndexCache.cpp new file mode 100644 index 00000000..99160300 --- /dev/null +++ b/src/utils/IndexCache.cpp @@ -0,0 +1,154 @@ +/* + * Copyright © (2011) Institut national de l'information + * géographique et forestière + * + * Géoportail SAV + * + * This software is a computer program whose purpose is to publish geographic + * data using OGC WMS and WMTS protocol. + * + * This software is governed by the CeCILL-C license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-C + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * + * knowledge of the CeCILL-C license and that you accept its terms. + */ + +/** + * \file IndexCache.cpp + ** \~french + * \brief Implémentation de la classe IndexCache + ** \~english + * \brief Implements classe IndexCache + */ + +#include "rok4/utils/IndexCache.h" + +IndexCache::IndexCache() { + +} + +IndexCache::~IndexCache() { + +} + +void IndexCache::setCacheSize(int s) { + size = s; +} + +void IndexCache::set_validity(int v) { + validity = v; +} + +void IndexCache::add_slab_infos(std::string origin_slab_name, Context *data_context, std::string data_slab_name, int tiles_number, uint8_t *offsets, uint8_t *sizes) { + // On utilise le nom original de la dalle (celle à lire a priori) comme clé dans la map + // Potentiellement ce nom est différent de la vraie dalle contenant la donnée (dans le cas d'une dalle symbolique) + // mais c'est via cette dalle symbolique que la donnée est a priori requêtée + // donc c'est ce nom qu'on utilisera pour l'interrogation du cache + + mtx.lock(); + + IndexElement *elem = new IndexElement(origin_slab_name, data_context, data_slab_name, tiles_number, offsets, sizes); + + // L'information n'est a priori pas dans le cache car + // Soit elle était dans le cache et valide, alors on aurait utilisé ce cache et on n'aurait pas fait appel à cet ajout + // Soit elle était dans le cache mais obsolète, alors on l'aurait déjà supprimé du cache + + if (cache.size() == size) + { + // On récupère le dernier élément du cache + IndexElement *last = cache.back(); + // On le vire du cache + cache.pop_back(); + // On le déréférence de la map d'accès + map.erase(last->key); + delete last; + } + + // update reference + cache.push_front(elem); + map[origin_slab_name] = cache.begin(); + + mtx.unlock(); +} + +bool IndexCache::get_slab_infos(std::string key, int tile_number, Context **data_context, std::string *data_slab_name, uint32_t *offset, uint32_t *size) { + std::unordered_map::iterator>::iterator it = map.find(key); + if (it == map.end()) + { + return false; + } + else + { + // Gestion de la péremption du cache (une heure max) + std::time_t now = std::time(NULL); + if (now - (*(it->second))->date > validity) + { + mtx.lock(); + + // on le cherche à nouveau pour vérifier qu'il n'a pas déjà été supprimé par un thread concurrent + it = map.find(key); + + if (it != map.end()) + { + delete *(it->second); + cache.erase(it->second); + map.erase(it); + } + + mtx.unlock(); + + return false; + } + + *data_slab_name = (*(it->second))->name; + *data_context = (*(it->second))->context; + *offset = (*(it->second))->offsets.at(tile_number); + *size = (*(it->second))->sizes.at(tile_number); + + // On fait le choix de ne pas remettre en tête du cache cet élément, même s'il vient d'être accéder + // C'est parce qu'en plus d'avoir une taille limite, les élément cachés ont une date de péromption + // Il serait donc dommage de remettre en avant (donc plus loin d'une suppression par taille de cache atteinte) + // un élément qui va de toute manière finir par être obsolète. + // C'est une différence avec une cache LRU classique + + return true; + } +} + +void IndexCache::clean_indexes() { + mtx.lock(); + std::list::iterator it; + for (it = cache.begin(); it != cache.end(); ++it) { + delete *it; + } + cache.clear(); + mtx.unlock(); +} + +std::list IndexCache::cache; +std::unordered_map::iterator> IndexCache::map; +int IndexCache::size = 100; +int IndexCache::validity = 300; +std::mutex IndexCache::mtx; diff --git a/src/utils/IndexElement.cpp b/src/utils/IndexElement.cpp new file mode 100644 index 00000000..ab09b029 --- /dev/null +++ b/src/utils/IndexElement.cpp @@ -0,0 +1,57 @@ +/* + * Copyright © (2011) Institut national de l'information + * géographique et forestière + * + * Géoportail SAV + * + * This software is a computer program whose purpose is to publish geographic + * data using OGC WMS and WMTS protocol. + * + * This software is governed by the CeCILL-C license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-C + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * + * knowledge of the CeCILL-C license and that you accept its terms. + */ + +/** + * \file IndexElement.cpp + ** \~french + * \brief Implémentation de la classe IndexElement + ** \~english + * \brief Implements classe IndexElement + */ + +#include "rok4/utils/IndexElement.h" + +IndexElement::IndexElement(std::string k, Context *c, std::string n, int tiles_number, uint8_t *os, uint8_t *ss) { + key = k; + context = c; + name = n; + date = std::time(NULL); + for (int i = 0; i < tiles_number; i++) { + offsets.push_back(*((uint32_t*) (os + i*4))); + sizes.push_back(*((uint32_t*) (ss + i*4))); + } +} \ No newline at end of file diff --git a/src/utils/ProjPool.cpp b/src/utils/ProjPool.cpp new file mode 100644 index 00000000..b90e9962 --- /dev/null +++ b/src/utils/ProjPool.cpp @@ -0,0 +1,82 @@ +/* + * Copyright © (2011) Institut national de l'information + * géographique et forestière + * + * Géoportail SAV + * + * This software is a computer program whose purpose is to publish geographic + * data using OGC WMS and WMTS protocol. + * + * This software is governed by the CeCILL-C license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-C + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * + * knowledge of the CeCILL-C license and that you accept its terms. + */ + +/** + * \file ProjPool.cpp + ** \~french + * \brief Implémentation de la classe ProjPool + ** \~english + * \brief Implements classe ProjPool + */ + + +#include "rok4/utils/ProjPool.h" + +ProjPool::ProjPool(){ +} + +ProjPool::~ProjPool(){ +} + +PJ_CONTEXT *ProjPool::get_proj_env() { + pthread_t i = pthread_self(); + + std::map::iterator it = pool.find ( i ); + if ( it == pool.end() ) { + PJ_CONTEXT* pjc = proj_context_create(); + proj_log_level(pjc, PJ_LOG_NONE); + pool.insert ( std::pair(i,pjc) ); + return pjc; + } else { + return it->second; + } +} + +void ProjPool::print_projs_count() { + BOOST_LOG_TRIVIAL(info) << "Nombre de contextes proj : " << pool.size() ; +} + +void ProjPool::clean_projs() { + std::map::iterator it; + for (it = pool.begin(); it != pool.end(); ++it) { + proj_context_destroy(it->second); + } + pool.clear(); +} + +std::map ProjPool::pool; + diff --git a/src/utils/Pyramid.cpp b/src/utils/Pyramid.cpp index eafa2ed2..b032449e 100644 --- a/src/utils/Pyramid.cpp +++ b/src/utils/Pyramid.cpp @@ -48,7 +48,6 @@ #include "image/ExtendedCompoundImage.h" #include "enums/Format.h" #include "utils/Level.h" -#include "utils/Cache.h" #include #include "image/EmptyImage.h" diff --git a/src/utils/Cache.cpp b/src/utils/StoragePool.cpp similarity index 69% rename from src/utils/Cache.cpp rename to src/utils/StoragePool.cpp index fb4fdf8f..0b6219d3 100644 --- a/src/utils/Cache.cpp +++ b/src/utils/StoragePool.cpp @@ -35,46 +35,86 @@ * knowledge of the CeCILL-C license and that you accept its terms. */ -/** - * \file Cache.cpp + /** + * \file StoragePool.cpp ** \~french - * \brief Implémentation des classes IndexCache, CurlPool, StoragePool et ProjPool + * \brief Implémentation de la classe StoragePool ** \~english - * \brief Implements classes IndexCache, CurlPool, StoragePool and ProjPool + * \brief Implements classe StoragePool */ -#include "utils/Cache.h" +#include "utils/StoragePool.h" #include "storage/FileContext.h" #include "storage/SwiftContext.h" #include "storage/S3Context.h" -#if CEPH_ENABLED - #include "storage/ceph/CephPoolContext.h" -#endif -std::map CurlPool::pool; +StoragePool::StoragePool(){ + +} + +std::string StoragePool::to_string() { + std::ostringstream oss; + oss.setf ( std::ios::fixed,std::ios::floatfield ); + oss << "------ Context pool -------" << std::endl; + oss << "\t- context number = " << pool.size() << std::endl; + + std::map, Context*>::iterator it = pool.begin(); + while (it != pool.end()) { + std::pair key = it->first; + oss << "\t\t- pot = " << key.first << "/" << key.second << std::endl; + oss << it->second->to_string() << std::endl; + it++; + } + + return oss.str() ; + } + + -std::map ProjPool::pool; +void StoragePool::get_storages_count (int& file_count, int& s3_count, int& ceph_count, int& swift_count) { + file_count = 0; + s3_count = 0; + ceph_count = 0; + swift_count = 0; + std::map, Context*>::iterator it = pool.begin(); + while (it != pool.end()) { + std::pair key = it->first; + switch(key.first) { + #if CEPH_ENABLED + case ContextType::CEPHCONTEXT: + ceph_count++; + break; + #endif + case ContextType::SWIFTCONTEXT: + swift_count++; + break; + case ContextType::S3CONTEXT: + s3_count++; + break; + case ContextType::FILECONTEXT: + file_count++; + break; + } + it++; + } + } -std::map,Context*> StoragePool::pool; +std::map,Context*> StoragePool::get_pool() { + return pool; + } -std::list IndexCache::cache; -std::unordered_map::iterator> IndexCache::map; -int IndexCache::size = 100; -int IndexCache::validity = 300; -std::mutex IndexCache::mtx; +StoragePool::~StoragePool(){ -std::map TmsBook::book; -std::vector TmsBook::trash; -std::string TmsBook::directory = ""; -std::mutex TmsBook::mtx; +} -std::map StyleBook::book; -std::vector StyleBook::trash; -std::string StyleBook::directory = ""; -std::mutex StyleBook::mtx; -std::map CrsBook::book; -std::mutex CrsBook::mtx; +void StoragePool::clean_storages () { + std::map,Context*>::iterator it; + for (it=pool.begin(); it!=pool.end(); ++it) { + delete it->second; + it->second = NULL; + } +} Context * StoragePool::get_context(ContextType::eContextType type, std::string tray, Context* reference_context) { @@ -153,4 +193,6 @@ Context * StoragePool::get_context(ContextType::eContextType type, std::string t return ctx; } -} \ No newline at end of file +} + +std::map,Context*> StoragePool::pool; \ No newline at end of file diff --git a/src/utils/StyleBook.cpp b/src/utils/StyleBook.cpp new file mode 100644 index 00000000..640e9a7c --- /dev/null +++ b/src/utils/StyleBook.cpp @@ -0,0 +1,144 @@ +/* + * Copyright © (2011) Institut national de l'information + * géographique et forestière + * + * Géoportail SAV + * + * This software is a computer program whose purpose is to publish geographic + * data using OGC WMS and WMTS protocol. + * + * This software is governed by the CeCILL-C license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-C + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * + * knowledge of the CeCILL-C license and that you accept its terms. + */ + +/** + * \file StyleBook.cpp + ** \~french + * \brief Implémentation de la classe StyleBook + ** \~english + * \brief Implements classe StyleBook + */ + + +#include "rok4/utils/StyleBook.h" + +StyleBook::StyleBook(){ + +} + +void StyleBook::send_to_trash() { + mtx.lock(); + std::map::iterator it; + for (it = book.begin(); it != book.end(); ++it) { + trash.push_back(it->second); + } + book.clear(); + mtx.unlock(); +} + +void StyleBook::empty_trash() { + mtx.lock(); + for (int i = 0; i < trash.size(); i++) { + delete trash.at(i); + } + trash.clear(); + mtx.unlock(); +} + +void StyleBook::set_directory(std::string d) { + // Suppression du slash final + if (d.compare ( d.size()-1,1,"/" ) == 0) { + d.pop_back(); + } + directory = d; +} + +std::map StyleBook::get_book() { + return book; +} + +Style *StyleBook::get_style(std::string id) { + std::map::iterator it = book.find ( id ); + if ( it != book.end() ) { + return it->second; + } + std::string d; + if (directory.empty()) { + char* e = getenv (ROK4_STYLES_DIRECTORY); + if (e == NULL) { + d.assign("/usr/share/rok4/styles"); + } else { + d.assign(e); + } + } else { + d = directory; + } + std::string style_path = d + "/" + id; + mtx.lock(); + // Si on fait du cache de style, on revérifie que ce style n'a pas déjà été ajouté par un thread concurrent entre temps + if(getenv (ROK4_STYLES_NO_CACHE) == NULL) { + if ( it != book.end() ) { + // On a effectivement depuis déjà enregistré ce style + return it->second; + } + } + Style* style = new Style(style_path); + if ( ! style->is_ok() ) { + BOOST_LOG_TRIVIAL(error) << style->get_error_message(); + delete style; + mtx.unlock(); + return NULL; + } + if ( contain_chars(style->get_identifier(), "<>") ) { + BOOST_LOG_TRIVIAL(error) << "Style identifier contains forbidden chars" ; + delete style; + mtx.unlock(); + return NULL; + } + if(getenv (ROK4_STYLES_NO_CACHE) == NULL) { + // On veut utiliser le cache, on met donc ce nouveau style dans l'annuaire pour le trouver la porchaine fois + book.insert ( std::pair(id, style) ); + } else { + // On met le style directement dans la corbeille, pour que le nettoyage se fasse bien + trash.push_back(style); + } + mtx.unlock(); + return style; +} + +int StyleBook::get_styles_count() { + return book.size(); +} + +StyleBook::~StyleBook() { + +} + +std::map StyleBook::book; +std::vector StyleBook::trash; +std::string StyleBook::directory = ""; +std::mutex StyleBook::mtx; \ No newline at end of file diff --git a/src/utils/TileMatrixSet.cpp b/src/utils/TileMatrixSet.cpp index 0e311c4c..78ef2c93 100644 --- a/src/utils/TileMatrixSet.cpp +++ b/src/utils/TileMatrixSet.cpp @@ -45,9 +45,6 @@ #include "utils/TileMatrixSet.h" -#include "utils/Utils.h" -#include "utils/Cache.h" -#include "storage/Context.h" #include #include diff --git a/src/utils/TmsBook.cpp b/src/utils/TmsBook.cpp new file mode 100644 index 00000000..8f45ba44 --- /dev/null +++ b/src/utils/TmsBook.cpp @@ -0,0 +1,139 @@ +/* + * Copyright © (2011) Institut national de l'information + * géographique et forestière + * + * Géoportail SAV + * + * This software is a computer program whose purpose is to publish geographic + * data using OGC WMS and WMTS protocol. + * + * This software is governed by the CeCILL-C license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-C + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * + * knowledge of the CeCILL-C license and that you accept its terms. + */ + +/** + * \file TmsBook.cpp + ** \~french + * \brief Implémentation de la classe TmsBook + ** \~english + * \brief Implements classe TmsBook + */ + + +#include "rok4/utils/TmsBook.h" + +TmsBook::TmsBook(){ + +} + +void TmsBook::send_to_trash() { + mtx.lock(); + std::map::iterator it; + for (it = book.begin(); it != book.end(); ++it) { + trash.push_back(it->second); + } + book.clear(); + mtx.unlock(); +} + +void TmsBook::empty_trash() { + mtx.lock(); + for (int i = 0; i < trash.size(); i++) { + delete trash.at(i); + } + trash.clear(); + mtx.unlock(); +} + +void TmsBook::set_directory(std::string d) { + // Suppression du slash final + if (d.compare ( d.size()-1,1,"/" ) == 0) { + d.pop_back(); + } + directory = d; +} + +std::map TmsBook::get_book() { + return book; +} + +TileMatrixSet *TmsBook::get_tms(std::string id) { + std::map::iterator it = book.find ( id ); + if ( it != book.end() ) { + return it->second; + } + std::string d; + if (directory.empty()) { + char* e = getenv (ROK4_TMS_DIRECTORY); + if (e == NULL) { + d.assign("/usr/share/rok4/tilematrixsets"); + } else { + d.assign(e); + } + } else { + d = directory; + } + std::string tms_path = d + "/" + id; + mtx.lock(); + // Si on fait du cache de TMS, on revérifie que ce TMS n'a pas déjà été ajouté par un thread concurrent entre temps + if(getenv (ROK4_TMS_NO_CACHE) == NULL) { + if ( it != book.end() ) { + // On a effectivement depuis déjà enregistré ce TMS + return it->second; + } + } + TileMatrixSet* tms = new TileMatrixSet(tms_path); + if ( ! tms->is_ok() ) { + BOOST_LOG_TRIVIAL(error) << tms->get_error_message(); + delete tms; + mtx.unlock(); + return NULL; + } + if(getenv (ROK4_TMS_NO_CACHE) == NULL) { + // On veut utiliser le cache, on met donc ce nouveau TMS dans l'annuaire pour le trouver la prochaine fois + book.insert ( std::pair(id, tms) ); + } else { + // On met le TMS directement dans la corbeille, pour que le nettoyage se fasse bien + trash.push_back(tms); + } + + mtx.unlock(); + return tms; +} + +int TmsBook::get_tms_count() { + return book.size(); +} + +TmsBook::~TmsBook(){ + +} + +std::map TmsBook::book; +std::vector TmsBook::trash; +std::string TmsBook::directory = ""; +std::mutex TmsBook::mtx; \ No newline at end of file