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

Qt Discussion :

Poids d'icône : fichier BMP ou QPixmap ?


Sujet :

Qt

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    199
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Mars 2004
    Messages : 199
    Points : 103
    Points
    103
    Par défaut Poids d'icône : fichier BMP ou QPixmap ?
    Bonjour à tous

    Dans mon application j'ai à afficher #255000 points représentés par une icone.

    Dans un cas, je prends un fichier .bmp de 32x32 pixels et j'ai une charge en mémoire de 162 Mo pour tous ces points.

    Dans un second cas, je crée l’icône à partir d'un QPixmap, d'une taille de 38x38 pixels, car j'y rajoute un texte de 1 à 5 caractères. La mémoire est alors saturée pour finir par une erreur d'allocation tellement ça déborde de partout.

    Voici le code de création de l'icône :
    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
     
    QPixmap GenIcone::wayPoint(QString code)
    {
        QPixmap *pm = new QPixmap(38,38);
        pm->fill(Qt::transparent);
        QPainter *pmp = new QPainter(pm);
        pmp->setRenderHint(QPainter::Antialiasing);
        pmp->setBrush(Qt::cyan);
        pmp->setPen(Qt::black);
        static const QPoint triangle[3] = {
            QPoint(15,0),
            QPoint(3, 20),
            QPoint(27,20)
        };
        pmp->drawPolygon(triangle, 3);
        pmp->setFont(QFont("ArialBold",12));
        pmp->drawText(1,32,code);
        pmp->end();
     
        return *pm;
     
    }
    elle est appelée par ce code :

    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
     
        //Parser du fichier Waypoints
        QTextStream in(&file);
     
        while(!in.atEnd()) {
            QString line = in.readLine();
            QStringList fields = line.split(",");
     
            //Création du point et ajout au calque
     
            //*********************************************
            //Structure du fichier Waypoints
            //Col0 = CODE (1 à 5 CHAR)
            //Col1 = LATITUDE
            //Col2 = LONGITUDE
            //Col3 = PAYS (2 CHAR null si rien)
            //*********************************************
     
            QString str = fields.at(1);
            double latitude = str.toDouble();
            str = fields.at(2);
            double longitude = str.toDouble();
            str = fields.at(0);
     
            // Choix de l'icone
            //icone = new QPixmap(QCoreApplication::applicationDirPath() + "/Images/Point.bmp");
            icone = new QPixmap(GenIcone::wayPoint(str));
     
            Point* pointCourant = new Point(longitude, latitude, *icone, str);
            waypoints->addGeometry(pointCourant);
        }
     
        file.close();
    Aurais-je oublié de fermer/supprimer quelque chose ou y a-t-il une si grande différence d'utilisation mémoire entre les deux façons de procéder ?

    Merci pour votre aide.

  2. #2
    Responsable 2D/3D/Jeux


    Avatar de LittleWhite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2008
    Messages
    26 894
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mai 2008
    Messages : 26 894
    Points : 219 533
    Points
    219 533
    Billets dans le blog
    124
    Par défaut
    Bonjour,

    Pourquoi pm est construit dynamiquement (utilisation de pointeur). En plus, vous retournez une copie de pm, sans faire la libération de mémoire. Je ne sais pas combien de fois wayPoint() est appelé, mais cela me semble une fuite de mémoire.

  3. #3
    Membre régulier
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    199
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Mars 2004
    Messages : 199
    Points : 103
    Points
    103
    Par défaut
    Pourquoi pm est construit dynamiquement (utilisation de pointeur).
    Aller, je vais être franc : je ne sais pas !
    Malgré toutes mes recherches, je n'ai pas encore compris quand/pourquoi créer un objet de façon statique et quand/pourquoi le créer de façon dynamique. C'est une explication que je n'ai pas. On trouve toujours comment déclarer/créer mais pas pourquoi/quand telle ou telle procédure utiliser. Donc quand ça marche d'une façon ou d'une autre j'utilise la première façon qui fonctionne (souvent à partir d'exemples d'ailleurs). Je sais, ce n'est pas bien, mais c'est certainement le lot de ceux qui débutent sans être guidés. Heureusement, ce forum apporte beaucoup d'aide et je progresse.

    Donc j'ai retraduit ma méthode comme suit :

    genicone.h
    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
     
    #ifndef GENICONE_H
    #define GENICONE_H
    #include <QPixmap>
     
    class GenIcone
    {
    public:
        static QPixmap wayPoint(QString code);
        static QPixmap vor(QString code);
        static QPixmap vorDme(QString code);
        static QPixmap dme(QString code);
        static QPixmap ndb(QString code);
    };
     
    #endif // GENICONE_H
    genicone.cpp
    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
     
    #include "genicone.h"
    #include <QPainter>
     
    QPixmap GenIcone::wayPoint(QString code)
    {
        QPixmap pm(38,38);
        pm.fill(Qt::transparent);
        QPainter pmp(&pm);
        pmp.setRenderHint(QPainter::Antialiasing);
        pmp.setBrush(Qt::cyan);
        pmp.setPen(Qt::black);
        static const QPoint triangle[3] = {
            QPoint(15,0),
            QPoint(3, 20),
            QPoint(27,20)
        };
        pmp.drawPolygon(triangle, 3);
        pmp.setFont(QFont("ArialBold",12));
        pmp.drawText(1,32,code);
        pmp.end();
     
        return pm;
    }
    ...
    Ca ne génère pas d'erreur, mais le problème mémoire demeure.

    En plus, vous retournez une copie de pm, sans faire la libération de mémoire.
    Il est bien là le problème, merci de le mettre en évidence. Effectivement, waypoint étant appelé un peu plus de 250000 fois, ceci explique cela.
    Pour moi, la libération de mémoire se fait avec un delete. Mais si je fais cela, je ne suis plus en mesure de renvoyer pm. Bref, je tourne en rond avec mon code.

    Merci encore pour votre aide.

  4. #4
    Responsable 2D/3D/Jeux


    Avatar de LittleWhite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2008
    Messages
    26 894
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mai 2008
    Messages : 26 894
    Points : 219 533
    Points
    219 533
    Billets dans le blog
    124
    Par défaut
    Avec le nouveau code, je ne vois pas pourquoi il y aurait un problème de mémoire. Vous pouvez utiliser valgrind (Dr Memory sous Windows) pour trouver la source de la fuite.
    Ensuite, vous pouvez réduire les allocation/libération en faisant en sorte de créer le Pixmap/Painter qu'une unique fois pour vos 250000 textes. D'ailleurs dans cette même optique, si vous faites que 100 textes, est-ce que la fuite est toujours présente ou non ?

  5. #5
    Membre régulier
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    199
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Mars 2004
    Messages : 199
    Points : 103
    Points
    103
    Par défaut
    Merci encore pour cette aide.

    J'ai donc repris le code et - pour faciliter la détection du problème - réintégré la fonction à la méthode en n'initialisant qu'un seul QPixmap et en ne changeant que le texte à chaque fois. Cela donne le code suivant :

    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
    58
    59
     
    void Gspv::addFixes() // Calque des waypoints
    {
        waypoints = new GeometryLayer("Waypoints", mapadapter);
        mc->addLayer(waypoints);
     
            //Création de l'icone
            QPixmap icone(38,38);
            icone.fill(Qt::transparent);
            QPainter pmp(&icone);
            pmp.setRenderHint(QPainter::Antialiasing);
            pmp.setBrush(Qt::cyan);
            pmp.setPen(Qt::black);
            static const QPoint triangle[3] = {
                QPoint(15,0),
                QPoint(3, 20),
                QPoint(27,20)
            };
            pmp.drawPolygon(triangle, 3);
            pmp.setFont(QFont("ArialBold",10));
     
     
     
        QFile file(QCoreApplication::applicationDirPath() + "/data/Waypoints.txt");
        if(!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
            QMessageBox::information(0, "erreur lecture fichier : " + file.fileName(), file.errorString());
            return;
        }
     
        //Parser du fichier Waypoints
        QTextStream in(&file);
     
        while(!in.atEnd()) {
            QString line = in.readLine();
            QStringList fields = line.split(",");
     
            //Création du point et ajout au calque
     
            QString str = fields.at(1);
            double latitude = str.toDouble();
            str = fields.at(2);
            double longitude = str.toDouble();
            str = fields.at(0);
     
     
            //Ecriture du code de l'icone
            pmp.drawText(0,31,str);
            Point* pointCourant = new Point(longitude, latitude, icone, str);
     
            //Effacement du texte précédent
            pmp.eraseRect(0,20,38,15);
     
            //Rajout du point de passage sur le layer
            waypoints->addGeometry(pointCourant);
     
        }
     
        file.close();
    }
    J'ai aussi lancé l'application avec Dr Memory. Je ne sais pas exploiter le rapport mais il ne m'a pas semblé qu'un des problèmes soulevé était directement lié à mon code, même si en final l'application a planté par défaut d'adressage mémoire me semble-t-il.

    Voici le fichier global qui en résulte, j'ai simplifié les erreurs récurrentes.
    global.3604.log.txt

    A ce moment, je n'ai plus de voie de progression ouverte pour cette méthode.

    PS : pour en finir avec l'analyse de ce problème, l'origine se trouve dans la simple déclaration de QPainter pmp(&icone).
    Un Qpixmap transparent de 38x38 pixel sans QPainter amène à un impact sur la mémoire pour l'application de 152 Mo ce qui est équivalent à l'utilisation d'une icône BMP en 2 couleurs qui génère un impact de 158 Mo. Dès que Qpainter est déclaré, le besoin de mémoire s'envole pour finir par faire crasher l'application.

  6. #6
    Responsable 2D/3D/Jeux


    Avatar de LittleWhite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2008
    Messages
    26 894
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mai 2008
    Messages : 26 894
    Points : 219 533
    Points
    219 533
    Billets dans le blog
    124
    Par défaut
    Pour Dr Memory, il faut prendre le rapport "leaked" et non global.
    Pour voir, je dé-commenterai la partie pixmap et voir si la fuite est toujours présente. Je n'ai pas spécialement compris votre dernier paragraphe, cela étant dit.

  7. #7
    Membre régulier
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    199
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Mars 2004
    Messages : 199
    Points : 103
    Points
    103
    Par défaut
    Bonjour LittleWhite.
    Pour Dr Memory, il faut prendre le rapport "leaked" et non global.
    Je n'ai pas ce rapport dans le dossier. J'ai :
    - potential_errors
    - results
    - suppress
    - missing_symbols
    et le global.####.log

    Pour voir, je dé-commenterai la partie pixmap et voir si la fuite est toujours présente.
    Il ne me semble pas avoir commenté la partie pixmap dans mon dernier code...

    Je n'ai pas spécialement compris votre dernier paragraphe, cela étant dit.
    A la relecture, je comprends, des fois on est dans son univers sans avoir suffisamment de recul. Voici le détail du raisonnement.

    Si j'utilise un fichier "pointnoir.bmp" comme icone, j'obtiens le résultat suivant :


    le code se borne cette une simple ligne :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
     
    ...
       while(!in.atEnd()) {
    ...
            icone = new QPixmap(QCoreApplication::applicationDirPath() + "/Images/Pointnoir.bmp");
            Point* pointCourant = new Point(longitude, latitude, *icone, str);
    ...
     
        }
    ...
    et dans ce cas, la charge en mémoire de l'application est de 158 Mo

    Si j'utilise un simple QPixmap de couleur bleu, j'obtiens le résultat suivant :


    le code devient ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    ...
            //Création de l'icone
            QPixmap icone(38,38);
            icone.fill(Qt::blue);
    ...
       while(!in.atEnd()) {
    ...
           Point* pointCourant = new Point(longitude, latitude, icone, str);
    ...
     
        }
    ...
    et dans ce cas, la charge en mémoire est de 152Mo, soit sensiblement identique à l'appel au fichier.

    Dans le cas qui m'intéresse, je souhaite créer l’icône (un triangle) et rajouter son code dessous avec un drawtext du code pour arriver à ceci :


    le code est donc celui que j'ai présenté plus haut :
    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
     
    ...
            //Création de l'icone
            QPixmap icone(38,38);
            icone.fill(Qt::transparent);
            QPainter pmp(&icone);
           pmp.setRenderHint(QPainter::Antialiasing);
            pmp.setBrush(Qt::cyan);
            pmp.setPen(Qt::black);
            static const QPoint triangle[3] = {
                QPoint(15,0),
                QPoint(3, 20),
                QPoint(27,20)
            };
            pmp.drawPolygon(triangle, 3);
            pmp.setFont(QFont("ArialBold",10));
     
    ...
       while(!in.atEnd()) {
    ...
            pmp.drawText(0,31,str);
            Point* pointCourant = new Point(longitude, latitude, icone, str);
     
            //Effacement du texte précédent
            pmp.eraseRect(0,20,38,15);
    ...
     
        }
        pmp.end();
    Et c'est là que rien ne va plus !

    Alors on pourrait se dire que c'est le dessin du triangle et le rajout du texte qui génèrent la fuite de mémoire. Mais si l'on supprime toute la partie dessin et texte en ne conservant simplement qu'un appel à QPainter, et bien le problème mémoire persiste. Donc pour le code suivant - qui n'est supposé ne rien afficher de plus que des carrés bleus (comme dans le deuxième exemple ci-dessus) - j'obtiens un plantage par augmentation exponentielle du besoin mémoire.

    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
     
    ...
            //Création de l'icone
            QPixmap icone(38,38);
            icone.fill(Qt::transparent);
            QPainter pmp(&icone);
            //ici, plus rien
    ...
       while(!in.atEnd()) {
    ...
            Point* pointCourant = new Point(longitude, latitude, icone, str);
    ...
     
        }
        pmp.end();
    Ce code devrait donc fonctionner aussi bien que le second, mais non.

    D'où ma déduction que le problème se situe dans la mise en œuvre de la fonction QPainter.

    J'espère avoir été plus clair.

  8. #8
    Responsable 2D/3D/Jeux


    Avatar de LittleWhite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2008
    Messages
    26 894
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mai 2008
    Messages : 26 894
    Points : 219 533
    Points
    219 533
    Billets dans le blog
    124
    Par défaut
    Pour Dr Memory, je crois (de mémoire car je ne peux pas vérifier immédiatement) que c'est potential_errors. Aussi, il faut que le programme soit en debug, pour que ce soit intéressant.
    Pour l'histoire de dé-commenter, je voulais dire "commenter", afin de désactiver la partie pixmap.

    Au final, cela voudrait dire qu'il faille créer un unique QPainter pour l'affichage.

  9. #9
    Membre régulier
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    199
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Mars 2004
    Messages : 199
    Points : 103
    Points
    103
    Par défaut
    Bonjour LittleWhite

    Pour Dr Memory, je crois (de mémoire car je ne peux pas vérifier immédiatement) que c'est potential_errors. Aussi, il faut que le programme soit en debug, pour que ce soit intéressant.
    Le fichier potential_errors ne contient aucune information utile.

    Je pense lancer mon programme en mode debug avec Dr Memory. Pour cela j'utilise le .exe créé en mode debug auquel je rajoute les dll (debug) propre à Qt pour le faire tourner. Je n'ai pas trouver d'information permettant de lancer Dr memory directement à partir de Qt creator.

    Pour l'histoire de dé-commenter, je voulais dire "commenter", afin de désactiver la partie pixmap.
    Je pense que j'ai fait fait au travers des variantes mentionnées dans mon précédent post.

    Au final, cela voudrait dire qu'il faille créer un unique QPainter pour l'affichage.
    Là je ne comprends pas le sens de ceci. Il me semble avoir restructuré le code et que de cette façon il n'y a qu'un seul Qpainter activé, car il est avant la boucle while.

  10. #10
    Responsable 2D/3D/Jeux


    Avatar de LittleWhite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2008
    Messages
    26 894
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mai 2008
    Messages : 26 894
    Points : 219 533
    Points
    219 533
    Billets dans le blog
    124
    Par défaut
    Alors cela doit être le fichier results
    Bref, on cherche un fichier qui indique les fuites de mémoire.
    Sinon, je n'ai plus de piste .

  11. #11
    Membre régulier
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    199
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Mars 2004
    Messages : 199
    Points : 103
    Points
    103
    Par défaut
    Bonjour LittleWhite.

    Concernant les résultats de dr memory, je viens de relancer un test dont voici les résultats.

    results.txtsuppress.txt

    D'un autre coté, j'ai pu progresser grâce à ce sujet de stackoverflow : https://stackoverflow.com/questions/...ter-on-qpixmap.

    En synthèse le QPixmap doit être instancié en statique alors que le QPainter doit l'être en dynamique et surtout être détruit avant d'utiliser le QPixmap (pour prévenir les fuites de mémoire d'ailleurs). C'est donc que ce problème est connu.

    Ainsi, en réaménageant mon code de la façon suivante :
    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
     
    void Gspv::addFixes() // Calque des waypoints
    {
        waypoints = new GeometryLayer("Waypoints", mapadapter);
        mc->addLayer(waypoints);
     
        //Création de l'icone
        QPixmap icone(38,38);
        icone.fill(Qt::transparent);
        QPainter *paint = new QPainter(&icone);
        paint->setRenderHint(QPainter::Antialiasing);
        paint->setBrush(Qt::cyan);
        paint->setPen(Qt::black);
        static const QPoint triangle[3] = {
            QPoint(15,0),
            QPoint(3, 20),
            QPoint(27,20)
        };
        paint->drawPolygon(triangle, 3);
        delete paint;
     
    ...
     
        //Parser du fichier Waypoints
        QTextStream in(&file);
        while(!in.atEnd()) {
            QString line = in.readLine();
            QStringList fields = line.split(",");
            QString str = fields.at(1);
            double latitude = str.toDouble();
            str = fields.at(2);
            double longitude = str.toDouble();
            str = fields.at(0);
     
            //Rajout du point courant
            Point* pointCourant = new Point(longitude, latitude, icone, str);
            pointCourant->setBaselevel(10);
            pointCourant->setMaxsize(QSize(38, 38));
            waypoints->addGeometry(pointCourant);
        }
     
        file.close();
     
    }
    il fonctionne sans fuite de mémoire. C'est un pas dans la bonne direction.

    Le problème qu'il me reste à résoudre est de "dessiner" le texte sur le QPixmap. Or si je rajoute un code tel que celui-ci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
            //Rajout du code
            QPainter *pmp = new QPainter(&icone);
            pmp->setPen(Qt::black);
            pmp->setFont(QFont("ArialBold",9));
            pmp->eraseRect(0,20,38,15);
            pmp->drawText(0,33,str);
            delete pmp;
    dans la boucle while, avant le rajout du point courant, j'ai une fuite de mémoire.

    J'ai donc tenté d'écrire via une fonction extérieure à la boucle while de la façon suivante :
    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
     
    void Gspv::addFixes() // Calque des waypoints
    {
        waypoints = new GeometryLayer("Waypoints", mapadapter);
        mc->addLayer(waypoints);
     
        //Création de l'icone
        QPixmap icone(38,38);
        icone.fill(Qt::transparent);
        QPainter *paint = new QPainter(&icone);
        paint->setRenderHint(QPainter::Antialiasing);
        paint->setBrush(Qt::cyan);
        paint->setPen(Qt::black);
        static const QPoint triangle[3] = {
            QPoint(15,0),
            QPoint(3, 20),
            QPoint(27,20)
        };
        paint->drawPolygon(triangle, 3);
        delete paint;
     
    ...
     
        //Parser du fichier Waypoints
        QTextStream in(&file);
        while(!in.atEnd()) {
            QString line = in.readLine();
            QStringList fields = line.split(",");
            QString str = fields.at(1);
            double latitude = str.toDouble();
            str = fields.at(2);
            double longitude = str.toDouble();
            str = fields.at(0);
     
            addCode(icone,str); // ici appel de la fonction addCode
     
            //Rajout du point courant
            Point* pointCourant = new Point(longitude, latitude, icone, str);
            pointCourant->setBaselevel(10);
            pointCourant->setMaxsize(QSize(38, 38));
            waypoints->addGeometry(pointCourant);
     
        }
     
        file.close();
    }
     
    void Gspv::addCode(QPixmap pm, QString code)
    {
        QPainter *pmp = new QPainter(&pm);
        pmp->setPen(Qt::black);
        pmp->setFont(QFont("ArialBold",12));
        pmp->drawText(1,32,code);
        delete pmp;
    }
    le programme tourne correctement mais la fonction addCode n'écrit pas le code dans le QPixmap, bien qu'elle soit appelée et qu'elle se déroule correctement à chaque boucle.

    Une idée du problème ?

    merci encore pour l'aide apportée.

  12. #12
    Responsable 2D/3D/Jeux


    Avatar de LittleWhite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2008
    Messages
    26 894
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mai 2008
    Messages : 26 894
    Points : 219 533
    Points
    219 533
    Billets dans le blog
    124
    Par défaut
    Oui, car vous passer le pixmap en copie (ainsi que le QString, ce qui pose un problème de performance (voir la FAQ)) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    void Gspv::addCode(QPixmap pm, QString code)
    Donc, vous agissez sur une autre instance du QPixmap, instance qui est locale à la fonction.

  13. #13
    Membre régulier
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    199
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Mars 2004
    Messages : 199
    Points : 103
    Points
    103
    Par défaut
    Effectivement, ça passe mieux avec l'esperluette... erreur du débutant.

    Mais même si ça fonctionne, le problème mémoire reste dès lors que l'appel à QPainter se fait dans la boucle while, et ce de quelque manière que je tente de passer.

    Après toute ces recherche - qui néanmoins ont été très positive - j'abandonne donc cette voie et je vais envisager une autre solution.

    Encore merci beaucoup, LittleWhite, pour toute l'aide que vous m'avez apporté.

  14. #14
    Responsable 2D/3D/Jeux


    Avatar de LittleWhite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2008
    Messages
    26 894
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mai 2008
    Messages : 26 894
    Points : 219 533
    Points
    219 533
    Billets dans le blog
    124
    Par défaut
    Du coup, quelle sera la nouvelle méthode ?

  15. #15
    Membre régulier
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    199
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Mars 2004
    Messages : 199
    Points : 103
    Points
    103
    Par défaut
    Bonjour LittleWhite.

    Et bien voilà, je pense tenir le principe de ma nouvelle méthode. J'ai attentivement étudié l'exemple donné par Qt : "40000 chips" qui s'apparente fort bien à mon projet.

    Ils mettent la boucle while dans une méthode de MainWindow comme ceci (j'ai simplifié leur code pour ne retenir que le minimum nécessaire) :
    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
     
    void MainWindow::populateScene()
    {
        scene = new QGraphicsScene(this);
     
        // Populate scene
        int xx = 0;
        int nitems = 0;
        for (int i = -11000; i < 11000; i += 110) {
            ++xx;
            int yy = 0;
            for (int j = -7000; j < 7000; j += 70) {
                ++yy;
     
                QGraphicsItem *item = new Chip(Qt::transparent, xx, yy);
                item->setPos(QPointF(i, j));
                scene->addItem(item);
     
                ++nitems;
            }
        }
    }
    et ils dessinent et affichent leur texte par surcharge de paint dans la classe Chip :
    voici le .h simplifié aussi à l'essentiel :
    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
     
    #ifndef CHIP_H
    #define CHIP_H
     
    #include <QColor>
    #include <QGraphicsItem>
     
    class Chip : public QGraphicsItem
    {
    public:
        Chip(const QColor &color, int x, int y);
     
        QRectF boundingRect() const Q_DECL_OVERRIDE;
        QPainterPath shape() const Q_DECL_OVERRIDE;
        void paint(QPainter *painter, const QStyleOptionGraphicsItem *item, QWidget *widget) Q_DECL_OVERRIDE;
     
    private:
        int x;
        int y;
        QColor color;
    };
     
    #endif // CHIP_H
    Si je transpose mes besoins dans leur code, j'obtiens ce résultat, sans fuite mémoire bien entendu :


    Il me reste maintenant à transposer leur utilisation basée sur un QGraphicsItem, alors que j'ai besoin d'un Qpixmap.

    Peut-il y avoir un lien / une conversion entre les deux ?

    Merci pour votre aide.

  16. #16
    Responsable 2D/3D/Jeux


    Avatar de LittleWhite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2008
    Messages
    26 894
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mai 2008
    Messages : 26 894
    Points : 219 533
    Points
    219 533
    Billets dans le blog
    124
    Par défaut
    Si vous allez transposer un QGraphicsItem pour chaque texte différent que vous avez en QPixmap, cela risque d'être lourd. Pourquoi ne pas travailler complètement et uniquement avec la QGraphicsScene ?

  17. #17
    Membre régulier
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    199
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Mars 2004
    Messages : 199
    Points : 103
    Points
    103
    Par défaut
    Bonjour à tous.

    Trois semaines se sont passées depuis le début de ce post, semaines pendant lesquelles j'ai beaucoup fait d'essais différents, sans succès.

    Tout a débuté par le constat suivant : dessiner une icône dans un pixmap et la reproduire un peu plus de 250000 fois charge la mémoire pour 152 Mo alors que la même chose avec un simple rajout de 5 lettres en bas de l'icône amène à une saturation de la mémoire.

    Aujourd'hui, je pense avoir trouvé la raison à ce problème. Elle tient en un mot : cacheKey. Si le contenu est identique, un seul objet Qpixmap est utilisé d'où la faible utilisation mémoire du premier cas. Dès lors que le pixmap est modifié, ce dernier est de nouveau mis en cache à une autre adresse, accessible via cacheKey. Le fait pour moi de changer le code à chaque icône multiplie leur mise en cache, menant ainsi à la saturation de la mémoire. CQFD.

    Il ne s'agit donc pas d'une fuite de mémoire, mais bien d'une utilisation de la mémoire par QT.

    Il ne me reste plus qu'à revoir la conception même de mon application.

    Je considère donc ce problème résolu. Merci pour l'aide que vous m'avez apportée.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [VB6] Convertion d'un fichier bmp en jpg
    Par WOLO Laurent dans le forum VB 6 et antérieur
    Réponses: 22
    Dernier message: 12/01/2015, 13h22
  2. convertir un fichier bmp en jpeg (sous visual)
    Par mateo.14 dans le forum MFC
    Réponses: 2
    Dernier message: 24/03/2005, 13h22
  3. Un fichier .bmp comme paramètre d'une Procédure stockée
    Par FONKOU dans le forum Bases de données
    Réponses: 2
    Dernier message: 28/10/2004, 17h56
  4. Réponses: 2
    Dernier message: 07/10/2004, 14h16
  5. [TP]Charger un fichier bmp
    Par flavien tetart dans le forum Turbo Pascal
    Réponses: 5
    Dernier message: 30/06/2002, 19h04

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