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 :

ecrire des images bmp


Sujet :

C

  1. #1
    Membre habitué

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2010
    Messages
    80
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2010
    Messages : 80
    Points : 127
    Points
    127
    Par défaut ecrire des images bmp
    Bonjour,

    je manipule des tableaux des données, et j'essaie de les sauvegarder sous forme d'images bmp.
    J'ai donc fait comme dit là bas : http://www.siggraph.org/education/ma...ag/bmpfile.htm,

    mais même en n'écrivant que des zéros dans mon image, je n'arrive pas à l'ouvrir avec paint ensuite...

    Je n'arrive pas à savoir si mon pb vient de ma méconnaissance de la librairie standard du C (fwrite et toute la clique) ou d'une mauvaise écriture de données...

    Pourriez vous jeter un oeil svp?

    je n'y arrive vraiment pas...

    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
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
     
     
    // structure encapsulant le Header BMP
    typedef struct {
    	char id[2];
    	long filesize;
    	int reserved[2];
    	long headersize;
    	long infoSize;
    	long width;
    	long depth;
    	short biPlanes;
    	short bits;
    	long biCompression;
    	long biSizeImage;
    	long biXPelsPerMeter;
    	long biYPelsPerMeter;
    	long biClrUsed;
    	long biClrImportant;
    } BMPHEAD;
     
     
     
     
    void display (float* alt, int pixels)
    {
                 // ouverture du fichier de sortie
    	FILE* out = fopen("img.bmp", "wb") ;
    	if (out == NULL) {
    		cout << "error : no file !" << endl ;
    		return ;
    	}
                 // REMPLISSAGE DU HEADER
    	BMPHEAD bh ;
    	memset ((char *) &bh, 0, sizeof(BMPHEAD)) ; /* sets everything to 0 */
    	memcpy (bh.id, "BM", 2) ;
    	bh.filesize ; // =   calculated size of your file (see below)
    	//bh.reserved[0] = 0 ; bh.reserved[1] = 0 ;
    	bh.headersize  = 54L  ; // (for 24 bit images)
    	bh.infoSize  =  0x28L ; // (for 24 bit images)
    	bh.width     = (long) pixels ; // size in pixels of your image
    	bh.depth     = (long) pixels ; // size in pixels of your image
    	bh.biPlanes  =  1 ; // (for 24 bit images)
    	bh.bits      = 24 ; // (for 24 bit images)
    	bh.biCompression = 0L ;  // (no compression)
    	int bytesPerLine;
     
    	bytesPerLine = bh.width * 3;  /* (for 24 bit images) */
    	/* round up to a d word boundary */
    	if (bytesPerLine & 0x0003) 
    	{
    		bytesPerLine |= 0x0003;
    		++bytesPerLine;
    	}
    	bh.filesize=bh.headersize+(long)bytesPerLine*bh.depth;
    	fwrite(&bh, 1, sizeof (bh), out);
    	// end header
     
    	char *linebuf;
     
    	linebuf = (char *) calloc(1, bytesPerLine);
    	if (linebuf == NULL) {
    		printf ("Error allocating memory\n");
    		exit (1);   
    	}
    	for (int line = pixels-1 ; line >= 0 ; --line)
    	{
    		for (int j = 0 ; j < pixels ; ++j)
    		{
                              // ICI , JE N'ECRIS QUE DES ZEROS, EN M'ATTENDANT
                              // A UN CARRE NOIR EN SORTIE
    			int midx = line*pixels + j ;
    			if (alt[midx] == -10.f) {
    				linebuf[3*j] = (char) 0 ;
    				linebuf[3*j+1] = (char) 0 ;
    				linebuf[3*j+2] = (char) 0 ;
    			}
    			else {
    				linebuf[3*j] = (char) 0 ; 				linebuf[3*j+1] = (char) 0 ; 				linebuf[3*j+2] = (char) 0 ;			
    }
    		}
    		fwrite(linebuf, 1, bytesPerLine, out);
    	}
    	free(linebuf) ;
    	fclose (out) ;
    }

  2. #2
    Expert confirmé

    Inscrit en
    Août 2006
    Messages
    3 942
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 3 942
    Points : 5 654
    Points
    5 654
    Par défaut
    Boa,

    Tu es sûr de ta structure ?

    Il est probable qu'elle ne corresponde pas, en raison des alignements faits par le compilateur.

    Chez moi, j'obtiens size = 60, alors qu'elle doit faire 54.
    Si les cons volaient, il ferait nuit à midi.

  3. #3
    Expert confirmé

    Inscrit en
    Août 2006
    Messages
    3 942
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 3 942
    Points : 5 654
    Points
    5 654
    Par défaut
    Heo,

    Après vérification, tu devrais avoir :
    (je ne mets les balises [ code] que pour avoir l'indentation)

    pour GCC :
    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
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    struct myT{
    	char id[2];
    	long filesize;
     
    	// à noter la correction du type pour le champ reserved
    	//int reserved[2];
    	short reserved[2];
     
    	long headersize;
    	long infoSize;
    	long width;
    	long depth;
    	short biPlanes;
    	short bits;
    	long biCompression;
    	long biSizeImage;
    	long biXPelsPerMeter;
    	long biYPelsPerMeter;
    	long biClrUsed;
    	long biClrImportant;
    } __attribute__((__packed__));
     
    typedef myT BMPHEAD;
     
    //===============================================================
    // on ne peut pas simplifier les 2 définitions ci-dessus en
     
    typedef struct {
            ...
    } __attribute__((__packed__)) BMPHEAD;
     
    // !!
    //===============================================================
     
     
    int main (int argc, char* argv [])
    {
        //printf("hello \n");
        printf("size BMPHEAD = %I64u\n\n",sizeof (BMPHEAD));
        printf("offset id = %I64u\n",offsetof (BMPHEAD,id));
        printf("offset filesize = %I64u\n",offsetof (BMPHEAD,filesize));
        printf("offset reserved = %I64u\n",offsetof (BMPHEAD,reserved));
        printf("offset headersize = %I64u\n",offsetof (BMPHEAD,headersize));
        printf("offset infoSize = %I64u\n",offsetof (BMPHEAD,infoSize));
        printf("offset width = %I64u\n",offsetof (BMPHEAD,width));
        printf("offset depth = %I64u\n",offsetof (BMPHEAD,depth));
        printf("offset biPlanes = %I64u\n",offsetof (BMPHEAD,biPlanes));
        printf("offset bits = %I64u\n",offsetof (BMPHEAD,bits));
        printf("offset biCompression = %I64u\n",offsetof (BMPHEAD,biCompression));
        printf("offset biSizeImage = %I64u\n",offsetof (BMPHEAD,biSizeImage));
        printf("offset biSizeImage = %I64u\n",offsetof (BMPHEAD,biSizeImage));
        printf("offset biXPelsPerMeter = %I64u\n",offsetof (BMPHEAD,biXPelsPerMeter));
        printf("offset biYPelsPerMeter = %I64u\n",offsetof (BMPHEAD,biYPelsPerMeter));
        printf("offset biClrUsed = %I64u\n",offsetof (BMPHEAD,biClrUsed));
        printf("offset biClrImportant = %I64u\n",offsetof (BMPHEAD,biClrImportant));
     
        return EXIT_SUCCESS;
    }
     
    ==>
    size BMPHEAD = 54
     
    offset id = 0
    offset filesize = 2
    offset reserved = 6
    offset headersize = 10
    offset infoSize = 14
    offset width = 18
    offset depth = 22
    offset biPlanes = 26
    offset bits = 28
    offset biCompression = 30
    offset biSizeImage = 34
    offset biSizeImage = 34
    offset biXPelsPerMeter = 38
    offset biYPelsPerMeter = 42
    offset biClrUsed = 46
    offset biClrImportant = 50
     
    ce qui est le resultat attendu pour une structure compactée.
    (si on ne compacte pas, on obtient :
     
    size BMPHEAD = 56
     
    offset id = 0
    offset filesize = 4
    offset reserved = 8
    offset headersize = 12
    offset infoSize = 16
    offset width = 20
    offset depth = 24
    offset biPlanes = 28
    offset bits = 30
    offset biCompression = 32
    offset biSizeImage = 36
    offset biSizeImage = 36
    offset biXPelsPerMeter = 40
    offset biYPelsPerMeter = 44
    offset biClrUsed = 48
    offset biClrImportant = 52
    pour Visual:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    #pragma pack(1)
     
    // le pragma n'agit que sur la 1ère définition de structure rencontrée !!
     
    typedef struct {
            ...
    } BMPHEAD;
    Si les cons volaient, il ferait nuit à midi.

  4. #4
    Membre habitué

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2010
    Messages
    80
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2010
    Messages : 80
    Points : 127
    Points
    127
    Par défaut
    Formidable !

    merci beaucoup !

    J'avais essayé de changer des int en short, mais pas les bons visiblement !

    [RESOLU]

  5. #5
    Expert confirmé

    Inscrit en
    Août 2006
    Messages
    3 942
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 3 942
    Points : 5 654
    Points
    5 654
    Par défaut
    Hoa,

    Ce n'était pas qu'un problème de type, s'y ajoutait l'alignement des champs, qui modifie l'offset des champs par rapport à ce qu'on prévoit "à la main", pour améliorer la vitesse d'accès.

    Par exemple, si on a un champ char, qui n'occupe qu'un octet, le champ suivant sera aligné, généralement à une adresse multiple de 4, ce qui fait que le champ char occupera de fait 4 octets.
    Si les cons volaient, il ferait nuit à midi.

  6. #6
    Membre éprouvé Avatar de orfix
    Homme Profil pro
    Inscrit en
    Avril 2007
    Messages
    707
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Maroc

    Informations professionnelles :
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Avril 2007
    Messages : 707
    Points : 1 132
    Points
    1 132
    Par défaut
    Il faut garder en tête que le standard ne précise pas les tailles des différents types...

    Pour ce qui est du problème d'alignement je préfère de loin écrire les champs un à un c'est plus portable (car pour être totalement portable il faudrait aussi régler le problème des tailles des types ainsi que celui de l'endianness).
    To start press any key. (reading screen) Where's the "any" key? I see Esc, Catarl, and Pig Up. There doesn't seem to be any "any" key. Wo! All this computer hacking is making me thirsty. I think I'll order a Tab. (presses TAB key). -- HOMER --

  7. #7
    Expert confirmé

    Inscrit en
    Août 2006
    Messages
    3 942
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 3 942
    Points : 5 654
    Points
    5 654
    Par défaut
    Sia,

    Le format bmp est Windows, donc processeurs Intel, pas trop besoin de s'occuper little ou big endian tant qu'on travaille avec les compilateurs pour Windows.

    Par contre, il serait effectivement utile d'utiliser des types précisant la taille de la variable (genre uint32_t, uint16_t ...), ça éviterait des problèmes quand les types "par défaut" des compilateurs changeront (on en reparle dans 20 ou 30 ans ?).
    Si les cons volaient, il ferait nuit à midi.

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

Discussions similaires

  1. [Débutant] insertion des images .bmp
    Par slaima15 dans le forum Interfaces Graphiques
    Réponses: 0
    Dernier message: 16/07/2010, 23h34
  2. Réponses: 18
    Dernier message: 25/10/2007, 15h08
  3. lire des images BMP
    Par b_electronique dans le forum MFC
    Réponses: 4
    Dernier message: 18/05/2006, 18h20
  4. [Image]Comment convertir des images bmp en jpg avec PHP ?
    Par amarcil dans le forum Bibliothèques et frameworks
    Réponses: 2
    Dernier message: 15/04/2006, 13h59
  5. [TP]Gestion des images bmp avec BMP.TPU
    Par Gabi dans le forum Turbo Pascal
    Réponses: 9
    Dernier message: 14/05/2004, 23h20

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