Ecriture d'un fichier BMP "à l'ancienne"

MaxSoldier Messages postés 289 Date d'inscription dimanche 10 août 2003 Statut Membre Dernière intervention 28 février 2009 - 4 déc. 2007 à 11:21
MaxSoldier Messages postés 289 Date d'inscription dimanche 10 août 2003 Statut Membre Dernière intervention 28 février 2009 - 5 déc. 2007 à 18:14
Salut à tous ! N'ayant pas pus résoudre mon prblème seul, je m'en réfère à vous !
Je m'explique, je cherche à écrire un fichier BMP à l'ancienne, c'est à dire sans aucune librairie.
Je suis presque au bout de mon programme mais lorsque je lui demande de dessiner un pixel, il dessine tout les ligne horizontale. A quoi est-ce du ?

Voici mon code :


<hr />

#include
#include <stdlib.h>
#include <windows.h>
#include <stdio.h>
#include <math.h>// Structs
typedef struct{
 unsigned char Red;
 unsigned char Green;
 unsigned char Blue;
}Color;

typedef struct
{
 Color* ImgArray;

 char* Filename;
 int iWidth;
 int iHeight;

 FILE* FS;
}Picture;

void InitBmpFile(FILE *FS,unsigned int iWidth,unsigned int iHeight);

Picture BuildPicture(char* Filename,unsigned int iWidth,unsigned int iHeight)
{
 Picture TmpPic;

 TmpPic.Filename = Filename;
 TmpPic.FS = fopen(Filename,"wb");

 TmpPic.iWidth = iWidth;
 TmpPic.iHeight = iHeight;

 TmpPic.ImgArray = (Color*)malloc((sizeof(Color)*iWidth) + (sizeof(Color)*iHeight));
 
 InitBmpFile(TmpPic.FS,iWidth,iHeight);

 return TmpPic;
}

void InitBmpFile(FILE *FS,unsigned int iWidth,unsigned int iHeight)
{
 const char *BMFormat = "BM";
 unsigned int BMPHeaderLenght = (iWidth*iHeight*3) + 54;
 unsigned int ReservedBit = 0;
 unsigned int DataOffset = 54;

 unsigned int DataHeaderLenght = 40;
 unsigned short Planes = 1;
 unsigned short BPP = 24;

 unsigned int Compression = 0;

 unsigned int ImageSize = 0;//(iWidth*iHeight*3);

 unsigned int ResX = 0;
 unsigned int Resy = 0;

 unsigned int ColorUsed =0;
 unsigned int ColorImportant = 0;

 fwrite(BMFormat,1,2,FS);
 fwrite(&BMPHeaderLenght,4,1,FS);
 fwrite(&ReservedBit,4,1,FS);
 fwrite(&DataOffset,4,1,FS);
 
 fwrite(&DataHeaderLenght,4,1,FS);
 fwrite(&iWidth,4,1,FS);
 fwrite(&iHeight,4,1,FS);

 fwrite(&Planes,2,1,FS);
 fwrite(&BPP,2,1,FS);

 fwrite(&Compression,4,1,FS);

 fwrite(&ImageSize,4,1,FS);
 fwrite(&ResX,4,1,FS);
 fwrite(&Resy,4,1,FS);

 fwrite(&ColorUsed,4,1,FS);
 fwrite(&ColorImportant,4,1,FS);
}

