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++Builder Discussion :

Tester si un fichier BMP est correct [Débutant]


Sujet :

C++Builder

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Février 2007
    Messages
    164
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 164
    Points : 85
    Points
    85
    Par défaut Tester si un fichier BMP est correct
    Bonjour,

    J'aimerais savoir s'il existe en C++ Builder une méthode permettant de tester si un fichier BMP est correctement formaté ? (en gros, est-ce qu'un fichier BMP est bien un BMP, mais pas un fichier renommé en .bmp par exemple) ou est-ce que nous devons utiliser l'API Windows, style avec LoadImage() ou LoadBitmap()?

    Merci,

  2. #2
    Membre averti

    Profil pro
    Inscrit en
    Janvier 2003
    Messages
    288
    Détails du profil
    Informations personnelles :
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations forums :
    Inscription : Janvier 2003
    Messages : 288
    Points : 334
    Points
    334
    Par défaut
    Bien entendu il est possible d'utiliser les API et en cas d'échec du chargement en déduire que le BMP est mal formaté. TBitmap est bien écrit il n'y a pas besoin de lui substituer le SDK pour ça.
    Tout dépend du contexte dans lequel tu fais ça:
    - est-ce que tu veux juste savoir quels sont les BMP mal formatés ?
    - est-ce que tu veux connaitre le format des images réel de ces images ?
    - est-ce que mal formé indique uniquement une conversion de format ou de possibles erreurs aux niveau des données

    Quoi qu'il en soit à part avoir la liste des images non chargées, pour savoir tout le reste il faut descendre plus bas que ce qu les API prennent généralement en charge (un loader à pour but de charger une image pas de faire un rapport complet).

    A présent pour détecter rapidement si une image est un Bitmap il faut de lire le header du bitmap (avec fopen ou ReadFile). La technique consiste à lire les 2 premiers caractères qui sont 'BM' pour un bitmap. Si ce n'est pas le cas on arrête là, sinon on lit la suite du header (mais attention il y a plusieurs formats, 2 je crois). Mais dans ton cas il peut suffire de lire 'BM', car si ce n'est pas 'BM' c'est que ce n'est pas un bitmap n'est-ce pas ?
    Pour un JPEG c'est pareil (identifiant + header).
    Pour un PNG aussi.

    Il y a pas de code un peu partout pour lire un BMP. Tu trouveras facilement.
    Le Top n'est pas forcément dans les librairies les plus connues comme ImageMagick car là le code est plutôt complexe. CXImage est pas mal.

  3. #3
    Membre régulier
    Profil pro
    Inscrit en
    Février 2007
    Messages
    164
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 164
    Points : 85
    Points
    85
    Par défaut
    ok merci yarp pour ton aide, effectivement, je veux faire une méthode qui liste les fichiers qui ne sont pas des BMP dans un répertoire donné; donc la solution de lire le "header" me suffira.
    Je regarde tout ça et encore merci

  4. #4
    Membre régulier
    Profil pro
    Inscrit en
    Février 2007
    Messages
    164
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 164
    Points : 85
    Points
    85
    Par défaut
    Ok, merci pour le tuyau, j'ai implémenté le code suivant qui fonctionne :
    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
    bool __stdcall isBMPFile(String sFile)
    {
    	FILE *pFile = NULL;
    	long lSize;
    	char *buffer = NULL;
    	AnsiString sResultat = "";
    	size_t result;
    	bool bResultat = false;
    	// lecture binaire du fichier ...
    	pFile = fopen (static_cast<AnsiString>(sFile).c_str(), "rb");
    	if (pFile == NULL)
    	{
    		ShowMessage("The file does not exist");
    		return bResultat ;
    	}
    	// Taille du fichier
    	fseek (pFile , 0 , SEEK_END);
    	lSize = ftell (pFile);
    	rewind (pFile);
    	// Allocation mémoire ...
    	buffer = (char*) malloc (sizeof(char) * lSize);
    	if (buffer == NULL)
    	{
    		ShowMessage("A memory error occured");
    		return bResultat ;
    	}
    	// Copie du fichier dans le buffer ...
    	result = fread (buffer, 1, lSize, pFile);
    	if (result != lSize)
    	{
    		ShowMessage("Reading file error");
    		return bResultat ;
    	}
    	sResultat = buffer;
    	// http://fr.wikipedia.org/wiki/Windows_bitmap
    	if (sResultat.SubString(0,2).UpperCase() == "BM")
    		bResultat = true;
    	return bResultat ;
    }

  5. #5
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 447
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 447
    Points : 24 844
    Points
    24 844
    Par défaut
    Tu as vraiment besoin de lire tout le fichier juste pour lire si ça commence par BM ?
    Dommage de ne pas avoir suivi le conseil de yarp en ne lisant que le header !

    Tu pourrais éliminer sResultat pour réduire la conso mémoire et CPU

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    bResultat = ((lSize > 2) && (UpCase(buffer[0]) == 'B') && (UpCase(buffer[1]) == 'M')
    Sinon, pourquoi ne pas utiliser un TFileStream cela éviterait le cast en AnsiString en utilisant le TFileName (Ansi sous 2007, Wide sous 2009)

    Tu peux t'appuyer sur la VCL :

    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
    bool __stdcall isBMPFile(const String sFileName, int *ErrorCode = NULL)
    {
      bool Result = false;
      if (ErrorCode) *ErrorCode = 0;
     
      try
      {
        TBitmap* BMP = new TBitmap();
        try
        {
          BMP->LoadFromFile(sFileName);
          Result = true;
        }
        __finally
        {
          delete BMP;
        }	
      }
      catch(const EInvalidGraphic &eig)
      {
        if (ErrorCode) *ErrorCode = -3; // not BM or Empty
      }
      catch(const EFOpenError &efoe)
      {
        if (ErrorCode) *ErrorCode = -2; // "The file does not exist" 
      }
      catch(const Exception &e)
      {
        if (ErrorCode) *ErrorCode = -1; // "A memory error occured" ou "Reading file error"
      }
     
      return Result;
    }
    ou en s'inspirant du ReadStream du TBitmap

    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
    bool __stdcall isBMPFile(const String sFileName, int *ErrorCode = NULL)
    {
      bool Result = false;
      if (ErrorCode) *ErrorCode = 0;
     
      try
      {
        TFileStream* Stream = new TFileStream(sFileName, fmOpenRead);
        try
        {
          if (Stream->Size > 0)
          {
            TBitmapFileHeader Bmf;
            Stream->Read((BYTE*)&Bmf, sizeof(Bmf));
            if (Bmf.bfType == 0x4D42) // BM en Hexa, voir TBitmap.ReadStream dans Graphics.pas
             Result = true; 
           else
             if (ErrorCode) *ErrorCode = -3; // not BM  
         }      
         else
           if (ErrorCode) *ErrorCode = -4; // Empty !
        }
        __finally
        {
          delete Stream;
        }
      }
      catch(const EFOpenError &efoe)
      {
        if (ErrorCode) *ErrorCode = -2; // "The file does not exist" 
      }
      catch(const Exception &e)
      {
        if (ErrorCode) *ErrorCode = -1; // "A memory error occured" ou "Reading file error"
      }  
      return Result;
    }
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  6. #6
    Membre averti

    Profil pro
    Inscrit en
    Janvier 2003
    Messages
    288
    Détails du profil
    Informations personnelles :
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations forums :
    Inscription : Janvier 2003
    Messages : 288
    Points : 334
    Points
    334
    Par défaut
    Tu as raison Shai le mieux est de regarder dans le source de la VCL.

    En suivant le lien donné par Mercusyo sur la page Wikipédia du BMP je viens de me rappeler qu'on nomme ces codes identifiant les formats de fichier: "magic number".
    Donc juste pour info, ça peut servir pour un google search.

  7. #7
    Membre régulier
    Profil pro
    Inscrit en
    Février 2007
    Messages
    164
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 164
    Points : 85
    Points
    85
    Par défaut
    Ok merci à vous pour ces précisions, j'ai adapté mon code dans ce sens.

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

Discussions similaires

  1. Tester si un fichier excel est déjà ouvert
    Par richard038 dans le forum Delphi
    Réponses: 3
    Dernier message: 08/10/2006, 14h01
  2. [VB6] (Pilote Isam) Tester si un fichier excel est ouvert
    Par Requin15 dans le forum VB 6 et antérieur
    Réponses: 30
    Dernier message: 20/03/2006, 17h57
  3. Tester que le fichier n'est pas un fichier binaire
    Par fedfil dans le forum Entrée/Sortie
    Réponses: 2
    Dernier message: 21/10/2005, 17h29
  4. [XML]Comment tester que mon fichier XML est comme ceci?
    Par Devil666 dans le forum XML/XSL et SOAP
    Réponses: 2
    Dernier message: 02/06/2005, 13h41
  5. Tester si un fichier X est ouvert
    Par James64 dans le forum API, COM et SDKs
    Réponses: 5
    Dernier message: 06/10/2004, 15h48

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