IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Lazarus Pascal Discussion :

Conversion d'un code C de Lightmap : noir et blanc au lieu de nuances de gris


Sujet :

Lazarus Pascal

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre chevronné Avatar de der§en
    Homme Profil pro
    Bretagne
    Inscrit en
    Septembre 2005
    Messages
    1 060
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Bretagne
    Secteur : Industrie

    Informations forums :
    Inscription : Septembre 2005
    Messages : 1 060
    Par défaut Conversion d'un code C de Lightmap : noir et blanc au lieu de nuances de gris
    Bonjour,

    Je suis en train de convertir un code en C++ sous GTK, qui produit une lightmap depuis une heightmap.

    Mais hélas, je n'obtiens pas le même résultat visuel sous Lazarus que sous le projet originel.

    Voilà ce que je devrais obtenir :

    Nom : Lightmap-cpp.jpeg
Affichages : 588
Taille : 33,4 Ko

    Et ce que j'ai sous Lazarus :

    Nom : lightmap.jpg
Affichages : 583
Taille : 65,6 Ko

    Chez moi, ma lightmap, est blanche et noire, il n'y a pas de niveaux de gris comme dans l'original.

    Voici la routine originelle :
    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
     
    void on_apercu(GtkWidget* widget, gpointer data)
    {
        int ombrage = (int)gtk_adjustment_get_value(adj_ombrage);
        float angle_rayons = (int)gtk_adjustment_get_value(adj_angle_rayons);
        float hauteur_max_rayons = (int)gtk_adjustment_get_value(adj_hauteur_max_rayons);
        float hauteur_max_heightmap = (float)gtk_adjustment_get_value(adj_hauteur_max_heightmap);
     
        int n_channels;
        int rowstride_lightmap, rowstride_heightmap;
        guchar *pixels_lightmap=NULL, *p_lightmap=NULL;
        guchar *pixels_heightmap=NULL, *p_heightmap=NULL;
        int x, y, width, height = 0;
        float step_z=0.0f;
        float z_origine=0.0f;
        int x_rayon=0;
        float z_rayon=0.0f;
     
        n_channels = gdk_pixbuf_get_n_channels(pixbuf_lightmap);
     
        g_assert(gdk_pixbuf_get_colorspace (pixbuf_lightmap) == GDK_COLORSPACE_RGB);
        g_assert(gdk_pixbuf_get_bits_per_sample (pixbuf_lightmap) == 8);
        g_assert(gdk_pixbuf_get_has_alpha (pixbuf_lightmap) == FALSE);
        g_assert(n_channels == 3);
     
        width = gdk_pixbuf_get_width(pixbuf_lightmap);
        height = gdk_pixbuf_get_height(pixbuf_lightmap);
     
        rowstride_lightmap = gdk_pixbuf_get_rowstride(pixbuf_lightmap);
        pixels_lightmap = gdk_pixbuf_get_pixels(pixbuf_lightmap);
     
        rowstride_heightmap = gdk_pixbuf_get_rowstride(pixbuf_heightmap);
        pixels_heightmap = gdk_pixbuf_get_pixels(pixbuf_heightmap);
     
        // Au départ, tout est dans l'ombre...
        for(y=0 ; y<height ; y++)
            for(x=0 ; x<width ; x++)
            {
                p_lightmap = pixels_lightmap + y * rowstride_lightmap + x * n_channels;
                p_lightmap[0] = ombrage;
                p_lightmap[1] = ombrage;
                p_lightmap[2] = ombrage;
            }
     
        // Puis vint la lumière !!
     
        // On calcule de combien on doit incrémenter en z à chaque nouveau rayon
        step_z = fabs(1/tan(angle_rayons));
     
        // On lance les rayons dans le sens horizontal (en voyant de haut), de la gauche vers la droite.
        // On fait donc ça pour toutes les lignes (d'où la boucle en y).
        for(y=0 ; y<height ; y++)
        {
            // On parcourt en montant (i.e. suivant l'axe des Z) pour lancer des rayons à chacune
            // de ces hauteurs
            for(z_origine=0.0f ; z_origine<hauteur_max_rayons ; z_origine+=step_z)
            {
                // Lancer du rayon !
                for(z_rayon=z_origine, x_rayon=0 ;
                    x_rayon < width;
                    z_rayon-=step_z, x_rayon++)
                {
                    // Si la hauteur du pixel en cours est supérieure ou égale à z_rayon,
                    // c'est qu'on a touché
                    // qqch, alors on le colorie en blanc et on passe au rayon d'après
     
                    // On pointe sur le point (x_rayon, y)
                    p_heightmap = pixels_heightmap + y * rowstride_heightmap + x_rayon * n_channels;
                    p_lightmap = pixels_lightmap + y * rowstride_lightmap + x_rayon * n_channels;
     
                    if((float)(p_heightmap[0]/255.0f)*hauteur_max_heightmap >= z_rayon)
                    {
                        p_lightmap[0] = p_lightmap[1] = p_lightmap[2] = 255;
                        break;
                    }
                }
            }
        }
     
        gtk_image_set_from_pixbuf(GTK_IMAGE(image_lightmap), pixbuf_lightmap);
        redimensionner_image(image_lightmap);
    }

    Et ma conversion en Pascal :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
     
    Procedure TForm1.bouton_apercuClick(Sender: TObject);
    var
       x, y, x_rayon: integer;
       z_step, z_origine, z_rayon: single;
       Pixel, Final: PRGBTriple;
    Begin
        // Calcul du pas en z pour chaque rayon.
        z_step := abs(1 / tan(spin_angle_rayons.Value));
     
        image_lightmap.Picture.Bitmap.BeginUpdate;
     
        // Lancement des rayons dans le sens horizontal et de gauche a droite.
        for y := 0 to image_lightmap.Picture.Bitmap.Height - 1 do
        begin
             // Pointeurs sur les 2 même lignes des 2 bitmaps.
             Final := PRGBTriple(image_heightmap.Picture.Bitmap.RawImage.GetLineStart(y));
             Pixel := PRGBTriple(image_lightmap.Picture.Bitmap.RawImage.GetLineStart(y));
     
             // Par defaut tout a la valeur de l'ombre défini dans l'UI.
             for x := 0 to image_lightmap.Picture.Bitmap.Width - 1 do
             begin
                  Pixel[x].rgbtRed   := spin_ombrage.Value;
                  Pixel[x].rgbtGreen := spin_ombrage.Value;
                  Pixel[x].rgbtBlue  := spin_ombrage.Value;
             End;
     
             // Lancements des rayons pour chaque hauteur en remontant suivant l'axe z
             z_origine := 0.0;
     
             while z_origine < spin_hauteur_max_rayons.Value do
             begin
                  // Lancement de rayon.
                  z_rayon := z_origine;
     
                  for x_rayon := 0 to image_lightmap.Picture.Bitmap.Width - 1 do
                  begin
                       // Si la hauteur (rouge pour l'exmple) du pixel est supérieur ou égale a la valeur
                       // du z_rayon alors on le colorie en blanc et on passe au rayoin lancé suivant.
                       if ((Final[x_rayon].rgbtRed / 255) * spin_hauteur_max_heightmap.Value) >= z_rayon then
                       begin
                            Pixel[x_rayon].rgbtRed   := 255;
                            Pixel[x_rayon].rgbtGreen := 255;
                            Pixel[x_rayon].rgbtBlue  := 255;
     
                            break;
                       End;
     
                       z_rayon := z_rayon - z_step;
                  end;
     
                  z_origine := z_origine + z_step;
             end;
        end;
     
        image_lightmap.Picture.Bitmap.EndUpdate;
    end;
    À votre avis, où ai-je loupé un truc ?

  2. #2
    Membre Expert

    Homme Profil pro
    Directeur de projet
    Inscrit en
    Mai 2013
    Messages
    1 631
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Directeur de projet
    Secteur : Service public

    Informations forums :
    Inscription : Mai 2013
    Messages : 1 631
    Par défaut All inclusive ?
    Bonjour,

    Quand on regarde les deux codes, il est difficile de voir une différence : les deux affectent soit un gris (ombrage) soit un blanc. Il ne devrait donc pas y avoir de nuances autres.

    Mais le code d'origine a une fonction "redimensionner_image(image_lightmap);" qui présuppose un filtre d'interpolation. Si celui-ci est plus pondéré que celui du redimensionnement appelé dans le code Lazarus (apparemment de type plus proche voisin) il va créer un flou qui va faire apparaître des niveaux de gris qui ne proviennent pas directement du traitement initial.

    La solution est d'appliquer explicitement un filtre d'interpolation au redimensionnement et de ne pas laisser, par exemple, la fonction stretch de décider de la méthode d'interpolation.

    Bon courage.

  3. #3
    Expert confirmé
    Avatar de anapurna
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2002
    Messages
    3 489
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Mai 2002
    Messages : 3 489
    Par défaut
    Salut

    il faut que tu regardes si l'image est bien en triplet RGB.
    Vérifie si l'image est pf24bit ou pf32bit, le résultat ne sera forcement pas le même.

  4. #4
    Membre chevronné Avatar de der§en
    Homme Profil pro
    Bretagne
    Inscrit en
    Septembre 2005
    Messages
    1 060
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Bretagne
    Secteur : Industrie

    Informations forums :
    Inscription : Septembre 2005
    Messages : 1 060
    Par défaut
    J’ai créé explicitement mes bitmaps en 24bits, et l’auteur du code originel aussi.

    Merci de vos retours...

    Petite question annexe: à votre avis normalement une lightmap doit être seulement noire et blanche ou en nuance de gris ?

  5. #5
    Membre Expert

    Homme Profil pro
    Directeur de projet
    Inscrit en
    Mai 2013
    Messages
    1 631
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Directeur de projet
    Secteur : Service public

    Informations forums :
    Inscription : Mai 2013
    Messages : 1 631
    Par défaut Niveaux
    Bonjour,

    En toute rigueur, la réflexion devrait dépendre de l'angle d'incidence et ne pas être systématiquement blanche. Ils ont triché en appliquant un filtre au redimensionnement pour avoir une solution plus performante (en temps sinon en qualité).

    Passer en 32 bits est une bonne solution pour accélérer le traitement (alignement d'adresse et possibilité d'écrire PInteger(p)^ := $00FFFFFF au lieu de 3 affectations de 255). En revanche je ne crois pas que cela change le fait que le code n'affecte que deux couleurs (un gris caractérisant la lumière diffuse et un blanc en cas de réflexion).

    Pour se rapprocher de ce qu'ils ont fait, on peut trouver sur Developpez.com le message de Jurassic Pork du 13/04/2016 à 05h14 qui répond à "Redimensionnement d'une image et perte de qualité" en montrant comment utiliser les filtres de redimensionnement.

    Bonne chance.

  6. #6
    Membre Expert
    Avatar de BeanzMaster
    Homme Profil pro
    Amateur Passionné
    Inscrit en
    Septembre 2015
    Messages
    1 899
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Amateur Passionné
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Septembre 2015
    Messages : 1 899
    Billets dans le blog
    2
    Par défaut
    Salut Guesset a raison la génération renvois que 2 couleurs Blanc ou Gris. Et effectivement ce dégradé est dût au redimensionnement.
    Peux tu nous faire un petit zip du projet ?. Je n'ai pas beaucoup de temps libre en ce moment, mais je pourrais jeter un oeil entre deux.

    A+
    Jérôme
    • "L'Homme devrait mettre autant d'ardeur à simplifier sa vie qu'il met à la compliquer" - Henri Bergson
    • "Bien des livres auraient été plus clairs s'ils n'avaient pas voulu être si clairs" - Emmanuel Kant
    • "La simplicité est la sophistication suprême" - Léonard De Vinci
    • "Ce qui est facile à comprendre ou à faire pour toi, ne l'est pas forcément pour l'autre." - Mon pèrei

    Mes projets sur Github - Blog - Site DVP

Discussions similaires

  1. [AC-2016] Impression Noir et blanc au lieu de couleurs pour certains Formulaires
    Par Philippe Tulliez dans le forum IHM
    Réponses: 0
    Dernier message: 29/08/2019, 14h06
  2. Code pour imprimer en noir et blanc
    Par ami19 dans le forum VBA Access
    Réponses: 1
    Dernier message: 17/10/2018, 08h16
  3. Conversion d'un code javascript en php
    Par jazz3210 dans le forum EDI, CMS, Outils, Scripts et API
    Réponses: 2
    Dernier message: 07/02/2009, 20h48
  4. Conversion d"un code javascript en php
    Par jazz3210 dans le forum Général JavaScript
    Réponses: 0
    Dernier message: 07/02/2009, 20h05
  5. Problème de conversion d'un code de AS2 en AS3
    Par platondog dans le forum ActionScript 3
    Réponses: 4
    Dernier message: 20/11/2008, 01h30

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo