_______________________________________________________________________________________________________________________________________ /*************************************************************************************************************************************/ /* */ /* F O N C T I O N S D E B A S E D E C O N V E R S I O N D E F O R M A T : */ /* */ /* */ /* Definition : */ /* */ /* Ce fichier contient toutes les fonctions */ /* de base de conversion inter-formats des */ /* images raster, quelle que soit la definition. */ /* */ /* */ /* Author of '$xiii/conversion$FON' : */ /* */ /* Jean-Francois COLONNA (LACTAMME, 19870000000000). */ /* */ /*************************************************************************************************************************************/ /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* C O N V E R S I O N " S T A N D A R D " --> " C H A R " : */ /* */ /*************************************************************************************************************************************/ BFonctionC DEFV(Common,DEFV(FonctionC,POINTERC(Istd_char(imageR,imageA)))) DEFV(Argument,DEFV(imageC,imageR)); /* Image Resultat, telle que le format des "pixels" change : */ /* */ /* imageR(CHAR)=imageA(std). */ /* */ DEFV(Argument,DEFV(image,imageA)); /* Image Argument. */ /*-----------------------------------------------------------------------------------------------------------------------------------*/ Bblock /*..............................................................................................................................*/ begin_image Bblock storeC_point(SCALE_POINT(NOIR_char,BLANC_char,load_point(imageA,X,Y),NOIR,BLANC),imageR,X,Y); Eblock end_image RETIC(imageR); Eblock EFonctionC _______________________________________________________________________________________________________________________________________ _______________________________________________________________________________________________________________________________________ /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* C O N V E R S I O N " S T A N D A R D " --> " I N T " : */ /* */ /*************************************************************************************************************************************/ BFonctionI DEFV(Common,DEFV(FonctionI,POINTERI(Istd_int(imageR,renormaliser_les_niveaux,imageA)))) DEFV(Argument,DEFV(imageI,imageR)); /* Image Resultat, telle que le format des "pixels" change : */ /* */ /* imageR(Int)=imageA(std). */ /* */ DEFV(Argument,DEFV(Logical,renormaliser_les_niveaux)); /* Cet indicateur precise s'il faut renormaliser les niveaux ('VRAI') ou les laisser */ /* inchanger ('FAUX'). Cette option a ete rajoute a cause de 'v $xiidU/fonction$FON'... */ DEFV(Argument,DEFV(image,imageA)); /* Image Argument. */ /*-----------------------------------------------------------------------------------------------------------------------------------*/ Bblock /*..............................................................................................................................*/ begin_image Bblock Test(IL_FAUT(renormaliser_les_niveaux)) Bblock storeI_point(SCALE_POINT(NOIR_int,BLANC_int,load_point(imageA,X,Y),NOIR,BLANC),imageR,X,Y); /* Conversion avec renormalisation des niveaux. */ Eblock ATes Bblock storeI_point(load_point(imageA,X,Y),imageR,X,Y); /* Conversion sans renormalisation des niveaux. */ Eblock ETes Eblock end_image RETII(imageR); Eblock EFonctionI _______________________________________________________________________________________________________________________________________ _______________________________________________________________________________________________________________________________________ /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* C O N V E R S I O N " S T A N D A R D " --> " F L O A T " B R U T A L E : */ /* */ /*************************************************************************************************************************************/ BFonctionF DEFV(Common,DEFV(FonctionF,POINTERF(Istd_float_brutal(imageR,imageA)))) /* Fonction introduite le 20090525190617... */ DEFV(Argument,DEFV(imageF,imageR)); /* Image Resultat, telle que le format des "pixels" change : */ /* */ /* imageR(Float)=imageA(std). */ /* */ DEFV(Argument,DEFV(image,imageA)); /* Image Argument. */ /*-----------------------------------------------------------------------------------------------------------------------------------*/ Bblock /*..............................................................................................................................*/ begin_image Bblock storeF_point(FLOT(load_point(imageA,X,Y)) ,imageR ,X,Y ); /* Rangement brutal... */ Eblock end_image RETIF(imageR); Eblock EFonctionF _______________________________________________________________________________________________________________________________________ _______________________________________________________________________________________________________________________________________ /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* C O N V E R S I O N " S T A N D A R D " --> " F L O A T " B R U T A L E A V E C N O R M A L I S A T I O N : */ /* */ /*************************************************************************************************************************************/ BFonctionF DEFV(Common,DEFV(FonctionF,POINTERF(Istd_float_brutal_normalise(imageR,imageA)))) /* Fonction introduite le 20221005113355... */ DEFV(Argument,DEFV(imageF,imageR)); /* Image Resultat, telle que le format des "pixels" change : */ /* */ /* imageR(Float)=NORMALISATION(imageA(std)). */ /* */ DEFV(Argument,DEFV(image,imageA)); /* Image Argument. */ /*-----------------------------------------------------------------------------------------------------------------------------------*/ Bblock /*..............................................................................................................................*/ begin_image Bblock storeF_point(______NORMALISE_NIVEAU(FLOT(load_point(imageA,X,Y))) ,imageR ,X,Y ); /* Rangement brutal, mais normalise... */ Eblock end_image RETIF(imageR); Eblock EFonctionF _______________________________________________________________________________________________________________________________________ _______________________________________________________________________________________________________________________________________ /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* C O N V E R S I O N " S T A N D A R D " --> " F L O A T " A V E C I N T E R P O L A T I O N : */ /* */ /*************************************************************************************************************************************/ BFonctionF DEFV(Common,DEFV(Float,SINT(Istd_float_avec_interpolation_____ponderation_de_la_moyenne_geometrique,FZERO))); DEFV(Common,DEFV(Float,SINT(Istd_float_avec_interpolation_____ponderation_de_l_interpolation_horizontale,FDU))); DEFV(Common,DEFV(Float,SINT(Istd_float_avec_interpolation_____ponderation_de_l_interpolation_verticale,FDU))); /* Ponderation de calcul du niveau interpole definitid. On notera l'initialisation qui */ /* est faite ici sur une moyenne arithmetique entre l'interpolation horizontale (1/2) et */ /* l'interpolation verticale (1/2). */ DEFV(Common,DEFV(Int,SINT(Istd_float_avec_interpolation_____seuil_d_interpolation,COULEURS))); /* Ce seuil permet de selectionner les points pour lesquels il y aura interpolation. Plus */ /* ce seuil est grand, plus les resultats peuvent etre inattendus (voir par exemple le cas */ /* d'un point BLANC entoure uniquement par du NOIR...). */ DEFV(Common,DEFV(Float,SINT(Istd_float_avec_interpolation_____facteur_des_derivees_numeriques,FU))); /* En diminuant ce facteur ou adoucit les transitions d'une maille a l'autre, alors qu'en */ /* l'augmentant, on les rend plus "cassantes"... */ #define DERIVATION_NUMERIQUE(fonction_origine,fonction_extremite) \ MUL2(Istd_float_avec_interpolation_____facteur_des_derivees_numeriques \ ,DERIVATION_PARTIELLE(FLOT(fonction_origine) \ ,FLOT(fonction_extremite) \ ,FLOT(DOUB(PAS_COULEURS)) \ ) \ ) \ /* Calcul de la derivee numerique d'une fonction lors de l'interpolation. */ DEFV(Common,DEFV(FonctionF,POINTERF(Istd_float_avec_interpolation(imageR ,niveau_minimal,niveau_maximal ,imageA ,interpoler_lineairement ) ) ) ) DEFV(Argument,DEFV(imageF,imageR)); /* Image Resultat, telle que : imageR[X][Y]=imageA[X][Y] convertie avec interpolation de */ /* facon a eliminer les plages uniformes... */ DEFV(Argument,DEFV(genere_Float,niveau_minimal)); /* Donne le niveau minimal de l'image Resultat (en general 'FLOT__NOIR'). */ DEFV(Argument,DEFV(genere_Float,niveau_maximal)); /* Donne le niveau maximal de l'image Resultat (en general 'FLOT__BLANC'). */ DEFV(Argument,DEFV(image,imageA)); /* Image Argument. */ DEFV(Argument,DEFV(Logical,interpoler_lineairement)); /* Indique si l'interpolation est lineaire ('VRAI') ou cubique ('FAUX'). */ /*-----------------------------------------------------------------------------------------------------------------------------------*/ Bblock /*..............................................................................................................................*/ begin_image Bblock DEFV(genere_p,INIT(niveau_standard_courant,load_point(imageA,X,Y))); DEFV(genere_Float,INIT(niveau_flottant_courant,FLOT__NIVEAU_UNDEF)); DEFV(genere_Float,INIT(niveau_flottant_interpole,FLOT__NIVEAU_UNDEF)); DEFV(genere_Float,INIT(niveau_flottant_interpole_horizontal,FLOT__NIVEAU_UNDEF)); DEFV(genere_Float,INIT(niveau_flottant_interpole_vertical,FLOT__NIVEAU_UNDEF)); /* Definition du niveau courant au point {X,Y} et de quelques valeurs "equivalentes"... */ EGAL(niveau_flottant_courant,FLOT(niveau_standard_courant)); EGAL(niveau_flottant_interpole,SCALE_POINT(niveau_minimal,niveau_maximal,niveau_standard_courant,NOIR,BLANC)); EGAL(niveau_flottant_interpole_horizontal,niveau_flottant_interpole); EGAL(niveau_flottant_interpole_vertical,niveau_flottant_interpole); /* Conversion flottante a priori... */ Test(IFOU(IFOU(IFEQ(X,Xmin),IFEQ(X,Xmax)),IFOU(IFEQ(Y,Ymin),IFEQ(Y,Ymax)))) Bblock /* Dans le cas d'un point situe au bord, on conserve la conversion flottante a priori... */ Eblock ATes Bblock DEFV(Float,INIT(lambda_horizontal,FZERO)); DEFV(Float,INIT(lambda_vertical,FZERO)); /* Parametres d'interpolation, nuls a priori au cas ou il y aurait un probleme de calcul... */ DEFV(Int,INIT(amplitude_horizontale,ZERO)); DEFV(Int,INIT(amplitude_verticale,ZERO)); /* Pour balayer un segment horizontal ou vertical autour du point courant... */ DEFV(genere_p,INIT(niveau_standard_a_gauche,niveau_standard_courant)); DEFV(genere_p,INIT(niveau_standard_a_droite,niveau_standard_courant)); DEFV(genere_p,INIT(niveau_standard_en_bas,niveau_standard_courant)); DEFV(genere_p,INIT(niveau_standard_en_haut,niveau_standard_courant)); /* Niveaux "extremes" reperes lors des balayages qui suivent... */ DEFV(genere_Float,INIT(niveau_standard_Origine_horizontal,FLOT(niveau_standard_courant))); DEFV(genere_Float,INIT(niveau_standard_Extremite_horizontal,FLOT(niveau_standard_courant))); DEFV(genere_Float,INIT(niveau_standard_Origine_vertical,FLOT(niveau_standard_courant))); DEFV(genere_Float,INIT(niveau_standard_Extremite_vertical,FLOT(niveau_standard_courant))); /* Niveaux Origine et Extremite pour les interpolations horizontale et verticale. */ Test(IFOU(IZNE(Istd_float_avec_interpolation_____ponderation_de_la_moyenne_geometrique) ,IZNE(Istd_float_avec_interpolation_____ponderation_de_l_interpolation_horizontale) ) ) Bblock /* Cas ou l'interpolation horizontale est necessaire : */ DEFV(Logical,INIT(trouve_a_gauche,FAUX)); DEFV(Logical,INIT(trouve_a_droite,FAUX)); /* Indique si les points cherches a gauche et a droite de niveaux differents de celui du */ /* point courant ont ete trouve. */ DEFV(Int,INIT(X_gauche,UNDEF)); DEFV(Int,INIT(X_droite,UNDEF)); /* Indique les abscisses de points cherches a gauche et a droite de niveaux differents de */ /* celui du point courant. */ Tant(IFOU(EST_FAUX(trouve_a_gauche),EST_FAUX(trouve_a_droite))) Bblock INCR(amplitude_horizontale,I); /* Balayage a priori du segment... */ Test(EST_FAUX(trouve_a_gauche)) Bblock EGAL(X_gauche,MAX2(Xmin,nPREX(X,amplitude_horizontale))); /* Balayage de l'horizontale courante. */ EGAL(niveau_standard_a_gauche,load_point(imageA,X_gauche,Y)); /* Recuperation des niveaux correspondants. */ Test(IFOU(IFEQ(X_gauche,Xmin),IFNE(niveau_standard_courant,niveau_standard_a_gauche))) Bblock EGAL(trouve_a_gauche,VRAI); /* Le balayage vers la gauche est arrete des qu'on atteint le bord de l'image ou des qu'un */ /* niveau different du point courant apparait... */ Eblock ATes Bblock Eblock ETes Eblock ATes Bblock Eblock ETes Test(EST_FAUX(trouve_a_droite)) Bblock EGAL(X_droite,MIN2(Xmax,nSUCX(X,amplitude_horizontale))); /* Balayage de l'horizontale courante. */ EGAL(niveau_standard_a_droite,load_point(imageA,X_droite,Y)); /* Recuperation des niveaux correspondants. */ Test(IFOU(IFEQ(X_droite,Xmax),IFNE(niveau_standard_courant,niveau_standard_a_droite))) Bblock EGAL(trouve_a_droite,VRAI); /* Le balayage vers la droite est arrete des qu'on atteint le bord de l'image ou des qu'un */ /* niveau different du point courant apparait... */ Eblock ATes Bblock Eblock ETes Eblock ATes Bblock Eblock ETes Eblock ETan Test(IFGE(X_droite,X_gauche)) Bblock Test(INCLff(niveau_standard_courant,niveau_standard_a_gauche,niveau_standard_a_droite)) Bblock /* Cas ou le niveau du point {X,Y} est encadre par celui des points [gauche,droite] : */ /* */ /* +********* */ /* + | */ /* + | */ /* + | */ /* + | */ /* +*********| */ /* | | */ /* | | */ /* | | */ /* ********** | | */ /* | | | */ /* | | | */ /* | | | */ /* ------------------------------------------------ */ /* gauche | droite */ /* {X,Y} */ /* */ /* ce dessin montre le profil d'une ligne avant interpolation avec "*" et l'interpolation */ /* qui va etre faite a l'aide de '+'. */ EGAL(X_gauche,COND(EST_VRAI(trouve_a_gauche),SUCX(X_gauche),X_gauche)); /* Et on revient sur le point immediatement a droite (qui a donc le meme niveau que le */ /* point courant {X,Y}). */ EGAL(niveau_standard_Origine_horizontal,niveau_flottant_courant); EGAL(niveau_standard_Extremite_horizontal,FLOT(niveau_standard_a_droite)); /* Definition du segment sur lequel interpoler. */ Eblock ATes Bblock /* Cas ou le niveau du point {X,Y} est hors de celui des points [gauche,droite] : */ Test(IFGT(SOUS(X_droite,X),SOUS(X,X_gauche))) Bblock /* Cas ou le point courant {X,Y} est a gauche du milieu du segment [gauche,droite] : */ /* */ /* *********+ */ /* | + */ /* | + ********** */ /* | + | */ /* | + | */ /* |*********+**********| */ /* | | | */ /* | | | */ /* | | | */ /* ------------------------------------------------ */ /* gauche | droite */ /* {X,Y} */ /* */ /* ce dessin montre le profil d'une ligne avant interpolation avec "*" et l'interpolation */ /* qui va etre faite a l'aide de '+'. */ EGAL(X_droite,MOYE(X_gauche,X_droite)); /* L'extremite de droite choisie est le milieu du segment [gauche,droite]. */ EGAL(niveau_standard_Origine_horizontal,FLOT(niveau_standard_a_gauche)); EGAL(niveau_standard_Extremite_horizontal,niveau_flottant_courant); /* Definition du segment sur lequel interpoler. */ Eblock ATes Bblock /* Cas ou le point courant {X,Y} est a droite du milieu du segment [gauche,droite] : */ /* */ /* +********* */ /* + | */ /* ********** + | */ /* | + | */ /* | + | */ /* |**********+*********| */ /* | | | */ /* | | | */ /* | | | */ /* ------------------------------------------------ */ /* gauche | droite */ /* {X,Y} */ /* */ /* ce dessin montre le profil d'une ligne avant interpolation avec "*" et l'interpolation */ /* qui va etre faite a l'aide de '+'. */ EGAL(X_gauche,MOYE(X_gauche,X_droite)); /* L'extremite de gauche choisie est le milieu du segment [gauche,droite]. */ EGAL(niveau_standard_Origine_horizontal,niveau_flottant_courant); EGAL(niveau_standard_Extremite_horizontal,FLOT(niveau_standard_a_droite)); /* Definition du segment sur lequel interpoler. */ Eblock ETes Eblock ETes EGAL(lambda_horizontal,DIVI(FLOT(SOUS(X,X_gauche)),FLOT(SOUS(X_droite,X_gauche)))); /* Calcul du parametre d'interpolation. */ Eblock ATes Bblock PRINT_ERREUR("le point de droite est a gauche et reciproquement"); Eblock ETes Eblock ATes Bblock Eblock ETes Test(IFOU(IZNE(Istd_float_avec_interpolation_____ponderation_de_la_moyenne_geometrique) ,IZNE(Istd_float_avec_interpolation_____ponderation_de_l_interpolation_verticale) ) ) Bblock /* Cas ou l'interpolation verticale est necessaire : */ DEFV(Logical,INIT(trouve_en_bas,FAUX)); DEFV(Logical,INIT(trouve_en_haut,FAUX)); /* Indique si les points cherches en bas et en haut de niveaux differents de celui du */ /* point courant ont ete trouve. */ DEFV(Int,INIT(Y_bas,UNDEF)); DEFV(Int,INIT(Y_haut,UNDEF)); /* Indique les abscisses de points cherches en bas et en haut de niveaux differents de */ /* celui du point courant. */ Tant(IFOU(EST_FAUX(trouve_en_bas),EST_FAUX(trouve_en_haut))) Bblock INCR(amplitude_verticale,I); /* Balayage a priori du segment... */ Test(EST_FAUX(trouve_en_bas)) Bblock EGAL(Y_bas,MAX2(Ymin,nPREY(Y,amplitude_verticale))); /* Balayage de la verticale courante. */ EGAL(niveau_standard_en_bas,load_point(imageA,X,Y_bas)); /* Recuperation des niveaux correspondants. */ Test(IFOU(IFEQ(Y_bas,Ymin),IFNE(niveau_standard_courant,niveau_standard_en_bas))) Bblock EGAL(trouve_en_bas,VRAI); /* Le balayage vers le bas est arrete des qu'on atteint le bord de l'image ou des qu'un */ /* niveau different du point courant apparait... */ Eblock ATes Bblock Eblock ETes Eblock ATes Bblock Eblock ETes Test(EST_FAUX(trouve_en_haut)) Bblock EGAL(Y_haut,MIN2(Ymax,nSUCY(Y,amplitude_verticale))); /* Balayage de la verticale courante. */ EGAL(niveau_standard_en_haut,load_point(imageA,X,Y_haut)); /* Recuperation des niveaux correspondants. */ Test(IFOU(IFEQ(Y_haut,Ymax),IFNE(niveau_standard_courant,niveau_standard_en_haut))) Bblock EGAL(trouve_en_haut,VRAI); /* Le balayage vers le haut est arrete des qu'on atteint le bord de l'image ou des qu'un */ /* niveau different du point courant apparait... */ Eblock ATes Bblock Eblock ETes Eblock ATes Bblock Eblock ETes Eblock ETan Test(IFGE(Y_haut,Y_bas)) Bblock Test(INCLff(niveau_standard_courant,niveau_standard_en_bas,niveau_standard_en_haut)) Bblock /* Cas ou le niveau du point {X,Y} est encadre par celui des points [bas,haut] : */ /* */ /* +********* */ /* + | */ /* + | */ /* + | */ /* + | */ /* +*********| */ /* | | */ /* | | */ /* | | */ /* ********** | | */ /* | | | */ /* | | | */ /* | | | */ /* ------------------------------------------------ */ /* bas | haut */ /* {X,Y} */ /* */ /* ce dessin montre le profil d'une colonne avant interpolation avec "*" et l'interpolation */ /* qui va etre faite a l'aide de '+'. */ EGAL(Y_bas,COND(EST_VRAI(trouve_en_bas),SUCY(Y_bas),Y_bas)); /* Et on revient sur le point immediatement au-dessus (qui a donc le meme niveau que le */ /* point courant {X,Y}). */ EGAL(niveau_standard_Origine_vertical,niveau_flottant_courant); EGAL(niveau_standard_Extremite_vertical,FLOT(niveau_standard_en_haut)); /* Definition du segment sur lequel interpoler. */ Eblock ATes Bblock /* Cas ou le niveau du point {X,Y} est hors de celui des points [bas,haut] : */ Test(IFGT(SOUS(Y_haut,Y),SOUS(Y,Y_bas))) Bblock /* Cas ou le point courant {X,Y} est en dessous du milieu du segment [bas,haut] : */ /* */ /* *********+ */ /* | + */ /* | + ********** */ /* | + | */ /* | + | */ /* |*********+**********| */ /* | | | */ /* | | | */ /* | | | */ /* ------------------------------------------------ */ /* bas | haut */ /* {X,Y} */ /* */ /* ce dessin montre le profil d'une colonne avant interpolation avec "*" et l'interpolation */ /* qui va etre faite a l'aide de '+'. */ EGAL(Y_haut,MOYE(Y_bas,Y_haut)); /* L'extremite du haut choisie est le milieu du segment [bas,haut]. */ EGAL(niveau_standard_Origine_vertical,FLOT(niveau_standard_en_bas)); EGAL(niveau_standard_Extremite_vertical,niveau_flottant_courant); /* Definition du segment sur lequel interpoler. */ Eblock ATes Bblock /* Cas ou le point courant {X,Y} est au dessus du milieu du segment [bas,haut] : */ /* */ /* +********* */ /* + | */ /* ********** + | */ /* | + | */ /* | + | */ /* |**********+*********| */ /* | | | */ /* | | | */ /* | | | */ /* ------------------------------------------------ */ /* bas | haut */ /* {X,Y} */ /* */ /* ce dessin montre le profil d'une colonne avant interpolation avec "*" et l'interpolation */ /* qui va etre faite a l'aide de '+'. */ EGAL(Y_bas,MOYE(Y_bas,Y_haut)); /* L'extremite du bas choisie est le milieu du segment [bas,haut]. */ EGAL(niveau_standard_Origine_vertical,niveau_flottant_courant); EGAL(niveau_standard_Extremite_vertical,FLOT(niveau_standard_en_haut)); /* Definition du segment sur lequel interpoler. */ Eblock ETes Eblock ETes EGAL(lambda_vertical,DIVI(FLOT(SOUS(Y,Y_bas)),FLOT(SOUS(Y_haut,Y_bas)))); /* Calcul du parametre d'interpolation. */ Eblock ATes Bblock PRINT_ERREUR("le point du haut est en bas et reciproquement"); Eblock ETes Eblock ATes Bblock Eblock ETes Test(IFET(IFET(IFLE(LENG(niveau_standard_a_gauche,niveau_standard_courant) ,Istd_float_avec_interpolation_____seuil_d_interpolation ) ,IFLE(LENG(niveau_standard_courant,niveau_standard_a_droite) ,Istd_float_avec_interpolation_____seuil_d_interpolation ) ) ,IFET(IFLE(LENG(niveau_standard_en_bas,niveau_standard_courant) ,Istd_float_avec_interpolation_____seuil_d_interpolation ) ,IFLE(LENG(niveau_standard_courant,niveau_standard_en_haut) ,Istd_float_avec_interpolation_____seuil_d_interpolation ) ) ) ) Bblock /* Cas ou le niveau du point courant {X,Y} est assez proche du niveau de gauche (du bas */ /* respectivement) et de celui de droite (ou du haut respectivement) : */ Test(IL_FAUT(interpoler_lineairement)) Bblock EGAL(niveau_flottant_interpole_horizontal ,INTERPOLATION_LINEAIRE(niveau_standard_Origine_horizontal ,niveau_standard_Extremite_horizontal ,lambda_horizontal ) ); EGAL(niveau_flottant_interpole_vertical ,INTERPOLATION_LINEAIRE(niveau_standard_Origine_vertical ,niveau_standard_Extremite_vertical ,lambda_vertical ) ); /* Et enfin, interpolation lineaire. ATTENTION, c'est bien 'niveau_flottant_courant' et */ /* non pas 'niveau_standard_a_gauche' qu'il convient d'utiliser comme "Origine" de */ /* l'interpolation, sinon, on introduit des "rebonds" (de meme 'niveau_standard_en_bas'). */ Eblock ATes Bblock EGAL(niveau_flottant_interpole_horizontal ,INTERPOLATION_CUBIQUE(niveau_standard_Origine_horizontal ,DERIVATION_NUMERIQUE(niveau_standard_Origine_horizontal ,niveau_standard_Origine_horizontal ) ,niveau_standard_Extremite_horizontal ,DERIVATION_NUMERIQUE(niveau_standard_Origine_horizontal ,niveau_standard_Extremite_horizontal ) ,lambda_horizontal ) ); EGAL(niveau_flottant_interpole_vertical ,INTERPOLATION_CUBIQUE(niveau_standard_Origine_vertical ,DERIVATION_NUMERIQUE(niveau_standard_Origine_vertical ,niveau_standard_Origine_vertical ) ,niveau_standard_Extremite_vertical ,DERIVATION_NUMERIQUE(niveau_standard_Origine_vertical ,niveau_standard_Extremite_vertical ) ,lambda_vertical ) ); /* Et enfin, interpolation cubique. ATTENTION, c'est bien 'niveau_flottant_courant' et */ /* non pas 'niveau_standard_a_gauche' qu'il convient d'utiliser comme "Origine" de */ /* l'interpolation, sinon, on introduit des "rebonds" (de meme 'niveau_standard_en_bas'). */ Eblock ETes EGAL(niveau_flottant_interpole ,SCALE_POINT(niveau_minimal ,niveau_maximal ,LRZ3(Istd_float_avec_interpolation_____ponderation_de_la_moyenne_geometrique ,MOYZ(niveau_flottant_interpole_horizontal,niveau_flottant_interpole_vertical) ,Istd_float_avec_interpolation_____ponderation_de_l_interpolation_horizontale ,niveau_flottant_interpole_horizontal ,Istd_float_avec_interpolation_____ponderation_de_l_interpolation_verticale ,niveau_flottant_interpole_vertical ) ,NOIR ,BLANC ) ); /* Puis interpolation "croise, et enfin, "renormalisation"... */ Eblock ATes Bblock /* Cas ou le niveau du point courant {X,Y} n'est pas assez proche du niveau de gauche (du */ /* bas respectivement) et de celui de droite (ou du haut respectivement) : dans ces */ /* conditions il faut conserver le niveau courant (voir par exemple le cas d'un point BLANC */ /* entoure que par du NOIR, en l'absence de ce test, ce point deviendrait NOIR puisqu'il */ /* serait interpole entre deux NOIRs...). */ Eblock ETes Eblock ETes storeF_point(niveau_flottant_interpole,imageR,X,Y); /* Enfin, rangement du niveau interpole. */ Eblock end_image RETIF(imageR); Eblock #undef DERIVATION_NUMERIQUE EFonctionF _______________________________________________________________________________________________________________________________________ _______________________________________________________________________________________________________________________________________ /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* C O N V E R S I O N " S T A N D A R D " --> " D O U B L E " : */ /* */ /*************************************************************************************************************************************/ BFonctionD DEFV(Common,DEFV(FonctionD,POINTERD(Istd_double(imageR,niveau_minimal,niveau_maximal,imageA)))) DEFV(Argument,DEFV(imageD,imageR)); /* Image Resultat, telle que le format des "pixels" change : */ /* */ /* imageR(Double)=imageA(std). */ /* */ DEFV(Argument,DEFV(Double,niveau_minimal)); /* Donne le niveau minimal de l'image Resultat (en general 'NOIR_double'). */ DEFV(Argument,DEFV(Double,niveau_maximal)); /* Donne le niveau maximal de l'image Resultat (en general 'BLANC_double'). */ DEFV(Argument,DEFV(image,imageA)); /* Image Argument. */ /*-----------------------------------------------------------------------------------------------------------------------------------*/ Bblock /*..............................................................................................................................*/ Test(IFEQ(niveau_minimal,niveau_maximal)) Bblock CALS(IDinitialisation(imageR,DPRE(NOIR))); /* Lorsque les niveaux minimal et maximal sont egaux, on se fixe */ /* a priori au plancher ('NOIR')... */ Eblock ATes Bblock begin_image Bblock storeD_point(SCALE_POINT(niveau_minimal,niveau_maximal,load_point(imageA,X,Y),NOIR,BLANC) ,imageR ,X,Y ); /* Sinon, on interpole entre-eux deux. */ Eblock end_image Eblock ETes RETID(imageR); Eblock EFonctionD _______________________________________________________________________________________________________________________________________ _______________________________________________________________________________________________________________________________________ /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* C O N V E R S I O N " C H A R " --> " S T A N D A R D " : */ /* */ /*************************************************************************************************************************************/ BFonctionP DEFV(Common,DEFV(FonctionP,POINTERp(Ichar_std(imageR,imageA)))) DEFV(Argument,DEFV(image,imageR)); /* Image Resultat, telle que le format des "pixels" change : */ /* */ /* imageR(std)=imageA(CHAR). */ /* */ DEFV(Argument,DEFV(imageC,imageA)); /* Image Argument. */ /*-----------------------------------------------------------------------------------------------------------------------------------*/ Bblock /*..............................................................................................................................*/ begin_image Bblock store_point(GENP(SCALE_POINT(NOIR,BLANC,loadC_point(imageA,X,Y),NOIR_char,BLANC_char)),imageR,X,Y,FVARIABLE); Eblock end_image RETI(imageR); Eblock EFonctionP _______________________________________________________________________________________________________________________________________ _______________________________________________________________________________________________________________________________________ /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* C O N V E R S I O N " I N T " --> " S T A N D A R D " : */ /* */ /*************************************************************************************************************************************/ BFonctionP DEFV(Common,DEFV(FonctionP,POINTERp(Iint_std(imageR,imageA)))) DEFV(Argument,DEFV(image,imageR)); /* Image Resultat, telle que le format des "pixels" change : */ /* */ /* imageR(std)=imageA(Int). */ /* */ DEFV(Argument,DEFV(imageI,imageA)); /* Image Argument. */ /*-----------------------------------------------------------------------------------------------------------------------------------*/ Bblock /*..............................................................................................................................*/ begin_image Bblock store_point(GENP(SCALE_POINT(NOIR,BLANC,loadI_point(imageA,X,Y),NOIR_int,BLANC_int)),imageR,X,Y,FVARIABLE); Eblock end_image RETI(imageR); Eblock EFonctionP _______________________________________________________________________________________________________________________________________ _______________________________________________________________________________________________________________________________________ /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* C O N V E R S I O N " I N T " --> " F L O A T " : */ /* */ /*************************************************************************************************************************************/ BFonctionF DEFV(Common,DEFV(FonctionF,POINTERF(Iint_float(imageR,imageA)))) DEFV(Argument,DEFV(imageF,imageR)); /* Image Resultat, telle que le format des "pixels" change : */ /* */ /* imageR(Float)=imageA(Int). */ /* */ DEFV(Argument,DEFV(imageI,imageA)); /* Image Argument. */ /*-----------------------------------------------------------------------------------------------------------------------------------*/ Bblock /*..............................................................................................................................*/ begin_image Bblock storeF_point(loadI_point(imageA,X,Y) ,imageR ,X,Y ); Eblock end_image RETIF(imageR); Eblock EFonctionF _______________________________________________________________________________________________________________________________________ _______________________________________________________________________________________________________________________________________ /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* C O N V E R S I O N " F L O A T " --> " S T A N D A R D " B R U T A L E : */ /* */ /*************************************************************************************************************************************/ BFonctionP DEFV(Common,DEFV(FonctionP,POINTERp(Ifloat_std_brutal(imageR,imageA)))) /* Fonction introduite le 20080902105754... */ DEFV(Argument,DEFV(image,imageR)); /* Image Resultat, telle que le format des "pixels" change : */ /* */ /* imageR(std)=imageA(Float). */ /* */ DEFV(Argument,DEFV(imageF,imageA)); /* Image Argument. */ /*-----------------------------------------------------------------------------------------------------------------------------------*/ Bblock begin_image Bblock DEFV(genere_Float,INIT(niveau_courant,loadF_point(imageA,X,Y))); /* Niveau du point courant {X,Y} avant conversion. */ DEFV(genere_p,INIT(niveau_converti,NIVEAU_UNDEF)); /* Niveau du point courant {X,Y} apres conversion "brutale", c'est-a-dire sans verifier */ /* qu'elle est compatible avec les formats... */ EGAL(niveau_converti,GENP(niveau_courant)); store_point(niveau_converti ,imageR ,X,Y ,FVARIABLE ); /* Enfin, rangement du niveau converti "brutalement"... */ Eblock end_image RETI(imageR); Eblock EFonctionP _______________________________________________________________________________________________________________________________________ _______________________________________________________________________________________________________________________________________ /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* C O N V E R S I O N " F L O A T " --> " S T A N D A R D " : */ /* */ /*************************************************************************************************************************************/ BFonctionP DEFV(Common,DEFV(Logical,SINT(Ifloat_std_____editer_le_message_d_attention_relatif_aux_extrema,VRAI))); /* Cette option a ete introduite pour 'v $xiirf/.FRA3.S2.2.$U message_attention_extrema' */ /* le 20101109160703. */ DEFV(Common,DEFV(Logical,SINT(Ifloat_std_____calculer_le_niveau_plancher_a_utiliser_si_les_extrema_sont_egaux,FAUX))); /* Cette possibilite de calculer le niveau plancher a ete introduite le 20200120140225 */ /* pour 'v $xiav/STRX.41$COORD_Z$R16' (en particulier...). */ DEFV(Common,DEFV(genere_p,SINT(Ifloat_std_____niveau_plancher_a_utiliser_si_les_extrema_sont_egaux,NOIR))); /* Definition du niveau "plancher" a utiliser si les extrema de 'imageA' sont egaux. Ceci */ /* fut introduit le 20071024151413 et est inutilise a cette date... */ DEFV(Common,DEFV(Logical,SINT(Ifloat_std_____conserver_le_zero,FAUX))); /* Cette option introduite le 20030909185023 permet de conserver le zero lors des */ /* conversions. Sa valeur par defaut ('FAUX') assure la compatibilite avec les versions */ /* anterieures au 20030909185023. On notera qu'evidemment avec la valeur 'VRAI', la */ /* fonction 'Ifloat_std(...)' equivaut a la fonction 'Ifloat_std_avec_le_vrai_zero(...)' ; */ /* malgre cette redondance, cela a ete introduit pour donner cette fonctionnalite aux '$K's */ /* qui utilisent 'Ifloat_std(...)' sans avoir a les modifier... */ DEFV(Common,DEFV(Logical,SINT(Ifloat_std_____seul_le_niveau_minimal_donnera_du_NOIR,FAUX))); /* Cette option introduite le 20040909094335 permet de faire que seul le niveau minimal */ /* flottant argument ('niveau_minimal') donnera du 'NOIR'. Cela n'a evidemment de sens que */ /* si 'IL_NE_FAUT_PAS(Ifloat_std_____conserver_le_zero)'... */ DEFV(Common,DEFV(Float,SINT(Ifloat_std_____epsilon_de_seuillage_inferieur_par_rapport_au_niveau_minimal,D_EPSILON))); /* En augmentant ce seuil, il est possible d'eliminer des "underflows" de conversion... */ #define EXTREMA_EFFECTIFS_DE_Ifloat_std(niveau_minimal_effectif,niveau_maximal_effectif,niveau_minimal,niveau_maximal) \ Bblock \ EGAL(niveau_maximal_effectif,NEUT(MAX2(ABSO(niveau_minimal),ABSO(niveau_maximal)))); \ EGAL(niveau_minimal_effectif,NEGA(niveau_maximal_effectif)); \ Eblock \ /* Extrema a utiliser dans 'Ifloat_std(...)' et 'Ifloat_std_avec_le_vrai_zero(...)' afin de */ \ /* conserver le zero... */ DEFV(Common,DEFV(genere_p,SINT(Ifloat_std_____niveau_NOIR,NOIR))); DEFV(Common,DEFV(genere_p,SINT(Ifloat_std_____niveau_BLANC,BLANC))); /* Definition du {NOIR,BLANC} pour 'imageR'. */ DEFV(Common,DEFV(FonctionP,POINTERp(Ifloat_std(imageR,imageA,niveau_minimal,niveau_maximal)))) DEFV(Argument,DEFV(image,imageR)); /* Image Resultat, telle que le format des "pixels" change : */ /* */ /* imageR(std)=imageA(Float). */ /* */ DEFV(Argument,DEFV(imageF,imageA)); /* Image Argument. */ DEFV(Argument,DEFV(genere_Float,niveau_minimal)); /* Donne le niveau minimal de l'image Argument (en general 'FLOT__NOIR'). */ DEFV(Argument,DEFV(genere_Float,niveau_maximal)); /* Donne le niveau maximal de l'image Argument (en general 'FLOT__BLANC'). */ /*-----------------------------------------------------------------------------------------------------------------------------------*/ Bblock /*..............................................................................................................................*/ Test(IFOU(IFGE(niveau_minimal,niveau_maximal) ,IFLE(niveau_maximal ,ADD2(niveau_minimal,Ifloat_std_____epsilon_de_seuillage_inferieur_par_rapport_au_niveau_minimal) ) ) ) /* Le 20000929180244 le 'IFEQ(niveau_minimal,niveau_maximal)' a ete remplace par un */ /* 'IFGE(...)' plus "sur" et le test sur l'epsilon a ete ajoute... */ Bblock Test(IL_FAUT(Ifloat_std_____editer_le_message_d_attention_relatif_aux_extrema)) /* Test introduit le 20101109160703... */ Bblock PRINT_ATTENTION("les niveaux 'minimal' et 'maximal' sont egaux ou dans l'ordre inverse, on force le niveau 'NOIR'"); CAL1(Prer1("ils valent tous les deux : %g\n",CHOI(niveau_minimal,niveau_maximal))); CAL1(Prer1("(le niveau 'NOIR' reellement utilise vaut %d)\n" ,Ifloat_std_____niveau_plancher_a_utiliser_si_les_extrema_sont_egaux ) ); Eblock ATes Bblock Eblock ETes Test(IL_FAUT(Ifloat_std_____calculer_le_niveau_plancher_a_utiliser_si_les_extrema_sont_egaux)) /* Test introduit le 20200120140225... */ Bblock CALS(Iinitialisation(imageR,__DENORMALISE_NIVEAU(CHOI(niveau_minimal,niveau_maximal)))); /* Lorsque les niveaux minimal et maximal sont egaux, on denormalise le niveau unique... */ Eblock ATes Bblock CALS(Iinitialisation(imageR,Ifloat_std_____niveau_plancher_a_utiliser_si_les_extrema_sont_egaux)); /* Lorsque les niveaux minimal et maximal sont egaux, on se fixe */ /* a priori au plancher ('NOIR')... */ Eblock ETes Eblock ATes Bblock DEFV(genere_Float,INIT(niveau_minimal_effectif,niveau_minimal)); DEFV(genere_Float,INIT(niveau_maximal_effectif,niveau_maximal)); /* Extrema effectif de l'image Argument. */ Test(IL_FAUT(Ifloat_std_____conserver_le_zero)) Bblock EXTREMA_EFFECTIFS_DE_Ifloat_std(niveau_minimal_effectif,niveau_maximal_effectif,niveau_minimal,niveau_maximal); /* Cas ou le zero doit etre conserve... */ Eblock ATes Bblock Eblock ETes begin_image Bblock DEFV(genere_Float,INIT(niveau_courant,loadF_point(imageA,X,Y))); /* Niveau du point courant {X,Y} avant conversion. */ DEFV(genere_p,INIT(niveau_converti,NIVEAU_UNDEF)); /* Niveau du point courant {X,Y} apres conversion (introduit le 20040909094335). */ Test(IFLE(niveau_courant ,ADD2(niveau_minimal_effectif,Ifloat_std_____epsilon_de_seuillage_inferieur_par_rapport_au_niveau_minimal) ) ) Bblock EGAL(niveau_courant,niveau_minimal_effectif); /* Pour eviter des "underflows" dans 'SCALE_POINT(...)' lorsque sera calculee la */ /* quantite 'niveau_courant-niveau_minimal' ci-apres (introduit le 20000929102058). */ Eblock ATes Bblock Eblock ETes EGAL(niveau_converti ,GENP(FLIN(SCALE_POINT(Ifloat_std_____niveau_NOIR,Ifloat_std_____niveau_BLANC ,niveau_courant ,niveau_minimal_effectif,niveau_maximal_effectif ) ,Ifloat_std_____translation_d_arrondi_au_plus_proche_entier ) ) ); /* Sinon, on interpole entre-eux deux ; on notera qu'autrefois, on faisait un */ /* 'ARRI(SCALE_POINT(...))', mais qu'il fut supprime a cause de sorties de l'intervalle */ /* [NOIR,BLANC] que cela pouvait creer dans des operations ulterieures. Le 20020315122536, */ /* j'ai remarque qu'en fait il fallait le reintroduire (mais afin d'assurer la compatibilite */ /* avec les generations anterieures, c'est en fait 'FLIN(...)', associee a un parametre que */ /* l'on peut annuler, qui est utilisee). En effet, les tests ont montre que : */ /* */ /* 0.50196078431373*255 = 128 */ /* */ /* et : */ /* */ /* 0.50196078431372*255 = 127 */ /* */ /* alors que l'on attend en fait : */ /* */ /* 0.50000000000000*255 = 128 */ /* */ /* et : */ /* */ /* 0.49999999999999*255 = 127 */ /* */ /* d'ou cette solution... */ Test(EST_VRAI(Ifloat_std_____seul_le_niveau_minimal_donnera_du_NOIR)) Bblock Test(IFET(IFGT(niveau_courant,niveau_minimal_effectif),IFEQ(niveau_converti,NOIR))) Bblock EGAL(niveau_converti,NOIR_PLANCHER); /* Lorsque cela est demande, on fait en sorte que seul le niveau minimal flottant donne */ /* du NOIR (introduit le 20040909094335 pour 'v $xiirf/.COT2.G1.1.$U NOIR_unique'. */ Eblock ATes Bblock Eblock ETes Eblock ATes Bblock Eblock ETes store_point(niveau_converti ,imageR ,X,Y ,FVARIABLE ); /* Enfin, rangement du niveau converti... */ Eblock end_image Eblock ETes RETI(imageR); Eblock EFonctionP /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* C O N V E R S I O N " S T A N D A R D " --> " F L O A T " : */ /* */ /*************************************************************************************************************************************/ BFonctionF DEFV(Common,DEFV(FonctionF,POINTERF(Istd_float(imageR,niveau_minimal,niveau_maximal,imageA)))) DEFV(Argument,DEFV(imageF,imageR)); /* Image Resultat, telle que le format des "pixels" change : */ /* */ /* imageR(Float)=imageA(std). */ /* */ DEFV(Argument,DEFV(genere_Float,niveau_minimal)); /* Donne le niveau minimal de l'image Resultat (en general 'FLOT__NOIR'). */ DEFV(Argument,DEFV(genere_Float,niveau_maximal)); /* Donne le niveau maximal de l'image Resultat (en general 'FLOT__BLANC'). */ DEFV(Argument,DEFV(image,imageA)); /* Image Argument. */ /*-----------------------------------------------------------------------------------------------------------------------------------*/ Bblock /*..............................................................................................................................*/ Test(IFEQ(niveau_minimal,niveau_maximal)) Bblock CALS(IFinitialisation(imageR,FLOT__NOIR)); /* Lorsque les niveaux minimal et maximal sont egaux, on se fixe */ /* a priori au plancher ('NOIR')... */ Eblock ATes Bblock begin_image Bblock storeF_point(SCALE_POINT(niveau_minimal,niveau_maximal,load_point(imageA,X,Y),NOIR,BLANC) ,imageR ,X,Y ); /* Sinon, on interpole entre-eux deux. */ Eblock end_image Eblock ETes RETIF(imageR); Eblock EFonctionF /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* C O N V E R S I O N " S T A N D A R D " --> " F L O A T " A V E C N O R M A L I S A T I O N : */ /* */ /*************************************************************************************************************************************/ BFonctionF DEFV(Common,DEFV(FonctionF,POINTERF(Istd_float_avec_normalisation(imageR,imageA)))) /* Fonction introduite le 20090318140048... */ DEFV(Argument,DEFV(imageF,imageR)); /* Image Resultat, telle que le format des "pixels" change : */ /* */ /* imageR(Float)=imageA(std) dans [0,1]. */ /* */ DEFV(Argument,DEFV(image,imageA)); /* Image Argument. */ /*-----------------------------------------------------------------------------------------------------------------------------------*/ Bblock DEFV(genere_Float,INIT(niveau_minimum,FLOT__NIVEAU_UNDEF)); DEFV(genere_Float,INIT(niveau_maximum,FLOT__NIVEAU_UNDEF)); /* Niveaux extrema de 'imageA'. */ BDEFV(imageF,imageA_flottante); /* 'imageA' convertie en flottant. */ /*..............................................................................................................................*/ CALS(Istd_float(imageA_flottante,FLOT__NOIR,FLOT__BLANC,imageA)); /* Conversion... */ CALS(IFnivo_extrema(imageA_flottante,ADRESSE(niveau_minimum),ADRESSE(niveau_maximum))); CALS(IFnormalisation(imageR,imageA_flottante,niveau_minimum,niveau_maximum)); /* Et normalisation (dans [0,1] par defaut...). */ EDEFV(imageF,imageA_flottante); /* 'imageA' convertie en flottant. */ RETIF(imageR); Eblock EFonctionF /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* C O N V E R S I O N " F L O A T " --> " S T A N D A R D " A V E C R E N O R M A L I S A T I O N : */ /* */ /*************************************************************************************************************************************/ BFonctionP DEFV(Common,DEFV(FonctionP,POINTERp(Ifloat_std_avec_renormalisation(imageR,imageA)))) DEFV(Argument,DEFV(image,imageR)); /* Image Resultat, telle que le format des "pixels" change : */ /* */ /* imageR(std)=imageA(Float) mais renormalisee afin d'utiliser pleinement [NOIR,BLANC]. */ /* */ DEFV(Argument,DEFV(imageF,imageA)); /* Image Argument. */ /*-----------------------------------------------------------------------------------------------------------------------------------*/ Bblock DEFV(genere_Float,INIT(niveau_minimal,FLOT__NIVEAU_UNDEF)); DEFV(genere_Float,INIT(niveau_maximal,FLOT__NIVEAU_UNDEF)); /* Afin de rechercher les niveaux minimal et maximal de 'imageA'. */ /*..............................................................................................................................*/ CALS(IFnivo_extrema(imageA ,ADRESSE(niveau_minimal) ,ADRESSE(niveau_maximal) ) ); /* Recherche des extrema de 'imageA'. */ CALS(Ifloat_std(imageR ,imageA ,niveau_minimal ,niveau_maximal ) ); /* Generation de 'imageR' (avec renormalisation). */ RETI(imageR); Eblock EFonctionP /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* R E N O R M A L I S A T I O N " S T A N D A R D " : */ /* */ /*************************************************************************************************************************************/ BFonctionP DEFV(Common,DEFV(Float,SINT(Irenormalisation_____niveau_minimal,FLOT__NOIR))); DEFV(Common,DEFV(Float,SINT(Irenormalisation_____niveau_maximal,FLOT__BLANC))); /* Introduit le 20220123181142, cela peut toujours servir... */ DEFV(Common,DEFV(FonctionP,POINTERC(Irenormalisation(imageR,imageA)))) /* Fonction introduite le 20220123141657 pour 'v $xiii/tri_image$FON 20220123142321'... */ DEFV(Argument,DEFV(imageC,imageR)); /* Image Resultat. */ DEFV(Argument,DEFV(image,imageA)); /* Image Argument. */ /*-----------------------------------------------------------------------------------------------------------------------------------*/ Bblock BDEFV(imageF,image_flottante); /* Image flottante dans laquelle on trouve l'image a renormaliser. */ /*..............................................................................................................................*/ CALS(Istd_float(image_flottante,Irenormalisation_____niveau_minimal,Irenormalisation_____niveau_maximal,imageA)); CALS(Ifloat_std_avec_renormalisation(imageR,image_flottante)); /* Lorsqu'il faut renormaliser, on passe par une representation flottante intermediaire... */ EDEFV(imageF,image_flottante); RETI(imageR); Eblock EFonctionP /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* C O N V E R S I O N " F L O A T " --> " S T A N D A R D " */ /* E N C O N S E R V A N T L A P O S I T I O N D U V R A I Z E R O : */ /* */ /*************************************************************************************************************************************/ BFonctionP DEFV(Common,DEFV(FonctionP,POINTERp(Ifloat_std_avec_le_vrai_zero(imageR,imageA,niveau_minimal,niveau_maximal)))) DEFV(Argument,DEFV(image,imageR)); /* Image Resultat, telle que le format des "pixels" change : */ /* */ /* imageR(std)=imageA(Float) mais renormalisee avec le vrai zero asscoie au 'GRIS'. */ /* */ DEFV(Argument,DEFV(imageF,imageA)); /* Image Argument. */ DEFV(Argument,DEFV(genere_Float,niveau_minimal)); /* Donne le niveau minimal de l'image Argument (en general 'FLOT__NOIR'). */ DEFV(Argument,DEFV(genere_Float,niveau_maximal)); /* Donne le niveau maximal de l'image Argument (en general 'FLOT__BLANC'). */ /*-----------------------------------------------------------------------------------------------------------------------------------*/ Bblock DEFV(genere_Float,INIT(faux_niveau_minimal,FLOT__NIVEAU_UNDEF)); DEFV(genere_Float,INIT(faux_niveau_maximal,FLOT__NIVEAU_UNDEF)); /* Afin de conserver la position du zero... */ /*..............................................................................................................................*/ EXTREMA_EFFECTIFS_DE_Ifloat_std(faux_niveau_minimal,faux_niveau_maximal,niveau_minimal,niveau_maximal); /* Recherche des faux extrema de 'imageA' tel que le zero soit conserve... */ CALS(Ifloat_std(imageR ,imageA ,faux_niveau_minimal ,faux_niveau_maximal ) ); /* Generation de 'imageR' (avec renormalisation et conservation du zero...). */ RETI(imageR); Eblock EFonctionP #undef EXTREMA_EFFECTIFS_DE_Ifloat_std /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* C O N V E R S I O N " F L O A T " --> " S T A N D A R D " A V E C R E N O R M A L I S A T I O N */ /* E N C O N S E R V A N T L A P O S I T I O N D U V R A I Z E R O : */ /* */ /*************************************************************************************************************************************/ BFonctionP DEFV(Common,DEFV(FonctionP,POINTERp(Ifloat_std_avec_le_vrai_zero_et_renormalisation(imageR,imageA)))) DEFV(Argument,DEFV(image,imageR)); /* Image Resultat, telle que le format des "pixels" change : */ /* */ /* imageR(std)=imageA(Float) mais renormalisee avec le vrai zero asscoie au 'GRIS'. */ /* */ DEFV(Argument,DEFV(imageF,imageA)); /* Image Argument. */ /*-----------------------------------------------------------------------------------------------------------------------------------*/ Bblock DEFV(genere_Float,INIT(vrai_niveau_minimal,FLOT__NIVEAU_UNDEF)); DEFV(genere_Float,INIT(vrai_niveau_maximal,FLOT__NIVEAU_UNDEF)); /* Afin de rechercher les vrais niveaux minimal et maximal de 'imageA'. */ /*..............................................................................................................................*/ CALS(IFnivo_extrema(imageA ,ADRESSE(vrai_niveau_minimal) ,ADRESSE(vrai_niveau_maximal) ) ); /* Recherche des vrais extrema de 'imageA'. */ CALS(Ifloat_std_avec_le_vrai_zero(imageR ,imageA ,vrai_niveau_minimal ,vrai_niveau_maximal ) ); /* Generation de 'imageR' (avec renormalisation et conservation du zero...). */ RETI(imageR); Eblock EFonctionP /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* C O N V E R S I O N " F L O A T " --> " S T A N D A R D " D U ' Z - B U F F E R ' : */ /* */ /*************************************************************************************************************************************/ BFonctionP DEFV(Common,DEFV(FonctionP,POINTERp(Ifloat_std_du_Z_Buffer(imageR)))) DEFV(Argument,DEFV(image,imageR)); /* Image Resultat, telle que le format des "pixels" change : */ /* */ /* imageR(std)=Z_Buffer(Float) mais renormalisee afin d'utiliser pleinement [NOIR,BLANC]. */ /* */ /*-----------------------------------------------------------------------------------------------------------------------------------*/ Bblock BDEFV(imageF,Z_Buffer_filtre); /* Valeur du 'Z-Buffer' apres filtrage "passe-bande". */ DEFV(genere_Float,INIT(valeur_de_marquage_de_la_valeur_d_initialisation_du_Z_Buffer ,SOUS(Z_Buffer_____minimum ,DIVI(NEUT(SOUS(Z_Buffer_____maximum,Z_Buffer_____minimum)) ,PRED(SOUS(FLOT__BLANC,FLOT__NOIR)) ) ) ) ); /* Valeur qui sera substituee a la valeur d'initialisation du 'Z-Buffer'. */ /*..............................................................................................................................*/ CALS(IFpasse_bande(Z_Buffer_filtre ,Z_Buffer ,Z_Buffer_____minimum,Z_Buffer_____maximum ,valeur_de_marquage_de_la_valeur_d_initialisation_du_Z_Buffer,Z_Buffer_____maximum ) ); /* Filtrage "passe-bande" du 'Z-Buffer' ; on notera que l'on ne peut utiliser la fonction */ /* 'IFnivo_extrema(...)' dans le cas du 'Z-Buffer' car, en effet, en ce qui concerne le */ /* 'niveau_minimal', on recupererait la valeur d'initialisation... */ CALS(Ifloat_std(imageR ,Z_Buffer_filtre ,valeur_de_marquage_de_la_valeur_d_initialisation_du_Z_Buffer ,Z_Buffer_____maximum ) ); /* Generation de 'imageR' (avec renormalisation). */ EDEFV(imageF,Z_Buffer_filtre); /* Valeur du 'Z-Buffer' apres filtrage "passe-bande". */ RETI(imageR); Eblock EFonctionP /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* C O N V E R S I O N " F L O A T " --> " S T A N D A R D " D U ' Z - B U F F E R A C C U M U L E ' : */ /* */ /*************************************************************************************************************************************/ BFonctionP DEFV(Common,DEFV(FonctionP,POINTERp(Ifloat_std_du_Z_Buffer_accumule(imageR)))) DEFV(Argument,DEFV(image,imageR)); /* Image Resultat, telle que le format des "pixels" change : */ /* */ /* imageR(std)=Z_Buffer_accumule(Float) mais renormalisee afin d'utiliser pleinement */ /* [NOIR,BLANC]. */ /* */ /*-----------------------------------------------------------------------------------------------------------------------------------*/ Bblock BDEFV(imageF,Z_Buffer_accumule_filtre); /* Valeur du 'Z-Buffer_accumule' apres filtrage "passe-bande". */ DEFV(genere_Float,INIT(valeur_de_marquage_de_la_valeur_d_initialisation_du_Z_Buffer_accumule ,SOUS(Z_Buffer_accumule_____minimum ,DIVI(NEUT(SOUS(Z_Buffer_accumule_____maximum,Z_Buffer_accumule_____minimum)) ,PRED(SOUS(FLOT__BLANC,FLOT__NOIR)) ) ) ) ); /* Valeur qui sera substituee a la valeur d'initialisation du 'Z-Buffer accumule'. */ /*..............................................................................................................................*/ CALS(IFpasse_bande(Z_Buffer_accumule_filtre ,Z_Buffer_accumule ,Z_Buffer_accumule_____minimum,Z_Buffer_accumule_____maximum ,valeur_de_marquage_de_la_valeur_d_initialisation_du_Z_Buffer_accumule,Z_Buffer_accumule_____maximum ) ); /* Filtrage "passe-bande" du 'Z-Buffer accumule' ; on notera que l'on ne peut utiliser la */ /* fonction 'IFnivo_extrema(...)' dans le cas du 'Z-Buffer accumule' car, en effet, en ce */ /* qui concerne le 'niveau_minimal', on recupererait la valeur d'initialisation... */ CALS(Ifloat_std(imageR ,Z_Buffer_accumule_filtre ,valeur_de_marquage_de_la_valeur_d_initialisation_du_Z_Buffer_accumule ,Z_Buffer_accumule_____maximum ) ); /* Generation de 'imageR' (avec renormalisation). */ EDEFV(imageF,Z_Buffer_accumule_filtre); /* Valeur du 'Z-Buffer accumule' apres filtrage "passe-bande". */ RETI(imageR); Eblock EFonctionP _______________________________________________________________________________________________________________________________________ _______________________________________________________________________________________________________________________________________ /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* C O N V E R S I O N " F L O A T " --> " S T A N D A R D " A V E C T R O N C A T I O N : */ /* */ /*************************************************************************************************************************************/ BFonctionP DEFV(Common,DEFV(Logical,SINT(Ifloat_std_avec_troncation_____editer_le_message_d_attention_relatif_aux_extrema,VRAI))); /* Cette option a ete introduite le 20160421103350 par "symetrie" avec */ /* 'Ifloat_std_____editer_le_message_d_attention_relatif_aux_extrema'... */ DEFV(Common,DEFV(Logical,SINT(Ifloat_std_avec_troncation_____eviter_les_faux_points_NOIRs,VRAI))); /* Cette option permet d'assurer (a l'etat 'FAUX') la compatibilite avec les versions */ /* anterieures au 20021111104829. */ DEFV(Common,DEFV(FonctionP,POINTERp(Ifloat_std_avec_troncation(imageR,imageA,niveau_minimal,niveau_maximal)))) DEFV(Argument,DEFV(image,imageR)); /* Image Resultat, telle que le format des "pixels" change : */ /* */ /* imageR(std)=imageA(Float) tronque dans [niveau_minimal,niveau_maximal]. */ /* */ DEFV(Argument,DEFV(imageF,imageA)); /* Image Argument. */ DEFV(Argument,DEFV(genere_Float,niveau_minimal)); /* Donne le niveau minimal de l'image Argument (en general 'FLOT__NOIR'). */ DEFV(Argument,DEFV(genere_Float,niveau_maximal)); /* Donne le niveau maximal de l'image Argument (en general 'FLOT__BLANC'). */ /*-----------------------------------------------------------------------------------------------------------------------------------*/ Bblock /*..............................................................................................................................*/ Test(IFEQ(niveau_minimal,niveau_maximal)) Bblock Test(IL_FAUT(Ifloat_std_avec_troncation_____editer_le_message_d_attention_relatif_aux_extrema)) /* Test introduit le 20160421103350... */ Bblock PRINT_ATTENTION("les niveaux 'minimal' et 'maximal' sont egaux, on force le niveau 'NOIR'"); CAL1(Prer1("ils valent tous les deux : %g\n",CHOI(niveau_minimal,niveau_maximal))); Eblock ATes Bblock Eblock ETes CALS(Inoir(imageR)); /* Lorsque les niveaux minimal et maximal sont egaux, on se fixe */ /* a priori au plancher ('NOIR')... */ Eblock ATes Bblock begin_image Bblock DEFV(genere_Float,INIT(niveau_courant_avant_conversion,loadF_point(imageA,X,Y))); DEFV(genere_p,INIT(niveau_courant_apres_conversion,NIVEAU_UNDEF)); /* Niveau du point courant {X,Y} avant, puis apres conversion... */ EGAL(niveau_courant_apres_conversion,GENP(TRON(niveau_courant_avant_conversion,niveau_minimal,niveau_maximal))); /* Conversion a priori... */ Test(IL_FAUT(Ifloat_std_avec_troncation_____eviter_les_faux_points_NOIRs)) /* Afin d'assurer la compatibilite avec les versions anterieures au 20021111104829. */ Bblock Test(IFET(IFEQ(niveau_minimal,FLOT__NOIR),IFEQ(niveau_maximal,FLOT__BLANC))) /* Ainsi, on ne traite que les images a dynamique [FLOT__NOIR,FLOT__BLANC]. */ Bblock Test(IFET(IFEQ(niveau_courant_apres_conversion,NOIR),IFNE(niveau_courant_avant_conversion,niveau_minimal))) /* Ainsi, on ne traite que les points ne correspondant pas au niveau minimal, mais qui */ /* malgre tout deviennent 'NOIR' par conversion... */ Bblock EGAL(niveau_courant_apres_conversion,NOIR_PLANCHER); /* Ce dispositif a ete introduit le 20021111104829 suite a un defaut observe lors de la */ /* generation de l'image 'v $xiic/champ.30001$D/MORL.100615$D/pro$Mo$Ph$D/VORTIC.12$M'. */ /* En effet, l'operation '$xci/lissage$X' contenue dans '$xci/acces_RVB.31$Z' conduit a */ /* quelques points qui deviennent 'NOIR's lors de la conversion faite par '$xci/acces$X'. */ /* Ces points 'NOIR's restent 'NOIR's lorsque la palette '$xiP/gris.11' est appliquee via */ /* '$xci/substitue$X' ; ils deviennent alors tres visibles... */ Eblock ATes Bblock Eblock ETes Eblock ATes Bblock Eblock ETes Eblock ATes Bblock Eblock ETes store_point(niveau_courant_apres_conversion ,imageR ,X,Y ,FVARIABLE ); Eblock end_image Eblock ETes RETI(imageR); Eblock EFonctionP _______________________________________________________________________________________________________________________________________ _______________________________________________________________________________________________________________________________________ /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* C O N V E R S I O N " F L O A T " --> " I N T " : */ /* */ /*************************************************************************************************************************************/ BFonctionI DEFV(Common,DEFV(FonctionI,POINTERI(Ifloat_int(imageR,imageA)))) DEFV(Argument,DEFV(imageI,imageR)); /* Image Resultat, telle que le format des "pixels" change : */ /* */ /* imageR(Int)=imageA(Float). */ /* */ DEFV(Argument,DEFV(imageF,imageA)); /* Image Argument. */ /*-----------------------------------------------------------------------------------------------------------------------------------*/ Bblock /*..............................................................................................................................*/ begin_image Bblock storeI_point(loadF_point(imageA,X,Y),imageR,X,Y); Eblock end_image RETII(imageR); Eblock EFonctionI _______________________________________________________________________________________________________________________________________ _______________________________________________________________________________________________________________________________________ /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* C O N V E R S I O N " D O U B L E " --> " S T A N D A R D " : */ /* */ /*************************************************************************************************************************************/ BFonctionP DEFV(Common,DEFV(FonctionP,POINTERp(Idouble_std(imageR,imageA,niveau_minimal,niveau_maximal)))) DEFV(Argument,DEFV(image,imageR)); /* Image Resultat, telle que le format des "pixels" change : */ /* */ /* imageR(std)=imageA(Double). */ /* */ DEFV(Argument,DEFV(imageD,imageA)); /* Image Argument. */ DEFV(Argument,DEFV(Double,niveau_minimal)); /* Donne le niveau minimal de l'image Argument (en general 'NOIR_double'). */ DEFV(Argument,DEFV(Double,niveau_maximal)); /* Donne le niveau maximal de l'image Argument (en general 'BLANC_double'). */ /*-----------------------------------------------------------------------------------------------------------------------------------*/ Bblock /*..............................................................................................................................*/ Test(IFEQ(niveau_minimal,niveau_maximal)) Bblock CALS(Inoir(imageR)); /* Lorsque les niveaux minimal et maximal sont egaux, on se fixe */ /* a priori au plancher ('NOIR')... */ Eblock ATes Bblock begin_image Bblock store_point(GENP(SCALE_POINT(NOIR,BLANC,loadD_point(imageA,X,Y),niveau_minimal,niveau_maximal)) ,imageR ,X,Y ,FVARIABLE ); /* Sinon, on interpole entre-eux deux. */ Eblock end_image Eblock ETes RETI(imageR); Eblock EFonctionP /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* C O N V E R S I O N " D O U B L E " --> " S T A N D A R D " A V E C R E N O R M A L I S A T I O N : */ /* */ /*************************************************************************************************************************************/ BFonctionP DEFV(Common,DEFV(FonctionP,POINTERp(Idouble_std_avec_renormalisation(imageR,imageA)))) DEFV(Argument,DEFV(image,imageR)); /* Image Resultat, telle que le format des "pixels" change : */ /* */ /* imageR(std)=imageA(Double) mais renormalisee afin d'utiliser pleinement [NOIR,BLANC]. */ /* */ DEFV(Argument,DEFV(imageD,imageA)); /* Image Argument. */ /*-----------------------------------------------------------------------------------------------------------------------------------*/ Bblock DEFV(Double,INIT(niveau_minimal,DPRE(UNDEF))); DEFV(Double,INIT(niveau_maximal,DPRE(UNDEF))); /* Afin de rechercher les niveaux minimal et maximal de 'imageA'. */ /*..............................................................................................................................*/ CALS(IDnivo_extrema(imageA ,ADRESSE(niveau_minimal) ,ADRESSE(niveau_maximal) ) ); /* Recherche des extrema de 'imageA'. */ CALS(Idouble_std(imageR ,imageA ,niveau_minimal ,niveau_maximal ) ); /* Generation de 'imageR' (avec renormalisation). */ RETI(imageR); Eblock EFonctionP _______________________________________________________________________________________________________________________________________ _______________________________________________________________________________________________________________________________________ /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* C O N V E R S I O N ' Int ' A L A P R E C I S I O N ' Float ' : */ /* */ /*************************************************************************************************************************************/ BFonctionV DEFV(Common,DEFV(FonctionV,POINTERF(Iconversion_Int_Float(imageR,imageA)))) /* Fonction introduite le 20170406094021. */ DEFV(Argument,DEFV(imageF,imageR)); DEFV(Argument,DEFV(imageI,imageA)); /*-----------------------------------------------------------------------------------------------------------------------------------*/ Bblock /*..............................................................................................................................*/ begin_image Bblock storeF_point(loadI_point(imageA,X,Y) ,imageR ,X,Y ); Eblock end_image RETU_VIDE Eblock EFonctionV _______________________________________________________________________________________________________________________________________ _______________________________________________________________________________________________________________________________________ /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* C O N V E R S I O N D E L A P R E C I S I O N ' Float ' */ /* A L A P R E C I S I O N ' Int ' : */ /* */ /*************************************************************************************************************************************/ BFonctionV DEFV(Common,DEFV(FonctionV,POINTERF(Fconversion_Float_Int(imageR,imageA)))) /* Fonction introduite le 20170406094021. */ DEFV(Argument,DEFV(imageI,imageR)); DEFV(Argument,DEFV(imageF,imageA)); /*-----------------------------------------------------------------------------------------------------------------------------------*/ Bblock /*..............................................................................................................................*/ begin_image Bblock storeI_point(loadF_point(imageA,X,Y) ,imageR ,X,Y ); Eblock end_image RETU_VIDE Eblock EFonctionV _______________________________________________________________________________________________________________________________________ _______________________________________________________________________________________________________________________________________ /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* C O N V E R S I O N D E L A V R A I E S I M P L E P R E C I S I O N */ /* A L A P R E C I S I O N ' Float ' : */ /* */ /*************************************************************************************************************************************/ BFonctionV DEFV(Common,DEFV(FonctionV,POINTERF(Fconversion_float_Float(imageR,imageA)))) /* Fonction introduite le 20170406094021. */ DEFV(Argument,DEFV(imageF,imageR)); DEFV(Argument,DEFV(image_vrai_float_de_base,imageA)); /*-----------------------------------------------------------------------------------------------------------------------------------*/ Bblock /*..............................................................................................................................*/ begin_image Bblock storeF_point(FLOT(loadQ_point_GENERAL(imageA,X,Y)) ,imageR ,X,Y ); Eblock end_image RETU_VIDE Eblock EFonctionV _______________________________________________________________________________________________________________________________________ _______________________________________________________________________________________________________________________________________ /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* C O N V E R S I O N D E L A P R E C I S I O N ' Float ' */ /* A L A V R A I E S I M P L E P R E C I S I O N : */ /* */ /*************************************************************************************************************************************/ BFonctionV DEFV(Common,DEFV(FonctionV,POINTERF(Fconversion_Float_float(imageR,imageA)))) /* Fonction introduite le 20170406094021. */ DEFV(Argument,DEFV(image_vrai_float_de_base,imageR)); DEFV(Argument,DEFV(imageF,imageA)); /*-----------------------------------------------------------------------------------------------------------------------------------*/ Bblock /*..............................................................................................................................*/ begin_image Bblock storeQV_point(vbFLOT(loadF_point(imageA,X,Y)) ,imageR ,X,Y ); Eblock end_image RETU_VIDE Eblock EFonctionV _______________________________________________________________________________________________________________________________________ _______________________________________________________________________________________________________________________________________ /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* C O N V E R S I O N " R E E L L E ( C O M P L E X E ) " --> " F L O A T " : */ /* */ /*************************************************************************************************************************************/ BFonctionF DEFV(Common,DEFV(FonctionF,POINTERF(Icomplexe_reelle(imageR,imageA)))) DEFV(Argument,DEFV(imageF,imageR)); /* Image Resultat, telle que le format des "pixels" change : */ /* */ /* imageR(Float)=Reelle(imageA(complexe)). */ /* */ DEFV(Argument,DEFV(imageJ,imageA)); /* Image Argument. */ /*-----------------------------------------------------------------------------------------------------------------------------------*/ Bblock /*..............................................................................................................................*/ begin_image Bblock storeF_point(loadRJ_point(imageA,X,Y),imageR,X,Y); Eblock end_image RETIF(imageR); Eblock EFonctionF _______________________________________________________________________________________________________________________________________ _______________________________________________________________________________________________________________________________________ /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* C O N V E R S I O N " I M A G I N A I R E ( C O M P L E X E ) " --> " F L O A T " : */ /* */ /*************************************************************************************************************************************/ BFonctionF DEFV(Common,DEFV(FonctionF,POINTERF(Icomplexe_imaginaire(imageR,imageA)))) DEFV(Argument,DEFV(imageF,imageR)); /* Image Resultat, telle que le format des "pixels" change : */ /* */ /* imageR(Float)=Imaginaire(imageA(complexe)). */ /* */ DEFV(Argument,DEFV(imageJ,imageA)); /* Image Argument. */ /*-----------------------------------------------------------------------------------------------------------------------------------*/ Bblock /*..............................................................................................................................*/ begin_image Bblock storeF_point(loadIJ_point(imageA,X,Y),imageR,X,Y); Eblock end_image RETIF(imageR); Eblock EFonctionF _______________________________________________________________________________________________________________________________________ _______________________________________________________________________________________________________________________________________ /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* C O N V E R S I O N " F L O A T " --> " R E E L L E ( C O M P L E X E ) " : */ /* */ /*************************************************************************************************************************************/ BFonctionJ DEFV(Common,DEFV(FonctionJ,POINTERJ(Ireelle_complexe(imageR,imageA)))) DEFV(Argument,DEFV(imageJ,imageR)); /* Image Resultat, telle que le format des "pixels" change : */ /* */ /* Reelle(imageR(complexe))=imageA(Float). */ /* */ DEFV(Argument,DEFV(imageF,imageA)); /* Image Argument. */ /*-----------------------------------------------------------------------------------------------------------------------------------*/ Bblock /*..............................................................................................................................*/ begin_image Bblock storeRJ_point(loadF_point(imageA,X,Y),imageR,X,Y); Eblock end_image RETIJ(imageR); Eblock EFonctionJ _______________________________________________________________________________________________________________________________________ _______________________________________________________________________________________________________________________________________ /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* C O N V E R S I O N " F L O A T " --> " I M A G I N A I R E ( C O M P L E X E ) " : */ /* */ /*************************************************************************************************************************************/ BFonctionJ DEFV(Common,DEFV(FonctionJ,POINTERJ(Iimaginaire_complexe(imageR,imageA)))) DEFV(Argument,DEFV(imageJ,imageR)); /* Image Resultat, telle que le format des "pixels" change : */ /* */ /* Imaginaire(imageR(complexe))=imageA(Float). */ /* */ DEFV(Argument,DEFV(imageF,imageA)); /* Image Argument. */ /*-----------------------------------------------------------------------------------------------------------------------------------*/ Bblock /*..............................................................................................................................*/ begin_image Bblock storeIJ_point(loadF_point(imageA,X,Y),imageR,X,Y); Eblock end_image RETIJ(imageR); Eblock EFonctionJ _______________________________________________________________________________________________________________________________________ _______________________________________________________________________________________________________________________________________ /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* C O N V E R S I O N " H R E E L L E ( H Y P E R - C O M P L E X E ) " --> " F L O A T " : */ /* */ /*************************************************************************************************************************************/ BFonctionF DEFV(Common,DEFV(FonctionF,POINTERF(Ihyper_complexe_reelle(imageR,imageA)))) DEFV(Argument,DEFV(imageF,imageR)); /* Image Resultat, telle que le format des "pixels" change : */ /* */ /* imageR(Float)=HReelle(imageA(hyper-complexe)). */ /* */ DEFV(Argument,DEFV(imageHJ,imageA)); /* Image Argument. */ /*-----------------------------------------------------------------------------------------------------------------------------------*/ Bblock /*..............................................................................................................................*/ begin_image Bblock storeF_point(loadRHJ_point(imageA,X,Y),imageR,X,Y); Eblock end_image RETIF(imageR); Eblock EFonctionF _______________________________________________________________________________________________________________________________________ _______________________________________________________________________________________________________________________________________ /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* C O N V E R S I O N " H I M A G I N A I R E ( H Y P E R - C O M P L E X E ) " --> " F L O A T " : */ /* */ /*************************************************************************************************************************************/ BFonctionF DEFV(Common,DEFV(FonctionF,POINTERF(Ihyper_complexe_imaginaire(imageR,imageA)))) DEFV(Argument,DEFV(imageF,imageR)); /* Image Resultat, telle que le format des "pixels" change : */ /* */ /* imageR(Float)=HImaginaire(imageA(hyper-complexe)). */ /* */ DEFV(Argument,DEFV(imageHJ,imageA)); /* Image Argument. */ /*-----------------------------------------------------------------------------------------------------------------------------------*/ Bblock /*..............................................................................................................................*/ begin_image Bblock storeF_point(loadIHJ_point(imageA,X,Y),imageR,X,Y); Eblock end_image RETIF(imageR); Eblock EFonctionF _______________________________________________________________________________________________________________________________________ _______________________________________________________________________________________________________________________________________ /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* C O N V E R S I O N " H J M A G I N A I R E ( H Y P E R - C O M P L E X E ) " --> " F L O A T " : */ /* */ /*************************************************************************************************************************************/ BFonctionF DEFV(Common,DEFV(FonctionF,POINTERF(Ihyper_complexe_jmaginaire(imageR,imageA)))) DEFV(Argument,DEFV(imageF,imageR)); /* Image Resultat, telle que le format des "pixels" change : */ /* */ /* imageR(Float)=HJmaginaire(imageA(hyper-complexe)). */ /* */ DEFV(Argument,DEFV(imageHJ,imageA)); /* Image Argument. */ /*-----------------------------------------------------------------------------------------------------------------------------------*/ Bblock /*..............................................................................................................................*/ begin_image Bblock storeF_point(loadJHJ_point(imageA,X,Y),imageR,X,Y); Eblock end_image RETIF(imageR); Eblock EFonctionF _______________________________________________________________________________________________________________________________________ _______________________________________________________________________________________________________________________________________ /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* C O N V E R S I O N " H K M A G I N A I R E ( H Y P E R - C O M P L E X E ) " --> " F L O A T " : */ /* */ /*************************************************************************************************************************************/ BFonctionF DEFV(Common,DEFV(FonctionF,POINTERF(Ihyper_complexe_kmaginaire(imageR,imageA)))) DEFV(Argument,DEFV(imageF,imageR)); /* Image Resultat, telle que le format des "pixels" change : */ /* */ /* imageR(Float)=HKmaginaire(imageA(hyper-complexe)). */ /* */ DEFV(Argument,DEFV(imageHJ,imageA)); /* Image Argument. */ /*-----------------------------------------------------------------------------------------------------------------------------------*/ Bblock /*..............................................................................................................................*/ begin_image Bblock storeF_point(loadKHJ_point(imageA,X,Y),imageR,X,Y); Eblock end_image RETIF(imageR); Eblock EFonctionF _______________________________________________________________________________________________________________________________________ _______________________________________________________________________________________________________________________________________ /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* C O N V E R S I O N " F L O A T " --> " H R E E L L E ( H Y P E R - C O M P L E X E ) " : */ /* */ /*************************************************************************************************************************************/ BFonctionHJ DEFV(Common,DEFV(FonctionHJ,POINTERHJ(Ireelle_hyper_complexe(imageR,imageA)))) DEFV(Argument,DEFV(imageHJ,imageR)); /* Image Resultat, telle que le format des "pixels" change : */ /* */ /* HReelle(imageR(hyper-complexe))=imageA(Float). */ /* */ DEFV(Argument,DEFV(imageF,imageA)); /* Image Argument. */ /*-----------------------------------------------------------------------------------------------------------------------------------*/ Bblock /*..............................................................................................................................*/ begin_image Bblock storeRHJ_point(loadF_point(imageA,X,Y),imageR,X,Y); Eblock end_image RETIHJ(imageR); Eblock EFonctionHJ _______________________________________________________________________________________________________________________________________ _______________________________________________________________________________________________________________________________________ /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* C O N V E R S I O N " F L O A T " --> " H I M A G I N A I R E ( H Y P E R - C O M P L E X E ) " : */ /* */ /*************************************************************************************************************************************/ BFonctionHJ DEFV(Common,DEFV(FonctionHJ,POINTERHJ(Iimaginaire_hyper_complexe(imageR,imageA)))) DEFV(Argument,DEFV(imageHJ,imageR)); /* Image Resultat, telle que le format des "pixels" change : */ /* */ /* HImaginaire(imageR(hyper-complexe))=imageA(Float). */ /* */ DEFV(Argument,DEFV(imageF,imageA)); /* Image Argument. */ /*-----------------------------------------------------------------------------------------------------------------------------------*/ Bblock /*..............................................................................................................................*/ begin_image Bblock storeIHJ_point(loadF_point(imageA,X,Y),imageR,X,Y); Eblock end_image RETIHJ(imageR); Eblock EFonctionHJ _______________________________________________________________________________________________________________________________________ _______________________________________________________________________________________________________________________________________ /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* C O N V E R S I O N " F L O A T " --> " H J M A G I N A I R E ( H Y P E R - C O M P L E X E ) " : */ /* */ /*************************************************************************************************************************************/ BFonctionHJ DEFV(Common,DEFV(FonctionHJ,POINTERHJ(Ijmaginaire_hyper_complexe(imageR,imageA)))) DEFV(Argument,DEFV(imageHJ,imageR)); /* Image Resultat, telle que le format des "pixels" change : */ /* */ /* HJmaginaire(imageR(hyper-complexe))=imageA(Float). */ /* */ DEFV(Argument,DEFV(imageF,imageA)); /* Image Argument. */ /*-----------------------------------------------------------------------------------------------------------------------------------*/ Bblock /*..............................................................................................................................*/ begin_image Bblock storeJHJ_point(loadF_point(imageA,X,Y),imageR,X,Y); Eblock end_image RETIHJ(imageR); Eblock EFonctionHJ _______________________________________________________________________________________________________________________________________ _______________________________________________________________________________________________________________________________________ /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* C O N V E R S I O N " F L O A T " --> " H K M A G I N A I R E ( H Y P E R - C O M P L E X E ) " : */ /* */ /*************************************************************************************************************************************/ BFonctionHJ DEFV(Common,DEFV(FonctionHJ,POINTERHJ(Ikmaginaire_hyper_complexe(imageR,imageA)))) DEFV(Argument,DEFV(imageHJ,imageR)); /* Image Resultat, telle que le format des "pixels" change : */ /* */ /* HKmaginaire(imageR(hyper-complexe))=imageA(Float). */ /* */ DEFV(Argument,DEFV(imageF,imageA)); /* Image Argument. */ /*-----------------------------------------------------------------------------------------------------------------------------------*/ Bblock /*..............................................................................................................................*/ begin_image Bblock storeKHJ_point(loadF_point(imageA,X,Y),imageR,X,Y); Eblock end_image RETIHJ(imageR); Eblock EFonctionHJ _______________________________________________________________________________________________________________________________________ _______________________________________________________________________________________________________________________________________ /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* C O N V E R S I O N " F L O A T " --> " S T A N D A R D " D ' U N A L B U M : */ /* */ /*************************************************************************************************************************************/ BFonctionP DEFV(Common,DEFV(Logical,SINT(Afloat_std_____editer_le_message_d_attention_relatif_aux_extrema,VRAI))); /* Cette option a ete introduite le 20101109160703 par "symetrie" avec */ /* 'Ifloat_std_____editer_le_message_d_attention_relatif_aux_extrema'... */ DEFV(Common,DEFV(Float,SINT(Afloat_std_____epsilon_de_seuillage_inferieur_par_rapport_au_niveau_minimal,D_EPSILON))); /* En augmentant ce seuil, il est possible d'eliminer des "underflows" de conversion... */ DEFV(Common,DEFV(FonctionP,POINTERp(Afloat_std(albumR,albumA,niveau_minimal,niveau_maximal)))) DEFV(Argument,DEFV(album,albumR)); /* Album Resultat, telle que le format des "pixels" change : */ /* */ /* albumR(std)=albumA(Float). */ /* */ DEFV(Argument,DEFV(albumF,albumA)); /* Album Argument. */ DEFV(Argument,DEFV(genere_Float,niveau_minimal)); /* Donne le niveau minimal de l'album Argument (en general 'FLOT__NOIR'). */ DEFV(Argument,DEFV(genere_Float,niveau_maximal)); /* Donne le niveau maximal de l'album Argument (en general 'FLOT__BLANC'). */ /*-----------------------------------------------------------------------------------------------------------------------------------*/ Bblock /*..............................................................................................................................*/ Test(IFOU(IFGE(niveau_minimal,niveau_maximal) ,IFLE(niveau_maximal ,ADD2(niveau_minimal,Afloat_std_____epsilon_de_seuillage_inferieur_par_rapport_au_niveau_minimal) ) ) ) Bblock Test(IL_FAUT(Afloat_std_____editer_le_message_d_attention_relatif_aux_extrema)) /* Test introduit le 20101109160703... */ Bblock PRINT_ATTENTION("les niveaux 'minimal' et 'maximal' sont egaux ou dans l'ordre inverse, on force le niveau 'NOIR'"); CAL1(Prer1("ils valent tous les deux : %g\n",CHOI(niveau_minimal,niveau_maximal))); Eblock ATes Bblock Eblock ETes CALS(dAnoir(albumR)); /* Lorsque les niveaux minimal et maximal sont egaux, on se fixe */ /* a priori au plancher ('NOIR')... */ Eblock ATes Bblock begin_album Bblock DEFV(genere_Float,INIT(niveau_courant,AloadF_point(albumA,X,Y,Z))); /* Niveau du point courant {X,Y,Z}. */ Test(IFLE(niveau_courant ,ADD2(niveau_minimal,Afloat_std_____epsilon_de_seuillage_inferieur_par_rapport_au_niveau_minimal) ) ) Bblock EGAL(niveau_courant,niveau_minimal); /* Pour eviter des "underflows" dans 'SCALE_POINT(...)' lorsque sera calculee la */ /* quantite 'niveau_courant-niveau_minimal' ci-apres. */ Eblock ATes Bblock Eblock ETes Astore_point(GENP(FLIN(SCALE_POINT(NOIR,BLANC,niveau_courant,niveau_minimal,niveau_maximal) ,Afloat_std_____translation_d_arrondi_au_plus_proche_entier ) ) ,albumR ,X,Y,Z ); /* Sinon, on interpole entre-eux deux ; on notera qu'autrefois, on faisait un */ /* 'ARRI(SCALE_POINT(...))', mais qu'il fut supprime a cause de sorties de l'intervalle */ /* [NOIR,BLANC] que cela pouvait creer dans des operations ulterieures. Le 20020315122536, */ /* j'ai remarque qu'en fait il fallait le reintroduire (mais afin d'assurer la compatibilite */ /* avec les generations anterieures, c'est en fait 'FLIN(...)', associee a un parametre que */ /* l'on peut annuler, qui est utilisee). En effet, les tests ont montre que : */ /* */ /* 0.50196078431373*255 = 128 */ /* */ /* et : */ /* */ /* 0.50196078431372*255 = 127 */ /* */ /* alors que l'on attend en fait : */ /* */ /* 0.50000000000000*255 = 128 */ /* */ /* et : */ /* */ /* 0.49999999999999*255 = 127 */ /* */ /* d'ou cette solution... */ Eblock end_album Eblock ETes RETA(albumR); Eblock EFonctionP _______________________________________________________________________________________________________________________________________ _______________________________________________________________________________________________________________________________________ /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* C O N V E R S I O N " RVB " --> " HLS " D ' U N E I M A G E " S T A N D A R D " : */ /* */ /*************************************************************************************************************************************/ BFonctionI /* ATTENTION : c'est bien 'FonctionI' (et non pas 'FonctionP') a cause du 'RETU_ERROR'... */ DEFV(Common,DEFV(FonctionI,Iconversion_RVB_en_HLS(imageR_Hue,imageR_Luminance,imageR_Saturation ,imageA_ROUGE,imageA_VERTE,imageA_BLEUE ) ) ) DEFV(Argument,DEFV(image,imageR_Hue)); DEFV(Argument,DEFV(image,imageR_Luminance)); DEFV(Argument,DEFV(image,imageR_Saturation)); /* Images Resultat {Hue,Luminance,Saturation}. */ DEFV(Argument,DEFV(image,imageA_ROUGE)); DEFV(Argument,DEFV(image,imageA_VERTE)); DEFV(Argument,DEFV(image,imageA_BLEUE)); /* Images Argument {ROUGE,VERTE,BLEUE}. */ /*-----------------------------------------------------------------------------------------------------------------------------------*/ Bblock INIT_ERROR; /*..............................................................................................................................*/ begin_image Bblock DEFV(Float,INIT(Hue_du_point_courant,FLOT__UNDEF)); /* Donne la teinte du point {X,Y} courant, */ DEFV(Float,INIT(Luminance_du_point_courant,FLOT__UNDEF)); /* Donne la luminance du point {X,Y} courant, */ DEFV(Float,INIT(Saturation_du_point_courant,FLOT__UNDEF)); /* Donne la saturation du point {X,Y} courant. */ PASSAGE_RVB_HLS(Hue_du_point_courant ,Luminance_du_point_courant ,Saturation_du_point_courant ,load_point(imageA_ROUGE,X,Y) ,load_point(imageA_VERTE,X,Y) ,load_point(imageA_BLEUE,X,Y) ); /* Passage de l'espace 'RVB' a l'espace 'HLS' pour le point {X,Y} courant. */ store_point(GENP(Hue_du_point_courant) ,imageR_Hue ,X,Y ,FVARIABLE ); store_point(GENP(Luminance_du_point_courant) ,imageR_Luminance ,X,Y ,FVARIABLE ); store_point(GENP(Saturation_du_point_courant) ,imageR_Saturation ,X,Y ,FVARIABLE ); /* Et enfin, generation des trois images Resultat. */ Eblock end_image RETU_ERROR; Eblock EFonctionI /* ATTENTION : c'est bien 'FonctionI' (et non pas 'FonctionP') a cause du 'RETU_ERROR'... */ _______________________________________________________________________________________________________________________________________ _______________________________________________________________________________________________________________________________________ /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* C O N V E R S I O N " RVB " --> " HLS " D ' U N E I M A G E " F L O A T " : */ /* */ /*************************************************************************************************************************************/ BFonctionI /* ATTENTION : c'est bien 'FonctionI' (et non pas 'FonctionF') a cause du 'RETU_ERROR'... */ DEFV(Common,DEFV(FonctionI,IFconversion_RVB_en_HLS(imageR_Hue,imageR_Luminance,imageR_Saturation ,imageA_ROUGE,imageA_VERTE,imageA_BLEUE ) ) ) /* Fonction introduite le 20111206092618... */ DEFV(Argument,DEFV(imageF,imageR_Hue)); DEFV(Argument,DEFV(imageF,imageR_Luminance)); DEFV(Argument,DEFV(imageF,imageR_Saturation)); /* Images Resultat {Hue,Luminance,Saturation}. */ DEFV(Argument,DEFV(imageF,imageA_ROUGE)); DEFV(Argument,DEFV(imageF,imageA_VERTE)); DEFV(Argument,DEFV(imageF,imageA_BLEUE)); /* Images Argument {ROUGE,VERTE,BLEUE}. */ /*-----------------------------------------------------------------------------------------------------------------------------------*/ Bblock INIT_ERROR; /*..............................................................................................................................*/ begin_image Bblock DEFV(Float,INIT(Hue_du_point_courant,FLOT__UNDEF)); /* Donne la teinte du point {X,Y} courant, */ DEFV(Float,INIT(Luminance_du_point_courant,FLOT__UNDEF)); /* Donne la luminance du point {X,Y} courant, */ DEFV(Float,INIT(Saturation_du_point_courant,FLOT__UNDEF)); /* Donne la saturation du point {X,Y} courant. */ PASSAGE_RVB_HLS(Hue_du_point_courant ,Luminance_du_point_courant ,Saturation_du_point_courant ,loadF_point(imageA_ROUGE,X,Y) ,loadF_point(imageA_VERTE,X,Y) ,loadF_point(imageA_BLEUE,X,Y) ); /* Passage de l'espace 'RVB' a l'espace 'HLS' pour le point {X,Y} courant. */ storeF_point(Hue_du_point_courant ,imageR_Hue ,X,Y ); storeF_point(Luminance_du_point_courant ,imageR_Luminance ,X,Y ); storeF_point(Saturation_du_point_courant ,imageR_Saturation ,X,Y ); /* Et enfin, generation des trois images Resultat. */ Eblock end_image RETU_ERROR; Eblock EFonctionI /* ATTENTION : c'est bien 'FonctionI' (et non pas 'FonctionF') a cause du 'RETU_ERROR'... */ _______________________________________________________________________________________________________________________________________ _______________________________________________________________________________________________________________________________________ /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* C O N V E R S I O N " HLS " --> " RVB " D ' U N E I M A G E " S T A N D A R D " : */ /* */ /*************************************************************************************************************************************/ BFonctionI DEFV(Common,DEFV(FonctionI,Iconversion_HLS_en_RVB(imageR_ROUGE,imageR_VERTE,imageR_BLEUE ,imageA_Hue,imageA_Luminance,imageA_Saturation ) ) ) DEFV(Argument,DEFV(image,imageR_ROUGE)); DEFV(Argument,DEFV(image,imageR_VERTE)); DEFV(Argument,DEFV(image,imageR_BLEUE)); /* Images Resultat {ROUGE,VERTE,BLEUE}. */ DEFV(Argument,DEFV(image,imageA_Hue)); DEFV(Argument,DEFV(image,imageA_Luminance)); DEFV(Argument,DEFV(image,imageA_Saturation)); /* Images Argument {Hue,Luminance,Saturation}. */ /*-----------------------------------------------------------------------------------------------------------------------------------*/ Bblock INIT_ERROR; /*..............................................................................................................................*/ begin_image Bblock DEFV(genere_p,INIT(niveau_ROUGE,NIVEAU_UNDEF)); /* NR = niveau du point courant imageA_ROUGE(X,Y), */ DEFV(genere_p,INIT(niveau_VERTE,NIVEAU_UNDEF)); /* NV = niveau du point courant imageA_VERTE(X,Y), */ DEFV(genere_p,INIT(niveau_BLEUE,NIVEAU_UNDEF)); /* NB = niveau du point courant imageA_BLEUE(X,Y). */ PASSAGE_HLS_RVB(niveau_ROUGE ,niveau_VERTE ,niveau_BLEUE ,load_point(imageA_Hue,X,Y) ,load_point(imageA_Luminance,X,Y) ,load_point(imageA_Saturation,X,Y) ); /* Passage de l'espace 'HLS' a l'espace 'RVB' pour le point {X,Y} courant. */ store_point(niveau_ROUGE ,imageR_ROUGE ,X,Y ,FVARIABLE ); store_point(niveau_VERTE ,imageR_VERTE ,X,Y ,FVARIABLE ); store_point(niveau_BLEUE ,imageR_BLEUE ,X,Y ,FVARIABLE ); /* Et enfin, generation des trois images Resultat. */ Eblock end_image RETU_ERROR; Eblock EFonctionI _______________________________________________________________________________________________________________________________________ _______________________________________________________________________________________________________________________________________ /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* C O N V E R S I O N " HLS " --> " RVB " D ' U N E I M A G E " F L O A T " : */ /* */ /*************************************************************************************************************************************/ BFonctionI /* ATTENTION : c'est bien 'FonctionI' (et non pas 'FonctionF') a cause du 'RETU_ERROR'... */ DEFV(Common,DEFV(FonctionI,IFconversion_HLS_en_RVB(imageR_ROUGE,imageR_VERTE,imageR_BLEUE ,imageA_Hue,imageA_Luminance,imageA_Saturation ) ) ) /* Fonction introduite le 20111206092618... */ DEFV(Argument,DEFV(imageF,imageR_ROUGE)); DEFV(Argument,DEFV(imageF,imageR_VERTE)); DEFV(Argument,DEFV(imageF,imageR_BLEUE)); /* Images Resultat {ROUGE,VERTE,BLEUE}. */ DEFV(Argument,DEFV(imageF,imageA_Hue)); DEFV(Argument,DEFV(imageF,imageA_Luminance)); DEFV(Argument,DEFV(imageF,imageA_Saturation)); /* Images Argument {Hue,Luminance,Saturation}. */ /*-----------------------------------------------------------------------------------------------------------------------------------*/ Bblock INIT_ERROR; /*..............................................................................................................................*/ begin_image Bblock DEFV(genere_Float,INIT(niveau_ROUGE,FLOT__NIVEAU_UNDEF)); /* NR = niveau du point courant imageA_ROUGE(X,Y), */ DEFV(genere_Float,INIT(niveau_VERTE,FLOT__NIVEAU_UNDEF)); /* NV = niveau du point courant imageA_VERTE(X,Y), */ DEFV(genere_Float,INIT(niveau_BLEUE,FLOT__NIVEAU_UNDEF)); /* NB = niveau du point courant imageA_BLEUE(X,Y). */ PASSAGE_HLS_RVB(niveau_ROUGE ,niveau_VERTE ,niveau_BLEUE ,loadF_point(imageA_Hue,X,Y) ,loadF_point(imageA_Luminance,X,Y) ,loadF_point(imageA_Saturation,X,Y) ); /* Passage de l'espace 'HLS' a l'espace 'RVB' pour le point {X,Y} courant. */ storeF_point(niveau_ROUGE ,imageR_ROUGE ,X,Y ); storeF_point(niveau_VERTE ,imageR_VERTE ,X,Y ); storeF_point(niveau_BLEUE ,imageR_BLEUE ,X,Y ); /* Et enfin, generation des trois images Resultat. */ Eblock end_image RETU_ERROR; Eblock EFonctionI /* ATTENTION : c'est bien 'FonctionI' (et non pas 'FonctionF') a cause du 'RETU_ERROR'... */ _______________________________________________________________________________________________________________________________________