diff --git a/CHANGELOG.md b/CHANGELOG.md index 6632391..179af2a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,13 @@ Le format est basé sur [Keep a Changelog](https://keepachangelog.com/) et ce pr ## [Unreleased] ### Added + +- `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. + ### Changed - `Cache` : Export de toutes les classes implémentées dans Cache dans leurs propres fichiers. Les fichiers ajoutés sont : @@ -22,6 +29,9 @@ Le format est basé sur [Keep a Changelog](https://keepachangelog.com/) et ce pr ### Deprecated ### Removed ### Fixed + +- `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. + ### Security ## [2.0.6] - 2025-09-11 diff --git a/include/rok4/image/AspectImage.h b/include/rok4/image/AspectImage.h deleted file mode 100644 index 8ec8c7d..0000000 --- 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 4d74501..0000000 --- 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/PenteImage.h b/include/rok4/image/StyledImage.h similarity index 55% rename from include/rok4/image/PenteImage.h rename to include/rok4/image/StyledImage.h index 1d4bf42..5b1b006 100644 --- a/include/rok4/image/PenteImage.h +++ b/include/rok4/image/StyledImage.h @@ -35,23 +35,44 @@ * knowledge of the CeCILL-C license and that you accept its terms. */ +/** + * \file TerrainrgbImage.h + ** \~french + * \brief D�finition de la classe TerrainrgbImage + ** \~english + * \brief Define class TerrainrgbImage + */ + #pragma once #include "rok4/image/Image.h" -#include "rok4/style/Pente.h" -#include - - -class PenteImage : public Image { - +#include "rok4/image/EstompageImage.h" +#include "rok4/image/PaletteImage.h" +#include "rok4/image/PenteImage.h" +#include "rok4/image/AspectImage.h" +#include "rok4/image/TerrainrgbImage.h" +#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 +96,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/style/Style.h b/include/rok4/style/Style.h index 33bc955..f1667c6 100644 --- a/include/rok4/style/Style.h +++ b/include/rok4/style/Style.h @@ -55,6 +55,7 @@ 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" @@ -163,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 @@ -220,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; @@ -233,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 { @@ -246,6 +266,7 @@ private : return orig_channels; } } + } /** @@ -253,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; @@ -293,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; @@ -348,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 @@ -422,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 0000000..58f80ab --- /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/src/image/AspectImage.cpp b/src/image/AspectImage.cpp deleted file mode 100644 index ba01edc..0000000 --- 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 524a096..0000000 --- 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/PaletteImage.cpp b/src/image/PaletteImage.cpp deleted file mode 100644 index 4843964..0000000 --- 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 ea62c56..0000000 --- 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 0000000..8c18465 --- /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 TerrainrgbImage.cpp + * \~french + * \brief Implémentation de la classe TerrainrgbImage permettant l'application du terrainrgb à une image. + * \~english + * \brief Implement the TerrainrgbImage Class handling computing of Terrainrgb 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/style/Style.cpp b/src/style/Style.cpp index 4962dc8..2d0ef49 100644 --- a/src/style/Style.cpp +++ b/src/style/Style.cpp @@ -61,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; @@ -105,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()) { @@ -143,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; } @@ -152,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; @@ -218,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; @@ -241,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]; @@ -252,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() { @@ -267,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/include/rok4/image/PaletteImage.h b/src/style/Terrainrgb.cpp similarity index 65% rename from include/rok4/image/PaletteImage.h rename to src/style/Terrainrgb.cpp index 0df6ccc..c0992d8 100644 --- a/include/rok4/image/PaletteImage.h +++ b/src/style/Terrainrgb.cpp @@ -35,38 +35,36 @@ * knowledge of the CeCILL-C license and that you accept its terms. */ -#pragma once - -#include "rok4/image/Image.h" -#include "rok4/style/Palette.h" - -class PaletteImage : public Image { -private: - Image* source_image; - Palette* palette; + /** + * \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. + */ - template - int _getline ( T* buffer, int line ); +#include "style/Terrainrgb.h" +#include +#include "zlib.h" +#include +#include "byteswap.h" +#include -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(); +Terrainrgb::Terrainrgb(json11::Json doc) : Configuration() +{ - /** \~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) << "" ; + 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() { +}