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++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  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 147
    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 147
    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

+ 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