VB 2008 Une erreur générique s'est produite dans GDI+ [Résolu]

EISDCC 12 Messages postés mardi 3 août 2004Date d'inscription 14 mai 2013 Dernière intervention - 12 mai 2013 à 12:32 - Dernière réponse : EISDCC 12 Messages postés mardi 3 août 2004Date d'inscription 14 mai 2013 Dernière intervention
- 14 mai 2013 à 17:58
Bonjour à tous,
Je suis confronté au fameux message 'Une erreur générique s'est produite dans GDI+' lorsque je veux sauver une image issue d'un picturebox. Et je ne comprends pas pourquoi j'ai ce message d'erreur. Pour faire simple j'ai résumé mon problème en une toute petite procédure en la débarrassant de toutes les lignes qui ne concernent pas le problème:

Cette procédure plante sur le save:
Dim Fichier_lu As String = "E:\Dossier_Entree\Photo1.jpg"
Dim Fichier_ecrit As String = "E:\Dossier_Sortie\Photo2.jpg"
PictureBox1.Load(Fichier_lu)
PictureBox1.Image.Save(Fichier_ecrit, System.Drawing.Imaging.ImageFormat.Jpeg)


La même procédure avec un fichier Tif en entrée ne plante pas:
Dim Fichier_lu As String = "E:\Dossier_Entree\Image1.tif"
Dim Fichier_ecrit As String = "E:\Dossier_Sortie\Photo2.jpg"
PictureBox1.Load(Fichier_lu)
PictureBox1.Image.Save(Fichier_ecrit, System.Drawing.Imaging.ImageFormat.Jpeg)

Le plantage parait absurde! Quelqu'un pourrait-il m'expliquer pourquoi ce code ne fonctionne pas?

Le but de mon programme est de permettre à l'utilisateur de sélectionner une image (photo, plan, ...) et de la ranger dans un dossier client en la complétant éventuellement par des marques (flèches, texte, ...). S'il y a modification de l'image, il n'y a pas plantage!

Merci par avance
Afficher la suite 

Votre réponse

12 réponses

foliv57 423 Messages postés vendredi 17 novembre 2006Date d'inscription 15 juillet 2014 Dernière intervention - 13 mai 2013 à 16:23
+3
Utile
Bonjour,

Essayez ceci :
Dim Fichier_lu As String = "E:\Dossier_Entree\Photo1.jpg" 
Dim Fichier_ecrit As String = "E:\Dossier_Sortie\Photo2.jpg" 
PictureBox1.Image = Image.FromFile(Fichier_lu)
PictureBox1.Image.Save(Fichier_ecrit, System.Drawing.Imaging.ImageFormat.Jpeg)
Cette réponse vous a-t-elle aidé ?  
Commenter la réponse de foliv57
Utilisateur anonyme - 12 mai 2013 à 13:03
0
Utile
Salut,

Un picturebox ne doit se contenter que d'un affichage car le fichier utilisé reste ouvert. Travaille plutôt avec les flux et les objets de type Image ou Bitmap.
Dim monimage As Image
Using monstream As New IO.FileStream("monimage.jpg", IO.FileMode.Open)
    monimage = Image.FromStream(monstream)
End Using
picturebox1.image = monimage
monimage.Save("manouvelleimage.jpg", Drawing.Imaging.ImageFormat.Jpeg)


Je passe sur les gestions d'erreur à réaliser bien entendu.
Commenter la réponse de Utilisateur anonyme
EISDCC 12 Messages postés mardi 3 août 2004Date d'inscription 14 mai 2013 Dernière intervention - 12 mai 2013 à 15:20
0
Utile
Bonjour,
Merci pour la réponse rapide. Cependant, je ne comprends pas bien pourquoi ça fonctionne avec un fichier TIF en entrée et pas avec un JPG.
J'ai précisément utilisé la méthode load parce qu'en utilisant un Stream, celui-ci devait rester ouvert en permanence, et que cela ne m'arrange pas.
Pour résoudre mon problème, j'utilise une astuce stupide. Je remplace le premier pixel de l'image par un pixel de même couleur, et ensuite la méthode save fonctionne. De toutes façons, ou la documentation pour utiliser les picturebox est mal faite, ou ça pue le bug à plein nez. Je ne sais pas pourquoi, mais je pense que c'est un peu des deux!
Mais je reste toujours intéressé par une explication du phénomène.
Commenter la réponse de EISDCC
Utilisateur anonyme - 12 mai 2013 à 18:02
0
Utile
J'ai précisément utilisé la méthode load parce qu'en utilisant un Stream, celui-ci devait rester ouvert en permanence, et que cela ne m'arrange pas.

L'instruction End Using libère et referme le flux. Tu as testé cette solution ?
Commenter la réponse de Utilisateur anonyme
EISDCC 12 Messages postés mardi 3 août 2004Date d'inscription 14 mai 2013 Dernière intervention - 12 mai 2013 à 19:02
0
Utile
Ce code fonctionne de la même façon que le mien: même erreur avec un fichier JPG, pas d'erreur avec un fichier TIF.
Je pense que le problème ne vient pas d'une ressource verrouillée.
Pour moi (mais je peux me tromper) il y a des caractéristiques de l'image du fichier en entrée non mémorisées dans le cas d'un jpeg, mais bien renseignées dans le cas d'un tif. Le fait de travailler sur l'image par l'intermédiaire d'un graphics rétablit les paramètres manquants:

Dim img As Image = CType(PictureBox1.Image, Image)
Dim gr As Graphics
gr = Graphics.FromImage(img)
' manipulations.... gr.DrawRectangle , ...
PictureBox1.Image = img
gr.Dispose()

