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

 C++ Discussion :

sauvegarder une multi_array en plusieurs fichier .raw


Sujet :

C++

  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    245
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Juin 2007
    Messages : 245
    Par défaut sauvegarder une multi_array en plusieurs fichier .raw
    Bonjour,

    J'essaye de sauvegarder une matrice a trois ou plus dimensions en fichier .raw de facon a pouvoir les ouvrirs sous imagej.

    j'ai ma matrice nommee data (c'est une multi_array de la librairie boost).

    admettons qu'elle fasse une taille de 3x865x568.
    j'essaye donc de faire 3 fichiers .raw avec chacun une matrice 865x568.
    les dimensions de la matrice sont stockes dans ma class ainsi que le nombre de bytes par elements donc ceci n'est pas un probleme. (la par exemple je suis en int).

    j'ai essaye le code:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    void Images::save_binaryFile()
    {
      cout << "saving the images" << endl;
     
      //calculation of the size of one slice
      int length1 = tsize[0][0]*tsize[0][1]*2; //tsize is a table with the size of the dimensions of each matrix used in the program.
      ofstream binaryFile ("test_image.raw", ios::out | ios::binary);
      binaryFile.write((char*)&data,length1);    //sizeof(&data) or sizeof(data)
      binaryFile.close();
    }
    mais ca ne marche pas. ca m'ecrit un fichier de taille 8ko au lieu de 994 ko.
    j'ai remarque que sizeof(data) me retourne 160 alors que c'est une matrice de taille 3*568*865*2.
    du coup je suis assez surpris par ce que me retourne sizeof(data).

    quelle erreur ais-je faite ?

    Merci d'avance

  2. #2
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 154
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 154
    Billets dans le blog
    4
    Par défaut
    Bonjour,

    ton erreur (au moins) est que sizeof est fait à la compilation.
    et sizeof(data) retourne la taille du type data, je suppose qu'il s'agit d'un pointeur, dont ça doit valoir 4 (il me semble sur une archi 32 bits).
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  3. #3
    Membre confirmé
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    245
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Juin 2007
    Messages : 245
    Par défaut
    bonjour,

    j'ai vu sur internet que sizeof etait fait a la compilation.
    (du coup j'ai un peu du mal a voir son utilite pour le coup ...)
    je me demandais justement pourquoi il me retourne 160 et pas 4 ou 8 ou un truc du genre.
    c'est pour cela que je ne l'utilise plus dans mon programme (je l'ai commente et remplace par length1 que je calcul comme etant le nombre d'element de la matrice * 2 vu que j'utilise des int (16 bits si je me trompe pas. enfin ca j'ai pas bien suivi parce qu'apparemment ca depend de si on est en 64 ou 32 bits et du compileur.... moi la plupart de mes ordi sur lequel j'utilise le programme sont en 64 bits).

  4. #4
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Citation Envoyé par svagrim Voir le message
    bonjour,

    j'ai vu sur internet que sizeof etait fait a la compilation.
    (du coup j'ai un peu du mal a voir son utilite pour le coup ...)
    En fait, c'est un "reliquat" du C...

    En C, on utilise les fonction *alloc (malloc, realloc, calloc, ...) et free.

    Les fontions *alloc prennent un nombre de bytes (les... char qui, ont d'office une taille de 1 et qui correspondent à la plus petite taille que l'on peut créer sans être au niveau du bit) comme taille de l'espace mémoire à allouer.

    La taille de n'importe quel type est connue à la compilation, mais elle n'est jamais valide que pour une architecture donnée avec un système d'exploitation donné.

    Et comme ni la norme C ni la norme C++ ne définissent clairement la taille des différents types "primitifs" (char, short, int, long, long long, float, double, long double + version signed et unsigned si existantes), on ne peut pas se baser sur ce que l'on pourrait observer, sur une architecture donnée, pour déduire la taille des types primitifs.

    En effet, tout ce qui est défini dans la norme C au niveau de la taille des types primitifs, c'est :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    sizeof(char) = sizeof(unsigned char) = 1;
    sizeof(char) <= sizeof(short) <= sizeof(int) <= sizeof(long) <= sizeof(long long)
    sizeof(char  <= sizeof(float) <= sizeof(double) <= sizeof(long double)
    Et tu ne peux même pas être sur que la taille d'un char soit de 8 bits (ca, ce n'est valable que si l'architecture travaille classiquement avec la table ASCII), parce que la norme précise que la taille d'un char est une taille "au minimum suffisante pour permettre de représenter tous les caractères du jeux de caractères utilisé"

    Dés lors, pour être sur qu'un code sera susceptible de fonctionner sur n'importe quel type d'architecture, il faut utiliser l'opérateur sizeof(type utilisé) qui renverra la taille de l'espace mémoire nécessaire à la représentation du type indiqué pour une architecture donnée, sur un système donné.

    En sachant quels sont l'architecture et le système pour lequel on va compiler l'application, le compilateur saura quel est exactement la taille de l'espace mémoire qu'il devra réserver pour être en mesure de maintenir les informations requises
    c'est pour cela que je ne l'utilise plus dans mon programme (je l'ai commente et remplace par length1 que je calcul comme etant le nombre d'element de la matrice * 2 vu que j'utilise des int (16 bits si je me trompe pas. enfin ca j'ai pas bien suivi parce qu'apparemment ca depend de si on est en 64 ou 32 bits et du compileur....
    Non, "classiquement", un int fait en réalité 32 bits (4 bytes)... Et ce, que ce soit sur une architecture 32 bits ou 64 bits (enfin, lorsqu'on parle de PC uniquement ).

    Mais, comme je l'ai indiqué plus haut, ce n'est valable que pour les architectures qui utilisent les même convention que les pc.

    Si tu veux que ton application ait une chance de fonctionner correctement sur n'importe quel système et n'importe quelle architecture sans avoir à modifier le code (d'autant plus que tu risques d'avoir du mal à déterminer "où se trouve l'erreur ), tu ne peux absolument pas de baser sur cette valeur lorsque tu as besoin de connaitre la taille de ton int
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  5. #5
    Membre confirmé
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    245
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Juin 2007
    Messages : 245
    Par défaut
    ok,
    merci pour toutes ces explications.
    je pense qu'avant de faire la version qui marche sur toutes les plateformes que j'utilise je vais commencer par la faire marcher sur celle que j'utilise le plus (mon pc avec ubuntu 12.04).

    du coup j'ai changé là taille length1 en multipliant par 4 au lieu de 2 pour le nombre de bytes.
    et ça n'a rien changé... j'ai toujours un fichier beaucoup trop court à la fin qui ne fait que 8 ko. ou 4 des fois ... je comprend pas trop.

    du coup en dehors de la taille en nombre de bytes, il y aurait un autre probleme dans mon programme ?
    pourquoi je n'arrive pas à sauvegarder cette matrice de façon à pour l'ouvrir en raw sous imagej.

    ça a pourtant l'air simple ... en dehors de cette histoire du nombre de bytes pour un int.

  6. #6
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Peut etre y arriverais tu beaucoup plus facilement si:
    1. tu respectais le principe de la responsabilité unique
    2. tu gardais "simplement" en tête le fait qu'une image composée de x pixels de large et de y pixels de haut est en fait une image composée de ... x*y pixels.
    Le principe de la responsabilité unique t'indique que chaque classe et chaque fonction devrait ne faire qu'une chose, mais devrait le faire correctement.

    Ton image a pour but de représenter un ensemble de pixels Cela signifie qu'il faut "quelque chose" pour représenter le pixel en lui-même, car tu ne peux pas demander à ton image de représenter à la fois la couleur qui sera affichée et de garder une trace de l'ensemble des points qu'il faut afficher.

    Tu devrais donc commencer par créer une structure pixel qui pourrait ressembler à quelque chose comme
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    struct Pixel{
        /* attention !! les valeurs disponibles pour chaque couleur d'un pixel sont
         * souvent codées sous la forme d'un unsigned char... 
         *
         * es-tu sur qu'il s'agisse d'un int ???
         */
        int red;
        int green; 
        int blue;
    };
    De cette manière, tu pourrais représenter ton image de x pixels de large et y pixels de haut sous la forme d'un tableau composé de x*y pixels.

    Pour pouvoir accéder à un pixel positionné à la ligne L et à la colonne C, tu utiliserait alors la formule position = L* x + C.

    au final, cela pourrait ressembler à quelque chose comme:
    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
    class ImageRaw{
        public:
            ImageRaw(int width, int height): width_(width),height_(height),
                data_(width*height){}
            /* juste parce qu'il est peut etre utile de pouvoir récupérer la largeur
             * et la hauteur de l'image ;))
             */
           int width() const{return widht_;}
           int height() const{return height_;}
           /* On veut pouvoir modifier le pixel qui se trouve à la ligne line et à la 
            * colonne column
            */
           Pixel & pixel(int line, int column){return data_[width_*line + column];}
           /* On veut, le cas échéant, pouvoir récupérer (sans pouvoir le modifier)
            * le pixel se trouvant à la ligne line et à la colonne column
            */
           Pixel const & pixel(int line, int column) const{return data_[width_*line+ column];}
           /* et l'on souhaite pouvoir enregistrer ces données sous forme de fichier raw
            */
          void saveRawFile(std::string const & filename){
              std::ofstream ofs(filename.c_str(), std::ios::binary);
              /* !!! je ne présente que la sauvegarde des pixels, à toi
               * de rajouter ce qu'il manque ;)
               *
               * attention!! tu pourrais avoir un problème de boutisme...
               * la spécification des fichiers raw utilise peut etre un boutisme
               * différent de ton architecture. Il t'appartient d'en tenir compte ;)
               */
              ofs.write(reinterpret_cast<char*>(& data_[0]), width_*height_*sizeof(Pixel));
        private:
            int width_;
            int height_;
            std::vector<Pixel> data_;
    };
    L'utilisation devient alors proche de quelque chose comme
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    int main(){
        ImageRaw img(253, 158);
        img.pixel(12,15).red=0x00;
        img.pixel(12,15).green= 0xFF;
        img.pixel(12,15).blue = 0x7F;
        img.saveRawFile("myImage.raw");
    }
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  7. #7
    Membre confirmé
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    245
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Juin 2007
    Messages : 245
    Par défaut
    merci pour ces reponses!

    c'est effectivement beaucoup plus complique que tout ce que j'ai trouve jusque la sur internet ou tous disais que les 3/4 lignes que j'avais poste suffisait.

    pour la struct pixel, ca fait bizarre de devoir repasser par un tableau alors que j'utilise des matrices style multi_array et matrix de Boost.

    sinon oui je suis sur que c'est des entiers.
    le data provienne d'ailleurs de ma multiarray que je remplie avec
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    int16_t number;
    number = trucmuche;
    data[x][y][z] = number;
    mes dimensions de matrice sont stockes dans une matrice tsize et je peux les recuperer aussi avec certaines fonctions de boost. enfin pour les matrix. pour les multi_array j'ai pas trouve.

    bon ba je potasse ca lundi. merci de ton aide. j'espere que je vais m'en sortir avec ca

  8. #8
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Citation Envoyé par svagrim Voir le message
    merci pour ces reponses!

    c'est effectivement beaucoup plus complique que tout ce que j'ai trouve jusque la sur internet ou tous disais que les 3/4 lignes que j'avais poste suffisait.
    Disons que c'est surtout une habitude de développer en suivant certaines règles
    pour la struct pixel, ca fait bizarre de devoir repasser par un tableau alors que j'utilise des matrices style multi_array et matrix de Boost.
    Ben non, un multiarray ou une matrice, c'est une collection...

    Personnellement, je crée juste une collection d'objet composés de données "qui vont bien". Ca permet juste de donner des noms "cohérents" à ce que l'on manipule
    sinon oui je suis sur que c'est des entiers.
    le data provienne d'ailleurs de ma multiarray que je remplie avec
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    int16_t number;
    number = trucmuche;
    data[x][y][z] = number;
    alors, ce ne sont pas des int, mais des ... int16_t (ce qui correspond à un type composé de 16 bits et qui est est beaucoup plus proche des short que des int, car les int sont classiquement composés de 32 bits)
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  9. #9
    Membre confirmé
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    245
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Juin 2007
    Messages : 245
    Par défaut
    du coup je creais une structure Pixel.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    struc Pixel {
    int16_t nb_photons;
    };
    apres dans ma classe je rajoute ce que tu m'a dit.
    enfin sauf la definition de data que j'ai deja faite. et j'ai deja aussi le moyen de recuperer les tailles des differentes dimensions de ma matrices.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    typedef boost::multi_array<int16_t, 3> array_type;
    array_type data;
    donc en gros je rajoute
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    Pixel & pixel(int line, int column){return data[line][column];}
           /* On veut, le cas échéant, pouvoir récupérer (sans pouvoir le modifier)
            * le pixel se trouvant à la ligne line et à la colonne column
            */
           Pixel const & pixel(int line, int column) const{return data[line][column];}
           /* et l'on souhaite pouvoir enregistrer ces données sous forme de fichier raw
    la j'avoue pas bien saisir la difference entre les deux pixel ....

    et apres je remplace ma fonction pour sauvegarder par :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    void saveRawFile(std::string const & filename){
              std::ofstream ofs(filename.c_str(), std::ios::binary);
              /* !!! je ne présente que la sauvegarde des pixels, à toi
               * de rajouter ce qu'il manque ;)
               *
               * attention!! tu pourrais avoir un problème de boutisme...
               * la spécification des fichiers raw utilise peut etre un boutisme
               * différent de ton architecture. Il t'appartient d'en tenir compte ;)
               */
              ofs.write(reinterpret_cast<char*>(& data[0]), tsize[0][0]*tsize[0][1]*sizeof(Pixel));
    ca ne marche pas pour le moment. mais je vais continuer a essayer.
    c'est bien comme ca qu'il faudrait faire alors ?
    moyennement des petites modifs vu que ca ne marche pas encore mais c'est pas loin ?

    la structure pixel je dois la creer dans la classe ? en private ?

  10. #10
    Membre confirmé
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    245
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Juin 2007
    Messages : 245
    Par défaut
    ca compile mais j'ai toujours un fichier de 4ko a la fin ne comportant pas mon image.
    par contre je n'utilise pas pixel en fait ...
    vu que tu t'en es servi que pour definir la matrice data.
    mais moi data est deja defini comme j'ai montre avec la multi_array.
    et je peux pas changer ca vu que je l'utilise dans pas mal d'autres fonctions.
    ou alors faudrait que je cree un data2 comme tu le dis et que je copie les valeurs dans data dans data2. mais ca me parait quand meme vachement farfelu et question optimisaton de memoire ca me parait pas terrible...

  11. #11
    Membre confirmé
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    245
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Juin 2007
    Messages : 245
    Par défaut
    ah! j'y suis presque !
    je vous tiens au courant d'ici pas longtemps.
    j'ai just un shift d'image qui traine la.
    j'ai genre une partie de droite de l'image qui passe a gauche.
    je cherche d'ou ca peut venir mais sinon les valeurs sont les bonnes et tout et tout!
    merci ! j'y suis presque !

  12. #12
    Membre confirmé
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    245
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Juin 2007
    Messages : 245
    Par défaut
    bon ca y est je m'en suis sorti.
    j'avais un probleme dans une autre parti du programme en fait.
    merci a tous !

    au cas ou ca interesse voici mon code du coup:
    main:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
      for(unsigned int k = 0; k < files.size(); ++k)
      {
          string name="proj_"+boost::lexical_cast<string>(k);
          myImages.save_binaryFile(path,name,k);
      }
    header:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
       struct Pixel {
       int16_t nb_photons;
       };
       //function: save the matrix
       void save_binaryFile(std::string path, std::string const & filename, int slice);
    la structure pixel ne me sert a rien entre guillemet. a part qu'il me fallait un truc sur lequel faire le sizeof. je peux pas le faire sur la multi_array directement.
    et puis bon comme ca je me rapelerais de la methode de koala

    et sur le fichier ou sont defini les fonctions de ma classe:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    void Images::save_binaryFile(string path, string const & filename, int slice){
              int length1 = tsize[0][0]*tsize[0][1]*sizeof(Pixel);
              string path_file = path+filename;
              ofstream ofs(path_file.c_str(), std::ios::binary);
              ofs.write(reinterpret_cast<char*>(& data[slice][0][0]), length1);}
    bref tout bete au final me sens un peu nul sur le coup. mais sur le net j'avais trouve que ce que j'avais poste au debut.

    plus qu'un seul probleme dans ce programme.
    j'arrive pas a utiliser les fonctions boost pour modifier la taille de mes multi_array ....
    merci encore !

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

Discussions similaires

  1. sauvegarde d'une bd en plusieurs fichiers
    Par brudao dans le forum PHP & Base de données
    Réponses: 2
    Dernier message: 18/11/2009, 11h49
  2. [ImageMagick] Sauvegarder une image dans un fichier
    Par kivan666 dans le forum Bibliothèques et frameworks
    Réponses: 1
    Dernier message: 15/12/2006, 12h28
  3. [XSL]récupérer une valeur de plusieurs fichiers XML
    Par snoop dans le forum XSL/XSLT/XPATH
    Réponses: 7
    Dernier message: 05/02/2006, 00h32
  4. Réponses: 4
    Dernier message: 03/12/2004, 11h18
  5. Sauvegarder une surface dans un fichier
    Par Freakazoid dans le forum DirectX
    Réponses: 6
    Dernier message: 18/08/2002, 15h23

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