Bienvenue, Invité. Merci de vous connecter ou de vous inscrire.
Avez-vous perdu votre e-mail d'activation ?

Auteur Sujet: Chemin d'une image et .qrc  (Lu 4328 fois)

0 Membres et 1 Invité sur ce sujet

MadMaXx

  • Newbie
  • *
  • Messages: 26
    • Voir le profil
Chemin d'une image et .qrc
« le: Mai 26, 2013, 02:44:45 pm »
Bonjour,

Un moyen efficace de lier des images à un .exe sans éviter de toute se les trimballer est d'utiliser un fichier ressource .rc . Dans mon cas j'utilise un fichier ressource à la sauce Qt soit un .qrc (http://qt.developpez.com/doc/4.6/resources/ ).

Concrètement, sa s'utilise comme ça avec la librairie Qt:

QIcon(":/images/img.png")

Le :/ permet de dire directement que l'image est dans le .qrc
Mais ça ne marche pas dans ce cas:

if (!image.loadFromFile(":/images/img.jpg"))
        return EXIT_FAILURE;

Avec les objets SFML ça ne marche pas. Je suppose que ce n'est pas exclusif a SFML, mais au fond j'en sais trop rien (c'est pour ça que je poste ici d'ailleurs). Pourtant ces .qrc sont très pratiques.

Auriez-vous une idée de comment faire pour pouvoir utiliser les .qrc avec SFML ? J'ai déjà cherché sur le web sans succès. Merci de m'aider, sinon tant pis je rangerais mes images de façon "classique" (dossiers à coté du .exe).

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32504
    • Voir le profil
    • SFML's website
    • E-mail
Re : Chemin d'une image et .qrc
« Réponse #1 le: Mai 26, 2013, 05:57:01 pm »
SFML ne peut bien sûr pas utiliser le système de ressources spécifique à Qt, il n'y a que Qt qui sait interpréter un chemin du type ":/la_ressource".

Du coup tu as deux solutions :

1. Tu copies ta ressource dans un tableau de char (je ne pense pas que Qt puisse te fournir un pointeur direct sur celle-ci), et tu utilises image.loadFromMemory.

2. Tu crées un sf::InputStream qui sait lire la ressource avec les classes Qt, et tu utilises image.loadFromStream.

Que tu choisisses l'une ou l'autre solution, tu auras besoin de QFile, et peut-être de QDataStream.
Laurent Gomila - SFML developer

MadMaXx

  • Newbie
  • *
  • Messages: 26
    • Voir le profil
Re : Chemin d'une image et .qrc
« Réponse #2 le: Mai 31, 2013, 03:40:07 pm »
Alors j'ai tenté quelque chose mais j'ai comme erreur: 'Int64' does not name a type. J'ai vu sur Internet qu'avec cette erreur il fallait inclure  <inttypes.h> et tester uint64_t ou int64_t à la place de Int64, mais ça donne toujours des erreurs. Il y aussi un truc dont je ne suis pas sûr... La méthode de la classe QFile pos() renvoie un qint32 et la méthode seek prend un int32. Est-ce bien compatible ? Voici le code:

main.cpp:

#include <SFML/Graphics.hpp>
#include "stream.h"

int main()
{
    sf::RenderWindow window(sf::VideoMode(800, 800), "SFML works!");
    sf::Texture image;
    Stream stream(":/img/uuu.jpg");
    if (!image.loadFromStream(stream))
        return EXIT_FAILURE;
    sf::Sprite sprite;
    sprite.setTexture(image);
    sprite.setPosition(0,0);
    sprite.setScale(0.5,0.5);
    while (window.isOpen())
    {
        sf::Event event;
        while (window.pollEvent(event))
        {
            if (event.type == sf::Event::Closed)
                window.close();
        }

        window.clear();
        window.draw(sprite);
        window.display();
    }

    return 0;
}
 

stream.cpp:

#include "stream.h"

Stream::Stream(QString & name)
{
    QFile file(name);
    seek(file.pos());
}

stream.h:

#ifndef STREAM_H
#define STREAM_H

#include <QTemporaryFile>
#include <QFile>
#include <stdint.h>
#include <inttypes.h>

class Stream : public sf::InputStream
{
public:
    Stream(QString & name);
    Int64 read(void* data, Int64 size);
    Int64 seek(Int64 position);
    Int64 tell();
    Int64 getSize();
};

#endif // STREAM_H
 

« Modifié: Mai 31, 2013, 03:43:59 pm par MadMaXx »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32504
    • Voir le profil
    • SFML's website
    • E-mail
Re : Chemin d'une image et .qrc
« Réponse #3 le: Mai 31, 2013, 04:17:23 pm »
Int64 est un type SFML, donc sf::Int64. Sinon, commence à implémenter le truc et puis tu verras bien ;)
Laurent Gomila - SFML developer

MadMaXx

  • Newbie
  • *
  • Messages: 26
    • Voir le profil
Re : Chemin d'une image et .qrc
« Réponse #4 le: Mai 31, 2013, 06:20:59 pm »
Ah oui c'était pourtant évident !  ::) Bon j'ai mis maintenant l'IDE  me met:

erreur : undefined reference to `vtable for Stream'
erreur : undefined reference to `Stream::seek(long long)'

Un problème d'héritage je crois. J'ai pourtant bien remis les méthodes virtuelles pures de la classe parente non? :S

main.cpp

#include <SFML/Graphics.hpp>
#include "stream.h"

int main()
{
    sf::RenderWindow window(sf::VideoMode(800, 800), "SFML works!");
    sf::Texture image;
    Stream stream(":/img/uuu.jpg");
    if (!image.loadFromStream(stream))
        return EXIT_FAILURE;
    sf::Sprite sprite;
    sprite.setTexture(image);
    sprite.setPosition(0,0);
    sprite.setScale(0.5,0.5);
    while (window.isOpen())
    {
        sf::Event event;
        while (window.pollEvent(event))
        {
            if (event.type == sf::Event::Closed)
                window.close();
        }

        window.clear();
        window.draw(sprite);
        window.display();
    }

    return 0;
}
 

stream.cpp

#include "stream.h"

Stream::Stream(const char name[])
{
    QFile file(name);
    seek(file.pos());
}

 

stream.h

#ifndef STREAM_H
#define STREAM_H

#include <SFML/System.hpp>
#include <QTemporaryFile>
#include <QFile>

class Stream : public sf::InputStream
{
public:
    Stream(const char name[]);
    sf::Int64 read(void* data, sf::Int64 size);
    sf::Int64 seek(sf::Int64 position);
    sf::Int64 tell();
    sf::Int64 getSize();
};

#endif // STREAM_H

 

« Modifié: Mai 31, 2013, 06:26:22 pm par MadMaXx »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32504
    • Voir le profil
    • SFML's website
    • E-mail
Re : Chemin d'une image et .qrc
« Réponse #5 le: Mai 31, 2013, 07:14:53 pm »
Et où sont définies toutes les fonctions que tu déclares dans la classe Stream ?
Laurent Gomila - SFML developer

MadMaXx

  • Newbie
  • *
  • Messages: 26
    • Voir le profil
Re : Chemin d'une image et .qrc
« Réponse #6 le: Mai 31, 2013, 10:33:11 pm »
Je mettais les prototypes en pensant que les fonctions étaient déjà définies et que ça "annulerait" le fait qu'elles soient virtuelles enfin bref n'importe quoi puisqu'elles ne sont pas du tout définies en amont...

Je crois que je m'embête pour rien et qu'il y a bien plus simple avec loadFromMemory. Ça devrait tenir juste dans le main:

#include <SFML/Graphics.hpp>
#include <QFile>

int main()
{
    sf::RenderWindow window(sf::VideoMode(800, 800), "SFML works!");
    sf::Texture image;
    QFile file(":/img/uuu.jpg");
    image.loadFromMemory(file.???,file.size());
    sf::Sprite sprite;
    sprite.setTexture(image);
    sprite.setPosition(0,0);
    sprite.setScale(0.5,0.5);
    while (window.isOpen())
    {
        sf::Event event;
        while (window.pollEvent(event))
        {
            if (event.type == sf::Event::Closed)
                window.close();
        }

        window.clear();
        window.draw(sprite);
        window.display();
    }

    return 0;
}

 


On doit toucher au but avec ça le problème est juste dans le image.loadFromMemory(). On a la taille de l'image et reste plus qu'à trouver le pointeur de l'image. J'ai pensé à file.map() d'après la doc http://qt-project.org/doc/qt-4.8/qfile.html qui est la seule fonction qui renvoie un pointeur... Après je sais pas quoi donner au paramètre "qint64 offset" de ce map().

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32504
    • Voir le profil
    • SFML's website
    • E-mail
Re : Chemin d'une image et .qrc
« Réponse #7 le: Mai 31, 2013, 10:51:30 pm »
"offset" c'est simplement 0, puisque tu veux commencer au début du fichier.

C'est pas la méthode la plus efficace mais ça devrait marcher.
Laurent Gomila - SFML developer

MadMaXx

  • Newbie
  • *
  • Messages: 26
    • Voir le profil
Re : Chemin d'une image et .qrc
« Réponse #8 le: Juin 01, 2013, 09:27:16 am »
Merci, en effet ça marche avec ceci:

image.loadFromMemory(file.map(0,file.size()),file.size());
 

Quand vous dites que la méthode n'est pas la plus efficace, vous voulez dire au niveau du code ou de la vitesse d’exécution ? Vous auriez fait avec InputStream ?

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32504
    • Voir le profil
    • SFML's website
    • E-mail
Re : Chemin d'une image et .qrc
« Réponse #9 le: Juin 01, 2013, 09:36:24 am »
Oui, j'aurais fait un sf::InputStream. C'est plus fastidieux à écrire mais une fois que c'est fait c'est beaucoup plus propre et simple à utiliser.

En termes de performances, je ne sais pas trop ce que vaux le mapping de fichier. C'est plus rapide que de charger tout le contenu en mémoire, mais je ne sais pas si ça vaut la lecture directe.
Laurent Gomila - SFML developer

 

anything