[C#] Enregistrer une image en cours d'utilisation [Résolu]

SlyK1012 6 Messages postés mercredi 23 février 2011Date d'inscription 10 juin 2011 Dernière intervention - 6 juin 2011 à 13:52 - Dernière réponse : sebmafate 4947 Messages postés lundi 17 février 2003Date d'inscription 14 février 2014 Dernière intervention
- 10 juin 2011 à 16:04
Bonjour à tous !

J'ai un petit problème pour enregistrer une image bitmap sur le même nom et dans le même dossier que l'image d'origine.

Pour une meilleur explication, je crée un programme qui permet de faire de la stéganographie. J'ouvre une image bitmap, puis je stock du texte ou une image dans celle-ci.

A l'enregistrement, je n'arrive pas à enregistrer sur le même nom, le programme me dit que l'image est en cours d'utilisation. J'ai essayé de résoudre ce problème par plusieurs moyen, mais rien n'y fait

A la lecture de l'image source pour pouvoir la changer par la suite, j'ai ce code :
Bitmap ImgFile = new Bitmap(strFilePath);
Bitmap ImgTmp = (Bitmap)ImgFile.Clone();
ImgFile.Dispose();


J'ai essayer de le faire comme ceci pour fermer l'image et utiliser un clone de celle-ci. Mais ça ne marche pas


Est-ce que vous auriez une solution pour enregistrer une image sur le même nom que celle d'origine ?

Je vous laisse toute la partie du code qui pose problème :
    /// <summary>
    /// Inscrit dans l'image le texte donné en paramètre dans l'image donnée en paramètre
    /// </summary>
    /// Texte à inclure


    /// Chemin vers l'image


    public void IncludeText(String strFilePath, String strInclude)
    {
      // Crée une image depuis la class Bitmap
      Bitmap ImgFile = new Bitmap(strFilePath);
      Bitmap ImgTmp = (Bitmap)ImgFile.Clone();
      ImgFile.Dispose();

      // Taille maximum du texte possible
      Int32 intMaxSize = ((ImgTmp.Height - 1) * (ImgTmp.Width - 1)) / 8;

      // Teste si le texte est trop long, si oui, affiche un message d'erreur
      if (strInclude.Length > intMaxSize) 
      { 
        System.Windows.MessageBox.Show("Le texte écrit est trop long !", "Erreur", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Error);
        return;
      }

      // Teste si l'encodage de l'image est le bon, si non, affiche un message d'erreur
      if (ImgTmp.PixelFormat != PixelFormat.Format24bppRgb)
      {
        System.Windows.MessageBox.Show("Mauvais encodage de l'image !", "Erreur", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Error);
        return;
      }

      Int32 x;                              // Variable de boucle
      Byte byTemp = 0;                      // Variable temporaire
      Byte R = 0;                           // Couleur Rouge
      Byte G = 0;                           // Couleur Vert
      Byte B = 0;                           // Couleur Bleu
      Point ptCurrentPoint = Point.Empty;   // Position actuelle dans l'image
      Color coCurrentColor = Color.Empty;   // Couleur actuelle du pixel

      // Inscrit le carractère de fin
      strInclude += FIN;

      // Boucle pour inscrire le texte dans l'image
      for (x = 0; x < strInclude.Length; x++)
      {
        // Prend le premier caractère est le stock dans la variable temporaire
        byTemp = (Byte)strInclude[x];

        // Stock la position du pixel selon l'avancement de l'écriture
        ptCurrentPoint.X = x % ImgTmp.Width;
        ptCurrentPoint.Y = x / ImgTmp.Width;

        // Séléctionne le pixel au point X;Y
        coCurrentColor = ImgTmp.GetPixel(ptCurrentPoint.X, ptCurrentPoint.Y);

        // Change la couleur du pixel pour inscrire le carractère
        R = (Byte)(coCurrentColor.R & 248 | (byTemp & 7));
        G = (Byte)(coCurrentColor.G & 248 | (byTemp & 56) >> 3);
        B = (Byte)(coCurrentColor.B & 252 | (byTemp & 192) >> 6);

        // Enregistre le nouveau pixel
        ImgTmp.SetPixel(ptCurrentPoint.X, ptCurrentPoint.Y, Color.FromArgb(R, G, B));
      }

      // Enregistre l'image
      try { ImgTmp.Save(strFilePath); }
      catch
      {
        System.Windows.MessageBox.Show("Erreur lors de l'enregistrement de l'image !", "Erreur", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Error);
        return;
      }
    } // Fin IncludeText



Merci bien,
SlyK
Afficher la suite 

Votre réponse

9 réponses

Meilleure réponse
sebmafate 4947 Messages postés lundi 17 février 2003Date d'inscription 14 février 2014 Dernière intervention - 6 juin 2011 à 14:14
1
Merci
Bonjour,

ce n'est pas possible d'enregistrer une image en même temps qu'on la lit.
il faut utiliser une subterfuge !

avant d'ouvrir ton image, il faut en créer une copie temporaire... ensuite tu pourras l'enregistrer à la place de l'originale.


Sébastien FERRAND
Ingénieur Concepteur Senior
Microsoft Visual C# MVP 2004 - 2009
Blog Photo

Merci sebmafate 1

Avec quelques mots c'est encore mieux Ajouter un commentaire

Codes Sources a aidé 123 internautes ce mois-ci

Commenter la réponse de sebmafate
SlyK1012 6 Messages postés mercredi 23 février 2011Date d'inscription 10 juin 2011 Dernière intervention - 6 juin 2011 à 14:40
0
Merci
Re !

Merci bien pour ta réponse

Donc c'est bien ça, il n'y a pas de moyen sans passer par un fichier temporaire

Voici le code que j'utilise donc pour inscrire le texte, il marche mais il y a un autre problème décrit plus bas :
    /// <summary>
    /// Inscrit dans l'image le texte donné en paramètre dans l'image donnée en paramètre
    /// </summary>
    /// Texte à inclure


    /// Chemin vers l'image


    /// Chemin vers l'image temporaire


    public void IncludeText(String strFilePath, String strTmpPath, String strInclude)
    {
      // Supprime le fichier temporaire si il existe
      if (File.Exists(strTmpPath)) { File.Delete(strTmpPath); }

      // Copie l'image dans le répertoire temporaire
      File.Copy(strFilePath, strTmpPath);

      // Crée une image depuis la class Bitmap
      Bitmap ImgFile = new Bitmap(strTmpPath);

      // Taille maximum du texte possible
      Int32 intMaxSize = ((ImgFile.Height - 1) * (ImgFile.Width - 1)) / 8;

      // Teste si le texte est trop long, si oui, affiche un message d'erreur
      if (strInclude.Length > intMaxSize) 
      { 
        System.Windows.MessageBox.Show("Le texte écrit est trop long !", "Erreur", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Error);
        return;
      }

      // Teste si l'encodage de l'image est le bon, si non, affiche un message d'erreur
      if (ImgFile.PixelFormat != PixelFormat.Format24bppRgb)
      {
        System.Windows.MessageBox.Show("Mauvais encodage de l'image !", "Erreur", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Error);
        return;
      }

      Int32 x;                              // Variable de boucle
      Byte byTemp = 0;                      // Variable temporaire
      Byte R = 0;                           // Couleur Rouge
      Byte G = 0;                           // Couleur Vert
      Byte B = 0;                           // Couleur Bleu
      Point ptCurrentPoint = Point.Empty;   // Position actuelle dans l'image
      Color coCurrentColor = Color.Empty;   // Couleur actuelle du pixel

      // Inscrit le carractère de fin
      strInclude += FIN;

      // Boucle pour inscrire le texte dans l'image
      for (x = 0; x < strInclude.Length; x++)
      {
        // Prend le premier caractère est le stock dans la variable temporaire
        byTemp = (Byte)strInclude[x];

        // Stock la position du pixel selon l'avancement de l'écriture
        ptCurrentPoint.X = x % ImgFile.Width;
        ptCurrentPoint.Y = x / ImgFile.Width;

        // Séléctionne le pixel au point X;Y
        coCurrentColor = ImgFile.GetPixel(ptCurrentPoint.X, ptCurrentPoint.Y);

        // Change la couleur du pixel pour inscrire le carractère
        R = (Byte)(coCurrentColor.R & 248 | (byTemp & 7));
        G = (Byte)(coCurrentColor.G & 248 | (byTemp & 56) >> 3);
        B = (Byte)(coCurrentColor.B & 252 | (byTemp & 192) >> 6);

        // Enregistre le nouveau pixel
        ImgFile.SetPixel(ptCurrentPoint.X, ptCurrentPoint.Y, Color.FromArgb(R, G, B));
      }

      // Enregistre l'image
      try { ImgFile.Save(strFilePath); ImgFile.Dispose(); File.Delete(strTmpPath); }
      catch
      {
        System.Windows.MessageBox.Show("Erreur lors de l'enregistrement de l'image !", "Erreur", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Error);
        return;
      }
    } // Fin IncludeText


Après avoir fait ceci, le preview de mon image m'embête pour les même problème de droit, je dois donc crée deux fichier temporaire ?
Un pour la modification de l'image et un pour le preview ?

Sans le preview, l'inscription marche très bien.
Je précise que je code avec du WPF.


Merci bien,
SlyK
Commenter la réponse de SlyK1012
sebmafate 4947 Messages postés lundi 17 février 2003Date d'inscription 14 février 2014 Dernière intervention - 6 juin 2011 à 15:09
0
Merci
je te propose une "petite" modification :

/// <summary>
    /// Inscrit dans l'image le texte donné en paramètre dans l'image donnée en paramètre
    /// </summary>
    /// Texte à inclure


    /// Chemin vers l'image


    /// Chemin vers l'image temporaire


    public void IncludeText(String strFilePath, String strTmpPath, String strInclude)
    {
      // Supprime le fichier temporaire si il existe
      if (File.Exists(strTmpPath)) { File.Delete(strTmpPath); }

      // Copie l'image dans le répertoire temporaire
      File.Copy(strFilePath, strTmpPath);

      // Crée une image depuis la class Bitmap
      using(Bitmap ImgFile = new Bitmap(strTmpPath)) {

      // Taille maximum du texte possible
      Int32 intMaxSize = ((ImgFile.Height - 1) * (ImgFile.Width - 1)) / 8;

      // Teste si le texte est trop long, si oui, affiche un message d'erreur
      if (strInclude.Length > intMaxSize) 
      { 
        System.Windows.MessageBox.Show("Le texte écrit est trop long !", "Erreur", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Error);
        return;
      }

      // Teste si l'encodage de l'image est le bon, si non, affiche un message d'erreur
      if (ImgFile.PixelFormat != PixelFormat.Format24bppRgb)
      {
        System.Windows.MessageBox.Show("Mauvais encodage de l'image !", "Erreur", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Error);
        return;
      }

      Int32 x;                              // Variable de boucle
      Byte byTemp = 0;                      // Variable temporaire
      Byte R = 0;                           // Couleur Rouge
      Byte G = 0;                           // Couleur Vert
      Byte B = 0;                           // Couleur Bleu
      Point ptCurrentPoint = Point.Empty;   // Position actuelle dans l'image
      Color coCurrentColor = Color.Empty;   // Couleur actuelle du pixel

      // Inscrit le carractère de fin
      strInclude += FIN;

      // Boucle pour inscrire le texte dans l'image
      for (x = 0; x < strInclude.Length; x++)
      {
        // Prend le premier caractère est le stock dans la variable temporaire
        byTemp = (Byte)strInclude[x];

        // Stock la position du pixel selon l'avancement de l'écriture
        ptCurrentPoint.X = x % ImgFile.Width;
        ptCurrentPoint.Y = x / ImgFile.Width;

        // Séléctionne le pixel au point X;Y
        coCurrentColor = ImgFile.GetPixel(ptCurrentPoint.X, ptCurrentPoint.Y);

        // Change la couleur du pixel pour inscrire le carractère
        R = (Byte)(coCurrentColor.R & 248 | (byTemp & 7));
        G = (Byte)(coCurrentColor.G & 248 | (byTemp & 56) >> 3);
        B = (Byte)(coCurrentColor.B & 252 | (byTemp & 192) >> 6);

        // Enregistre le nouveau pixel
        ImgFile.SetPixel(ptCurrentPoint.X, ptCurrentPoint.Y, Color.FromArgb(R, G, B));
      }

      // Enregistre l'image
      try { 
             ImgFile.Save(strFilePath); 
             ImgFile.Dispose(); 
             File.Delete(strTmpPath); }
      catch
      {
        System.Windows.MessageBox.Show("Erreur lors de l'enregistrement de l'image !", "Erreur", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Error);
        return;
      }
      }
    } // Fin IncludeText



Ne jamais oublier le using() lorsque l'on travaille avec des images.

Sébastien FERRAND
Ingénieur Concepteur Senior
Microsoft Visual C# MVP 2004 - 2009
Blog Photo
Commenter la réponse de sebmafate
SlyK1012 6 Messages postés mercredi 23 février 2011Date d'inscription 10 juin 2011 Dernière intervention - 6 juin 2011 à 15:27
0
Merci
Re !

Effectivement, ça marche pour la première inscription.

Par contre si je veux réinscrire la même image directement, ça ne marche pas.

Il me sort cette erreur.
Interception de System.Runtime.InteropServices.ExternalException
  Message=Une erreur générique s'est produite dans GDI+.
  Source=System.Drawing
  ErrorCode=-2147467259
  StackTrace:
       à System.Drawing.Image.Save(String filename, ImageCodecInfo encoder, EncoderParameters encoderParams)
       à System.Drawing.Image.Save(String filename, ImageFormat format)
       à System.Drawing.Image.Save(String filename)
       à HideMe.BitmapFile.IncludeText(String strFilePath, String strTmpPath, String strInclude)
  InnerException:


J'ai fais quelques recherches sur le numéro de l'erreur (2147467259) mais sans succès.


Merci bien,
SlyK
Commenter la réponse de SlyK1012
sebmafate 4947 Messages postés lundi 17 février 2003Date d'inscription 14 février 2014 Dernière intervention - 6 juin 2011 à 16:46
0
Merci
à quelle moment intervient la seconde erreur ?


Sébastien FERRAND
Ingénieur Concepteur Senior
Microsoft Visual C# MVP 2004 - 2009
Blog Photo
Commenter la réponse de sebmafate
SlyK1012 6 Messages postés mercredi 23 février 2011Date d'inscription 10 juin 2011 Dernière intervention - 7 juin 2011 à 13:18
0
Merci
Re !

L'erreur arrive à la sauvegarde de l'image.
        try { ImgFile.Save(strFilePath); ImgFile.Dispose(); File.Delete(strTmpPath); }
        catch
        {
          System.Windows.MessageBox.Show("Erreur lors de l'enregistrement de l'image !", "Erreur", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Error);
          return;
        }


Le truc qui est bizarre, c'est que l'enregistrement marche une fois, par la suite, il ne marche plus. Si je prend le focus sur une autre fenêtre, par exemple l'explorer, et que je reviens sur mon programme, la l'écriture marche

Je ne sais pas pourquoi mais c'est le cas


Merci bien,
SlyK
Commenter la réponse de SlyK1012
SlyK1012 6 Messages postés mercredi 23 février 2011Date d'inscription 10 juin 2011 Dernière intervention - 7 juin 2011 à 13:25
0
Merci
Maintenant, j'arrive à inscrire seulement 1 fois sur 14.

Tout les 14 cliques sur le bouton "Écrire", l'inscription marche
Commenter la réponse de SlyK1012
SlyK1012 6 Messages postés mercredi 23 février 2011Date d'inscription 10 juin 2011 Dernière intervention - 10 juin 2011 à 08:34
0
Merci
Re !

J'ai trouvé la solution, enfaite il me manquait juste un dispose() à un endroit

Merci quand même.


Cdlt,
SlyK
Commenter la réponse de SlyK1012
sebmafate 4947 Messages postés lundi 17 février 2003Date d'inscription 14 février 2014 Dernière intervention - 10 juin 2011 à 16:04
0
Merci
désolé... j'avais zappé ton thread...


Sébastien FERRAND
Ingénieur Concepteur Senior
Microsoft Visual C# MVP 2004 - 2009
Blog Photo
Commenter la réponse de sebmafate

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.