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

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    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
    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
    27 145
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

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

    Informations forums :
    Inscription : Mai 2008
    Messages : 27 145
    Billets dans le blog
    150
    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.
    Vous souhaitez participer à la rubrique 2D/3D/Jeux ? Contactez-moi

    Ma page sur DVP
    Mon Portfolio

    Qui connaît l'erreur, connaît la solution.

  3. #3
    Membre confirmé
    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
    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
    27 145
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

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

    Informations forums :
    Inscription : Mai 2008
    Messages : 27 145
    Billets dans le blog
    150
    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 ?
    Vous souhaitez participer à la rubrique 2D/3D/Jeux ? Contactez-moi

    Ma page sur DVP
    Mon Portfolio

    Qui connaît l'erreur, connaît la solution.

  5. #5
    Membre confirmé
    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
    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
    27 145
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

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

    Informations forums :
    Inscription : Mai 2008
    Messages : 27 145
    Billets dans le blog
    150
    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.
    Vous souhaitez participer à la rubrique 2D/3D/Jeux ? Contactez-moi

    Ma page sur DVP
    Mon Portfolio

    Qui connaît l'erreur, connaît la solution.

+ 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