car après ces lignes de code, la méthode save fonctionne toujours.
Commenter la réponse de EISDCC
Utilisateur anonyme - 12 mai 2013 à 19:09
0
Utile
Il y a une explication ici.
Commenter la réponse de Utilisateur anonyme
EISDCC 12 Messages postés mardi 3 août 2004Date d'inscription 14 mai 2013 Dernière intervention - 13 mai 2013 à 07:38
0
Utile
Le problème exposé par ce lien est un peu différent, car il traite de plantage sur l'enregistrement de fichier tif multipage.
Dans mon cas le plantage se fait sur le save au format JPG d'un fichier déjà en JPG, sans aucune transformation.
Comme la commande de mon client était urgente, j'ai utilisé la petite astuce indiquée précédemment, mais j'avoue que j'aimerai comprendre...
Commenter la réponse de EISDCC
EISDCC 12 Messages postés mardi 3 août 2004Date d'inscription 14 mai 2013 Dernière intervention - 14 mai 2013 à 11:43
0
Utile
Cela fonctionne parfaitement
Merci!
Commenter la réponse de EISDCC
foliv57 423 Messages postés vendredi 17 novembre 2006Date d'inscription 15 juillet 2014 Dernière intervention - 14 mai 2013 à 11:56
0
Utile
Juste pour info à banana,

Le problème vient justement de la libération des ressources du flux.
La méthode "picturebox.Load" fait exactement l'action donnée dans votre exemple
Dim monimage As Image
Using monstream As New IO.FileStream("monimage.jpg", IO.FileMode.Open)
    monimage = Image.FromStream(monstream)
End Using
picturebox1.image = monimage
monimage.Save("manouvelleimage.jpg", Drawing.Imaging.ImageFormat.Jpeg)

Elle ouvre un Stream, fait un Image.FromStream est libère le flux avec un "End Using" avant d'affecter l'image au picturebox.

Malheureusement la méthode "Image.Save" génère justement l'erreur GDI+ si le flux est fermé (End Using). Donc votre exemple fonctionne si le Save est fait dans le Using
Dim monimage As Image
Using monstream As New IO.FileStream("monimage.jpg", IO.FileMode.Open)
    monimage = Image.FromStream(monstream)
    picturebox1.image = monimage
    monimage.Save("manouvelleimage.jpg", Drawing.Imaging.ImageFormat.Jpeg)
End Using

Par contre la méthode "Image.FromFile" n'accède pas au fichier de la même manière. Le problème était donc bien un problème de flux, mais du au fait qu'il est libéré.

La seul chose que je n'ai pas encore clairement identifiée, c'est pourquoi la méthode "Image.Save" fonctionne si la source est un tif et que le flux est libéré.
Commenter la réponse de foliv57
Utilisateur anonyme - 14 mai 2013 à 12:42
0
Utile
Très intéressant. On en apprend tous les jours. Je ne pensais pas que Save pouvait donner des résultats différents selon l'état du flux.
Merci foliv57
Commenter la réponse de Utilisateur anonyme
foliv57 423 Messages postés vendredi 17 novembre 2006Date d'inscription 15 juillet 2014 Dernière intervention - 14 mai 2013 à 14:52
0
Utile
Et pour conclure, dixit MSDN (comme quoi il ne fallait pas chercher bien loin).
Vous devez garder le flux ouvert pendant la durée de vie de Image.

Donc je fini avec un petit exemple pour les personnes qui auraient besoin de travailler sur l'image avec le flux fermé (exemple: modifier et enregistrer l'image avec le même chemin car Image.FromFile ne le permet pas vu qu'il garde un handle ouvert)
Dim img As Image

Using fs As New FileStream("D:\Dossier_Entree\Test.jpg", FileMode.Open, FileAccess.Read)
     'Chargement de l'image depuis le flux et création d'une copie déconnecté à 
     'l'aide de la classe Bitmap qui hérite de la classe Image
     img = New Bitmap(Image.FromStream(fs))
End Using 'Fermeture du flux

'Sauvegarde sans erreur GDI+
img.Save("D:\Dossier_Sortie\Test.jpg", Imaging.ImageFormat.Jpeg

Je dois avouer que ça ressemble plus à un tour de passe-passe qu'à une solution, mais ça dépanne.

D'ailleurs je suppose que l'objet Image peut sauvegarder soit à partir du flux original, soit à partir d'une table d'octets représentant une copie de l'originale. Ce qui expliquerai peut-être pourquoi cela fonction immédiatement avec les tif. Ce format est peut-être mis instantanément dans la table d'octets au chargement.
Ce transfert se fait surement aussi lors de la modification de l'image, d'ou le fait que la sauvegarde fonctionne si on passe par un objet Graphics et qu'on modifie l'originale.
Ce dernier paragraphe n'est que des suppositions basées sur le fait que la classe Image dispose d'un variable privée nommée "rawData" de type "Byte()" qui, sous certaine conditions, est utilisée dans la méthode Save à la place du handle original.
Commenter la réponse de foliv57
EISDCC 12 Messages postés mardi 3 août 2004Date d'inscription 14 mai 2013 Dernière intervention - 14 mai 2013 à 17:58
0
Utile
Merci pour ces précisions.
J'avais bien vu MSDN, mais je ne pouvais pas garder le flux ouvert, car cela verrouille la ressource, et le logiciel fonctionnant en réseau, cela bloquait d'autres utilisateurs sur certains traitements.
Encore merci à tous
Commenter la réponse de EISDCC

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.