void Save(Picture Pic)
{
 for(int Y=Pic.iHeight;Y>0;Y--)
 {
  for(int X=0;X}

void WritePixel(Picture Pic,int X,int Y,Color PixelColor)
{
 Pic.ImgArray[X,Y] = PixelColor;
}

Color GetColor(unsigned char Red,unsigned unsigned Green,unsigned unsigned Blue)
{
 Color TmpColor;

 TmpColor.Red = Red;
 TmpColor.Green = Green;
 TmpColor.Blue = Blue;

 return TmpColor;
}
void Close(Picture Pic)
{
 fclose(Pic.FS); 
}

<hr />
Pour l'utiliser :

<hr />#include "stdafx.h"
#include "BitmapWriterLib.h"

int main(int argc, char* argv[])
{
 Picture MyPic= BuildPicture("\\\\galileo\\gaudin.m\\Mes documents\\TestFile.bmp",800,600);
 

 for(int X=0;X<MyPic.iWidth;X++)
 {
  for(int Y=0;Y<MyPic.iHeight;Y++)
  {
   WritePixel(MyPic,X,Y,GetColor(255,255,255));
  }
 }

 WritePixel(MyPic,400,300,GetColor(255,0,0));

 Save(MyPic);
 Close(MyPic);

 return 0;
}

<hr />
MLerci d'avance !
Tchou !
-=Ar$£nik=-

6 réponses

Pistol_Pete Messages postés 1053 Date d'inscription samedi 2 octobre 2004 Statut Membre Dernière intervention 9 juillet 2013 7
4 déc. 2007 à 11:49
Salut

Dans ta fonction  GetColor, tu retourne une variable local, tu ne peux donc pas etre sur que ta variable en sorti de fonction est correcte.
Je ne sais pas si ton problème vient de là, mais c'est important à corriger.

A+
Mon site internet : http://pistol.petesampras.free.fr
0
Pistol_Pete Messages postés 1053 Date d'inscription samedi 2 octobre 2004 Statut Membre Dernière intervention 9 juillet 2013 7
4 déc. 2007 à 13:16
Re
Ya quand meme pas mal de chose à revoir:
L'allocation dynamique de  TmpPic.ImgArray n'est pas correct : Tu alloues
(sizeof(Color)*iWidth) + (sizeof(Color)*iHeight) pour une image 600 par 800 ca fait un tableau de 1400 places alors qu'il y a 480 000 pixels !!!
L'accès à ton tableau est aussi incorrecte Pic.ImgArray[X,Y] jamais vu cette syntaxe, j'arrive meme pas à comprendre pourquoi ca compile sans erreur.
Pour accéder au pixel X,Y, il faut un truc du genre: [X+Y*Width]

Je pense que faire une classe serait plus simple ici.

A+
Mon site internet : http://pistol.petesampras.free.fr
0
Pistol_Pete Messages postés 1053 Date d'inscription samedi 2 octobre 2004 Statut Membre Dernière intervention 9 juillet 2013 7
4 déc. 2007 à 13:28
Voila une version qui marche:

#include
#include <stdlib.h>
#include <windows.h>
#include <stdio.h>
#include <math.h>

using namespace std;

// Structs
typedef struct{
 unsigned char Red;
 unsigned char Green;
 unsigned char Blue;
}Color;

typedef struct
{
 Color* ImgArray;

 char* Filename;
 int iWidth;
 int iHeight;

 FILE* FS;
}Picture;

void InitBmpFile(FILE *FS,unsigned int iWidth,unsigned int iHeight);

Picture BuildPicture(char* Filename,unsigned int iWidth,unsigned int iHeight)
{
 Picture TmpPic;

 TmpPic.Filename = Filename;
 TmpPic.FS = fopen(Filename,"wb");

 TmpPic.iWidth = iWidth;
 TmpPic.iHeight = iHeight;

 TmpPic.ImgArray = (Color*)malloc((sizeof(Color)*iWidth * iHeight));
 
 InitBmpFile(TmpPic.FS,iWidth,iHeight);

 return TmpPic;
}

void InitBmpFile(FILE *FS,unsigned int iWidth,unsigned int iHeight)
{
 const char *BMFormat = "BM";
 unsigned int BMPHeaderLenght = (iWidth*iHeight*3) + 54;
 unsigned int ReservedBit = 0;
 unsigned int DataOffset = 54;

 unsigned int DataHeaderLenght = 40;
 unsigned short Planes = 1;
 unsigned short BPP = 24;

 unsigned int Compression = 0;

 unsigned int ImageSize = 0;//(iWidth*iHeight*3);

 unsigned int ResX = 0;
 unsigned int Resy = 0;

 unsigned int ColorUsed =0;
 unsigned int ColorImportant = 0;

 fwrite(BMFormat,1,2,FS);
 fwrite(&BMPHeaderLenght,4,1,FS);
 fwrite(&ReservedBit,4,1,FS);
 fwrite(&DataOffset,4,1,FS);
 
 fwrite(&DataHeaderLenght,4,1,FS);
 fwrite(&iWidth,4,1,FS);
 fwrite(&iHeight,4,1,FS);

 fwrite(&Planes,2,1,FS);
 fwrite(&BPP,2,1,FS);

 fwrite(&Compression,4,1,FS);

 fwrite(&ImageSize,4,1,FS);
 fwrite(&ResX,4,1,FS);
 fwrite(&Resy,4,1,FS);

 fwrite(&ColorUsed,4,1,FS);
 fwrite(&ColorImportant,4,1,FS);
}

void Save(Picture Pic)
{
   
 for(int Y=Pic.iHeight-1;Y>=0;Y--)
 {
  for(int X=0;XA+
Mon site internet : http://pistol.petesampras.free.fr
0
cs_juju12 Messages postés 966 Date d'inscription samedi 3 avril 2004 Statut Membre Dernière intervention 4 mars 2010 4
4 déc. 2007 à 17:44
Pas regardé en détail mais il me semble que vous oubliez un truc : dans le codage bitmap chaque rangée doit être un multiple de 4 octets, peu importe la résolution en couleur. Dans le cas du test (800*600) c'est OK puisque 800 divisible par 4, par contre pour une image quelconque (essayez 799*600 par exemple ca devrait pas marcher) faut compléter chaque ligne avec des zéros.
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
Pistol_Pete Messages postés 1053 Date d'inscription samedi 2 octobre 2004 Statut Membre Dernière intervention 9 juillet 2013 7
5 déc. 2007 à 10:46
Oui tu as tout à faire raison Juju, on ne peut pas faire des images quelconques avec cet algo.

A+
Mon site internet : http://pistol.petesampras.free.fr
0
MaxSoldier Messages postés 289 Date d'inscription dimanche 10 août 2003 Statut Membre Dernière intervention 28 février 2009 2
5 déc. 2007 à 18:14
Salut à tous ! Tout d'abord, merci pour toutes ces réponses ! Je vais essayer de vous répondre un par un en expliquant le pourquoi du comment :-p

Pistol_Pete : Je débute en programmation C++, je viens du C# d'ou une structure de code peut être un peu étrange, j'ai appris sur le tas, au fil des erreur de compilation... Je vais essayé de corriger ça

Juju : Je sais mais ce programme étant quasiment un programme de test, j'ai essayé de pas trop me compliqué la vie pour les 0 à la fin d'une ligne non divisible par 4. Quant au 4 composante, j'ai lu partout qu'il n'en fallait que 3, dans l'ordre, bleu vert rouge ( Little-endien)

Merci à tous, je vais pouvoir avancer grâce à vous !
-=Ar$£nik=-
0
Rejoignez-nous