Skip to content

Commit bdf172d

Browse files
VincentMirasDolite
authored andcommitted
Ajout du style Colorize permettant de remplacer les pixels blancs de nodata en transparence
1 parent 060877a commit bdf172d

6 files changed

Lines changed: 418 additions & 4 deletions

File tree

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ Le format est basé sur [Keep a Changelog](https://keepachangelog.com/) et ce pr
66

77
## [Unreleased]
88

9+
### Added
10+
11+
- `Colorize` : Ajout d'un style colorize permettant de remplacer une couleur en une autre avec une possibilité de transparence.
12+
913
## [3.0.0] - 2026-03-12
1014

1115
### Added

include/rok4/style/Colorize.h

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
/*
2+
* Copyright © (2011) Institut national de l'information
3+
* géographique et forestière
4+
*
5+
* Géoportail SAV <contact.geoservices@ign.fr>
6+
*
7+
* This software is a computer program whose purpose is to publish geographic
8+
* data using OGC WMS and WMTS protocol.
9+
*
10+
* This software is governed by the CeCILL-C license under French law and
11+
* abiding by the rules of distribution of free software. You can use,
12+
* modify and/ or redistribute the software under the terms of the CeCILL-C
13+
* license as circulated by CEA, CNRS and INRIA at the following URL
14+
* "http://www.cecill.info".
15+
*
16+
* As a counterpart to the access to the source code and rights to copy,
17+
* modify and redistribute granted by the license, users are provided only
18+
* with a limited warranty and the software's author, the holder of the
19+
* economic rights, and the successive licensors have only limited
20+
* liability.
21+
*
22+
* In this respect, the user's attention is drawn to the risks associated
23+
* with loading, using, modifying and/or developing or reproducing the
24+
* software by the user in light of its specific status of free software,
25+
* that may mean that it is complicated to manipulate, and that also
26+
* therefore means that it is reserved for developers and experienced
27+
* professionals having in-depth computer knowledge. Users are therefore
28+
* encouraged to load and test the software's suitability as regards their
29+
* requirements in conditions enabling the security of their systems and/or
30+
* data to be ensured and, more generally, to use and operate it in the
31+
* same conditions as regards security.
32+
*
33+
* The fact that you are presently reading this means that you have had
34+
*
35+
* knowledge of the CeCILL-C license and that you accept its terms.
36+
*/
37+
38+
/**
39+
* \file Colorize.h
40+
** \~french
41+
* \brief D�finition de la classe Colorize
42+
** \~english
43+
* \brief Define class Colorize
44+
*/
45+
46+
47+
#pragma once
48+
49+
#include "rok4/utils/Configuration.h"
50+
51+
#include <stdint.h>
52+
#include <vector>
53+
#include <map>
54+
#include <stddef.h>
55+
56+
class Colorize : public Configuration
57+
{
58+
public:
59+
/** \~french
60+
* \brief tolerance : seuil de tolérance pour gérer les teintes de blanc plus larges
61+
** \~english
62+
* \brief tolerance : tolerance threshold for managing wider shades of white
63+
*/
64+
int tolerance;
65+
66+
/** \~french
67+
* \brief source : valeur visée en entrée
68+
** \~english
69+
* \brief source : input target value
70+
*/
71+
std::vector<int> source;
72+
73+
/** \~french
74+
* \brief destination : valeur visée en sortie
75+
** \~english
76+
* \brief destination : output target value
77+
*/
78+
std::vector<int> destination;
79+
80+
/** \~french
81+
* \brief noData : valeur de nodata pour l'image source
82+
** \~english
83+
* \brief noData : value of nodata for the source image
84+
*/
85+
std::vector<int> input_nodata_value;
86+
87+
/** \~french
88+
* \brief noData : valeur de nodata pour le colorize
89+
** \~english
90+
* \brief noData : value of nodata for the colorize
91+
*/
92+
float colorize_nodata_value;
93+
94+
/**
95+
* \~french
96+
* \brief Constructeurs avec des arguments
97+
* \~english
98+
* \brief Constructor with arguments
99+
*/
100+
Colorize(json11::Json doc);
101+
102+
/**
103+
* \~french
104+
* \brief Destructeur
105+
* \~english
106+
* \brief Destructor
107+
*/
108+
virtual ~Colorize();
109+
};

include/rok4/style/Style.h

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ class Style;
5656
#include "rok4/style/Estompage.h"
5757
#include "rok4/style/Aspect.h"
5858
#include "rok4/style/Terrainrgb.h"
59+
#include "rok4/style/Colorize.h"
5960
#include "rok4/enums/Interpolation.h"
6061
#include "rok4/utils/Configuration.h"
6162
#include "rok4/utils/StoragePool.h"
@@ -169,6 +170,11 @@ private :
169170
* \~english \brief Define wether the server must compute a RGB terrain
170171
*/
171172
Terrainrgb* terrainrgb;
173+
/**
174+
* \~french \brief Définit si un calcul de white to alpha doit être appliqué
175+
* \~english \brief Define wether the server must compute a white to alpha
176+
*/
177+
Colorize* colorize;
172178

173179
/**
174180
* \~french \brief Valeur de nodata attendue dans les données en entrée
@@ -226,7 +232,7 @@ private :
226232
* \~english \brief Style is allowed ?
227233
*/
228234
bool handle (int spp) {
229-
if (estompage_defined() || pente_defined() || aspect_defined() || terrainrgb_defined()) {
235+
if (estompage_defined() || pente_defined() || aspect_defined() || terrainrgb_defined() || colorize_defined()) {
230236
return (spp == 1);
231237
} else {
232238
return true;
@@ -258,6 +264,14 @@ private :
258264
return orig_channels;
259265
}
260266
}
267+
else if (colorize_defined()){
268+
if (orig_channels ==3 || orig_channels ==4){
269+
return colorize->destination.size();
270+
}
271+
else {
272+
return orig_channels;
273+
}
274+
}
261275
else {
262276
if (estompage_defined() || pente_defined() || aspect_defined()) {
263277
return 1;
@@ -274,7 +288,7 @@ private :
274288
* \~english \brief Which sample format after style
275289
*/
276290
SampleFormat::eSampleFormat get_sample_format (SampleFormat::eSampleFormat sf) {
277-
if ((palette && ! palette->is_empty()) || terrainrgb_defined()) {
291+
if ((palette && ! palette->is_empty()) || terrainrgb_defined() || colorize_defined()) {
278292
return SampleFormat::UINT8;
279293
} else {
280294
return sf;
@@ -314,7 +328,7 @@ private :
314328
return false;
315329
}
316330

317-
if (estompage_defined() || pente_defined() || aspect_defined() || terrainrgb_defined()) {
331+
if (estompage_defined() || pente_defined() || aspect_defined() || terrainrgb_defined() || colorize_defined()) {
318332
return false;
319333
} else {
320334
return true;
@@ -475,6 +489,27 @@ private :
475489
inline Terrainrgb* get_terrainrgb() {
476490
return terrainrgb;
477491
}
492+
493+
/**
494+
* \~french
495+
* \brief Return vrai si le style est un white to alpha
496+
* \return bool
497+
* \~english
498+
* \brief Return true if the style is an white to alpha
499+
* \return bool
500+
*/
501+
inline bool colorize_defined() {
502+
return (colorize != 0);
503+
}
504+
/**
505+
* \~french
506+
* \brief Retourne le white to alpha
507+
* \~english
508+
* \brief Return white to alpha
509+
*/
510+
inline Colorize* get_colorize() {
511+
return colorize;
512+
}
478513

479514

480515
/**

src/image/StyledImage.cpp

Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,14 @@ StyledImage::StyledImage(Image *input_image, Style *input_style, int offset) : I
169169
}
170170
}
171171

172+
else if (style->colorize_defined()) {
173+
if (source_image->get_channels() == 3 || source_image->get_channels() == 4) {
174+
channels = style->get_colorize()->destination.size();
175+
} else {
176+
channels = input_image->get_channels();
177+
}
178+
}
179+
172180
if (style->palette_defined()){
173181
// Il n'y aura application de la palette et modification des canaux que si
174182
// - la palette n'est pas nulle et pas vide
@@ -489,6 +497,138 @@ int StyledImage::_getline(T *buffer, int line) {
489497
space = width * sizeof ( T ) * channels;
490498
}
491499

500+
else if (style->colorize_defined()) {
501+
Colorize* wta = style->get_colorize();
502+
switch ( channels ) {
503+
case 3:
504+
if (source_image->get_channels()==3){
505+
for (int i = 0; i < source_image->get_width() ; i++ ) {
506+
//image de départ à 3 canaux pour une arrivée en 3 canaux
507+
int red = *(source+i*3);
508+
int green = *(source+i*3+1);
509+
int blue = *(source+i*3+2);
510+
red = red < 0 ? 0 : (red > 255 ? 255 : red);
511+
green = green < 0 ? 0 : (green > 255 ? 255 : green);
512+
blue = blue < 0 ? 0 : (blue > 255 ? 255 : blue);
513+
int s_red = wta->source[0];
514+
int s_green = wta->source[1];
515+
int s_blue = wta->source[2];
516+
517+
if (red>=s_red-wta->tolerance && red<=s_red+wta->tolerance &&
518+
green>=s_green-wta->tolerance && green<=s_green+wta->tolerance &&
519+
blue>=s_blue-wta->tolerance && blue<=s_blue+wta->tolerance){
520+
* ( buffer+i*3 ) = (T) wta->destination[0];
521+
* ( buffer+i*3+1 ) = (T) wta->destination[1];
522+
* ( buffer+i*3+2 ) = (T) wta->destination[2];
523+
}
524+
else{
525+
* ( buffer+i*3 ) = (T) red;
526+
* ( buffer+i*3+1 ) = (T) green;
527+
* ( buffer+i*3+2 ) = (T) blue;
528+
}
529+
}
530+
}
531+
if (source_image->get_channels()==4){
532+
for (int i = 0; i < source_image->get_width() ; i++ ) {
533+
//image de départ à 4 canaux pour une arrivée en 3 canaux
534+
int red = *(source+i*4);
535+
int green = *(source+i*4+1);
536+
int blue = *(source+i*4+2);
537+
int alpha = *(source+i*4+3);
538+
red = red < 0 ? 0 : (red > 255 ? 255 : red);
539+
green = green < 0 ? 0 : (green > 255 ? 255 : green);
540+
blue = blue < 0 ? 0 : (blue > 255 ? 255 : blue);
541+
alpha = alpha < 0 ? 0 : (alpha > 255 ? 255 : alpha);
542+
int s_red = wta->source[0];
543+
int s_green = wta->source[1];
544+
int s_blue = wta->source[2];
545+
int s_alpha = wta->source[3];
546+
547+
if (red>=s_red-wta->tolerance && red<=s_red+wta->tolerance &&
548+
green>=s_green-wta->tolerance && green<=s_green+wta->tolerance &&
549+
blue>=s_blue-wta->tolerance && blue<=s_blue+wta->tolerance &&
550+
alpha>=s_alpha-wta->tolerance && alpha<=s_alpha+wta->tolerance){
551+
* ( buffer+i*3 ) = (T) wta->destination[0];
552+
* ( buffer+i*3+1 ) = (T) wta->destination[1];
553+
* ( buffer+i*3+2 ) = (T) wta->destination[2];
554+
}
555+
else{
556+
* ( buffer+i*3 ) = (T) red;
557+
* ( buffer+i*3+1 ) = (T) green;
558+
* ( buffer+i*3+2 ) = (T) blue;
559+
}
560+
}
561+
}
562+
break;
563+
case 4:
564+
if (source_image->get_channels()==3){
565+
for (int i = 0; i < source_image->get_width() ; i++ ) {
566+
//image de départ à 3 canaux pour une arrivée en 4 canaux
567+
int red = *(source+i*3);
568+
int green = *(source+i*3+1);
569+
int blue = *(source+i*3+2);
570+
red = red < 0 ? 0 : (red > 255 ? 255 : red);
571+
green = green < 0 ? 0 : (green > 255 ? 255 : green);
572+
blue = blue < 0 ? 0 : (blue > 255 ? 255 : blue);
573+
int s_red = wta->source[0];
574+
int s_green = wta->source[1];
575+
int s_blue = wta->source[2];
576+
577+
if (red>=s_red-wta->tolerance && red<=s_red+wta->tolerance &&
578+
green>=s_green-wta->tolerance && green<=s_green+wta->tolerance &&
579+
blue>=s_blue-wta->tolerance && blue<=s_blue+wta->tolerance){
580+
* ( buffer+i*4 ) = (T) wta->destination[0];
581+
* ( buffer+i*4+1 ) = (T) wta->destination[1];
582+
* ( buffer+i*4+2 ) = (T) wta->destination[2];
583+
* ( buffer+i*4+3 ) = (T) wta->destination[3];
584+
}
585+
else{
586+
* ( buffer+i*4 ) = (T) red;
587+
* ( buffer+i*4+1 ) = (T) green;
588+
* ( buffer+i*4+2 ) = (T) blue;
589+
* ( buffer+i*4+3 ) = (T) 255;
590+
}
591+
}
592+
}
593+
if (source_image->get_channels()==4){
594+
for (int i = 0; i < source_image->get_width() ; i++ ) {
595+
//image de départ à 4 canaux pour une arrivée en 4 canaux
596+
int red = *(source+i*4);
597+
int green = *(source+i*4+1);
598+
int blue = *(source+i*4+2);
599+
int alpha = *(source+i*4+3);
600+
red = red < 0 ? 0 : (red > 255 ? 255 : red);
601+
green = green < 0 ? 0 : (green > 255 ? 255 : green);
602+
blue = blue < 0 ? 0 : (blue > 255 ? 255 : blue);
603+
alpha = alpha < 0 ? 0 : (alpha > 255 ? 255 : alpha);
604+
int s_red = wta->source[0];
605+
int s_green = wta->source[1];
606+
int s_blue = wta->source[2];
607+
int s_alpha = wta->source[3];
608+
609+
if (red>=s_red-wta->tolerance && red<=s_red+wta->tolerance &&
610+
green>=s_green-wta->tolerance && green<=s_green+wta->tolerance &&
611+
blue>=s_blue-wta->tolerance && blue<=s_blue+wta->tolerance &&
612+
alpha>=s_alpha-wta->tolerance && alpha<=s_alpha+wta->tolerance){
613+
* ( buffer+i*4 ) = (T) wta->destination[0];
614+
* ( buffer+i*4+1 ) = (T) wta->destination[1];
615+
* ( buffer+i*4+2 ) = (T) wta->destination[2];
616+
* ( buffer+i*4+3 ) = (T) wta->destination[3];
617+
}
618+
else{
619+
* ( buffer+i*4 ) = (T) red;
620+
* ( buffer+i*4+1 ) = (T) green;
621+
* ( buffer+i*4+2 ) = (T) blue;
622+
* ( buffer+i*4+3 ) = (T) alpha;
623+
}
624+
}
625+
}
626+
break;
627+
}
628+
629+
space = width * sizeof ( T ) * channels;
630+
}
631+
492632
if (style->palette_defined()){
493633
switch ( channels ) {
494634
case 4:
@@ -541,6 +681,16 @@ StyledImage *StyledImage::create(Image *input_image, Style *input_style) {
541681
return NULL;
542682
}
543683
}
684+
if (input_style->colorize_defined()){
685+
if (input_image->get_channels()!=3 && input_image->get_channels()!=4){
686+
BOOST_LOG_TRIVIAL(error)<<"Ce style ne s'applique que sur une image source à trois ou quatre canaux";
687+
return NULL;
688+
}
689+
if (input_style->palette_defined()){
690+
BOOST_LOG_TRIVIAL(error)<<"Le style colorize n'est pas compatible avec une palette";
691+
return NULL;
692+
}
693+
}
544694
return new StyledImage(input_image,input_style,offset);
545695

546696
}
@@ -570,6 +720,9 @@ void StyledImage::print() {
570720
if (style->terrainrgb_defined()){
571721
BOOST_LOG_TRIVIAL(info) << "--------- Terrainrgb -----------" ;
572722
}
723+
if (style->colorize_defined()){
724+
BOOST_LOG_TRIVIAL(info) << "--------- Colorize -----------" ;
725+
}
573726
if (style->palette_defined()){
574727
BOOST_LOG_TRIVIAL(info) << "--------- Palette -----------" ;
575728
}

0 commit comments

Comments
 (0)