Une erreur générique s'est produite dans GDI+, image JPEG à MemoryStream

Cela semble être un peu une erreur infâme sur le web. Tant et si bien que je n'ai pas pu trouver de réponse à mon problème car mon scénario ne correspond pas. Une exception se produit lorsque je sauvegarde l'image dans le flux.

étrangement cela fonctionne parfaitement avec un png mais donne l'erreur ci-dessus avec jpg et gif qui est assez confuse.

problème le plus similaire là-bas se rapportent à enregistrer des images pour les fichiers sans permissions. Ironiquement, le la solution est d'utiliser un flux de mémoire comme je le fais....

public static byte[] ConvertImageToByteArray(Image imageToConvert)
{
    using (var ms = new MemoryStream())
    {
        ImageFormat format;
        switch (imageToConvert.MimeType())
        {
            case "image/png":
                format = ImageFormat.Png;
                break;
            case "image/gif":
                format = ImageFormat.Gif;
                break;
            default:
                format = ImageFormat.Jpeg;
                break;
        }

        imageToConvert.Save(ms, format);
        return ms.ToArray();
    }
}

plus de détails sur l'exception. La raison pour laquelle cela provoque tant de problèmes est le manque d'explication :(

System.Runtime.InteropServices.ExternalException was unhandled by user code
Message="A generic error occurred in GDI+."
Source="System.Drawing"
ErrorCode=-2147467259
StackTrace:
   at System.Drawing.Image.Save(Stream stream, ImageCodecInfo encoder, EncoderParameters    encoderParams)
   at System.Drawing.Image.Save(Stream stream, ImageFormat format)
   at Caldoo.Infrastructure.PhotoEditor.ConvertImageToByteArray(Image imageToConvert) in C:UsersIanSVNCaldooCaldoo.CoordinatorPhotoEditor.cs:line 139
   at Caldoo.Web.Controllers.PictureController.Croppable() in C:UsersIanSVNCaldooCaldoo.WebControllersPictureController.cs:line 132
   at lambda_method(ExecutionScope , ControllerBase , Object[] )
   at System.Web.Mvc.ActionMethodDispatcher.Execute(ControllerBase controller, Object[] parameters)
   at System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary`2 parameters)
   at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary`2 parameters)
   at System.Web.Mvc.ControllerActionInvoker.<>c__DisplayClassa.<InvokeActionMethodWithFilters>b__7()
   at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func`1 continuation)
 InnerException: 

OK choses que j'ai essayé jusqu'à présent.

  1. Cloner l'image et travailler dessus.
  2. récupérant l'encodeur pour ce MIME passant celui avec le paramètre de qualité jpeg.
281
demandé sur Cœur 2009-06-27 19:40:29

28 réponses

OK je semble avoir trouvé la cause juste par pur hasard et ce n'est rien de mal avec cette méthode particulière, il est plus loin dans la pile d'appels.

plus tôt je redimensionne l'image et dans le cadre de cette méthode je rends l'objet redimensionné comme suit. J'ai inséré deux appels à la méthode ci-dessus et l'enregistrer dans un fichier.

// At this point the new bitmap has no MimeType
// Need to output to memory stream
using (var m = new MemoryStream())
{
       dst.Save(m, format);

       var img = Image.FromStream(m);

       //TEST
       img.Save("C:\test.jpg");
       var bytes = PhotoEditor.ConvertImageToByteArray(img);


       return img;
 }

Il semble que le flux de mémoire que l'objet a été créé sur a être ouvert au moment où l'objet est enregistré. Je ne suis pas sûr pourquoi. Est-ce que quelqu'un peut m'éclairer et me dire comment je peux m'en sortir?

je reviens seulement d'un flux parce qu'après avoir utilisé le code de redimensionnement similaire à ce le fichier de destination a un type mime inconnu (img.RawFormat.Guid) et Id comme le type Mime pour être correct sur tous les objets image car il rend dur écrire le code de manipulation Générique autrement.

EDIT

ce n'est pas venu dans ma recherche initiale mais voici la réponse de Jon Skeet

161
répondu madcapnmckay 2017-05-23 12:10:44

si vous obtenez cette erreur , alors je peux dire que votre application n'a pas de permission d'écriture sur un répertoire.

par exemple, si vous essayez de sauver l'Image du flux de mémoire au système de fichiers , vous pouvez obtenir cette erreur.

S'il vous plaît Si vous utilisez XP, assurez-vous d'ajouter la permission d'écriture pour le compte aspnet dans ce dossier.

Si vous utilisez windows server (2003,2008) ou Vista, assurez-vous qui ajoutent la permission d'écriture pour le compte de service réseau.

J'espère que ça aidera quelqu'un.

113
répondu Savindra 2011-09-15 06:06:07

je vais ajouter cette cause de l'erreur aussi bien dans l'espoir qu'il aide un futur voyageur internet. :)

GDI+ limite la hauteur maximale d'une image à 65500

nous faisons quelques redimensionnement d'image de base, mais en redimensionnement nous essayons de maintenir le rapport d'aspect. Nous avons un gars de QA qui est un peu trop bon à ce travail; il a décidé de tester cela avec une photo d'un pixel de large qui était de 480 pixels de haut. Lorsque l'image a été ajustée pour répondre à nos dimensions, la hauteur était au nord de 68 000 pixels et notre application a explosé avec A generic error occurred in GDI+ .

vous pouvez vérifier vous-même avec test:

  int width = 480;
  var height = UInt16.MaxValue - 36; //succeeds at 65499, 65500
  try
  {
    while(true)
    {
      var image = new Bitmap(width, height);
      using(MemoryStream ms = new MemoryStream())
      {
        //error will throw from here
        image.Save(ms, ImageFormat.Jpeg);
      }
      height += 1;
    }
  }
  catch(Exception ex)
  {
    //explodes at 65501 with "A generic error occurred in GDI+."
  }

c'est dommage qu'il n'y ait pas un amical .net ArgumentException jeté dans le constructeur de Bitmap .

45
répondu Fred 2017-01-18 18:14:35

cet article explique en détail ce qui se passe exactement: bitmap and Image constructor dependencies

en bref, pour une durée de vie d'un Image construit à partir d'un flux , le flux ne doit pas être détruit.

donc, au lieu de

using (var strm = new ... )  {
    myImage = Image.FromStream(strm);
}

essayez cette

Stream imageStream;
...

    imageStream = new ...;
    myImage = Image.FromStream(strm);

et fermer imageStream au formulaire fermer ou fermer la page web.

34
répondu Ivan Mesic 2010-12-19 23:38:05

vous obtiendrez aussi cette exception si vous essayez de sauvegarder sur un chemin invalide ou s'il y a un problème de permissions.

si vous n'êtes pas sûr à 100% que le chemin du fichier est disponible et que les permissions sont correctes, alors essayez d'écrire a dans un fichier texte. Cela ne prend que quelques secondes pour écarter ce qui serait une solution très simple.

var img = System.Drawing.Image.FromStream(incomingStream);

// img.Save(path);
System.IO.File.WriteAllText(path, "Testing valid path & permissions.");

Et n'oubliez pas de nettoyer votre fichier.

25
répondu Kirk Broadhurst 2011-11-09 01:06:52

Enregistrer l'image bitmap variable

using (var ms = new MemoryStream())
{
    Bitmap bmp = new Bitmap(imageToConvert);
    bmp.Save(ms, format);
    return ms.ToArray();
}
14
répondu Amir Atashin 2012-10-26 08:59:52

j'ai trouvé que si l'un des dossiers parent où je sauvais le dossier avait un espace de fuite alors GDI+ lancerait l'exception Générique.

en d'autres termes, si j'ai essayé de sauver à "C:\Documents and Settings\myusername\Local Settings\Temp\ABC DEF M1 Trended Values \Images\picture.png " puis il a jeté l'exception Générique.

mon nom de dossier était généré à partir d'un nom de fichier qui s'est avéré avoir un espace arrière donc il était facile de .Trim() et passer à la suite.

13
répondu Igilima 2013-06-24 13:37:39

C'est une extension / qualification de Fred réponse qui a déclaré: "GDI limite la hauteur d'une image à 65534". Nous avons rencontré ce problème avec L'une de nos applications.net, et après avoir vu le post, notre équipe d'impartition a levé les mains en l'air et a dit qu'elle ne pourrait pas régler le problème sans changements majeurs.

basé sur mes tests, il est possible de créer / manipuler des images avec une hauteur supérieure à 65534, mais le problème se pose lors de l'économie à un flux ou le fichier dans certains FORMATS . Dans le code suivant, le T. Save () appel de méthode lance notre ami l'exception Générique quand la hauteur du pixel est 65501 pour moi. Pour des raisons de curiosité, j'ai répété le test pour la largeur, et la même limite appliquée à l'économie.

    for (int i = 65498; i <= 100000; i++)
    {
        using (Bitmap t = new Bitmap(800, i))
        using (Graphics gBmp = Graphics.FromImage(t))
        {
            Color green = Color.FromArgb(0x40, 0, 0xff, 0);
            using (Brush greenBrush = new SolidBrush(green))
            {
                // draw a green rectangle to the bitmap in memory
                gBmp.FillRectangle(greenBrush, 0, 0, 799, i);
                if (File.Exists("c:\temp\i.jpg"))
                {
                    File.Delete("c:\temp\i.jpg");
                }
                t.Save("c:\temp\i.jpg", ImageFormat.Jpeg);
            }
        }
        GC.Collect();
    }

La même erreur se produit également si vous écrivez à un flux de mémoire.

pour le contourner, Vous pouvez répéter le code ci-dessus et remplacer ImageFormat.TIFF ou ImageFormat.Bmp for ImageFormat.Jpeg.

cela va jusqu'à des hauteurs / largeurs de 100.000 pour moi - je n'ai pas testé les limites. Comme il arrive .Tiff était une option viable pour nous.

SOYEZ AVERTI

les flux / fichiers TIFF en mémoire consomment plus de mémoire que leurs homologues JPG.

11
répondu vipes 2013-03-26 15:55:12

au cas où quelqu'un ferait des trucs aussi stupides que moi. 1. assurez-vous que le chemin n'existe pas. 2. assurez-vous que vous disposez des autorisations d'écriture. 3. assurez-vous que votre chemin est correct, dans mon cas je manquais le nom du fichier dans le chemin de Target: (

il aurait dû dire, votre chemin craint que "une erreur générique s'est produite dans GDI+ "

11
répondu ahsant 2016-09-19 01:47:53

j'ai aussi eu cette erreur lors de la sauvegarde de JPEGs, mais seulement pour certaines images.

mon code final:

  try
  {
    img.SaveJpeg(tmpFile, quality); // This is always successful for say image1.jpg, but always throws the GDI+ exception for image2.jpg
  }
  catch (Exception ex)
  {
    // Try HU's method: Convert it to a Bitmap first
    img = new Bitmap(img); 
    img.SaveJpeg(tmpFile, quality); // This is always successful
  }

Je n'ai pas créé les images donc je ne peux pas dire quelle est la différence.

J'apprécierais que quelqu'un puisse expliquer ça.

Ceci est mon SaveJpeg fonction juste pour info:

private static void SaveJpeg(this Image img, string filename, int quality)
{
  EncoderParameter qualityParam = new EncoderParameter(Encoder.Quality, (long)quality);
  ImageCodecInfo jpegCodec = GetEncoderInfo("image/jpeg");
  EncoderParameters encoderParams = new EncoderParameters(1);
  encoderParams.Param[0] = qualityParam;
  img.Save(filename, jpegCodec, encoderParams);
}
10
répondu Aximili 2014-05-07 01:55:22

si votre code est comme suit, alors cette erreur se produit aussi

private Image GetImage(byte[] byteArray)
{
   using (var stream = new MemoryStream(byteArray))
   {
       return Image.FromStream(stream);
    }
}

la bonne est

private Image GetImage(byte[] byteArray)
{
   var stream = new MemoryStream(byteArray))
   return Image.FromStream(stream);        
}

c'est peut-être parce que nous revenons du bloc d'utilisation

9
répondu dhinesh 2010-10-07 14:22:08

avait un problème très similaire et a également essayé de cloner l'image qui ne fonctionne pas. J'ai trouvé que la meilleure solution était de créer un nouvel objet Bitmap à partir de l'image chargée à partir du flux de mémoire. De cette façon, le flux peut être éliminé par exemple

using (var m = new MemoryStream())
{
    var img = new Bitmap(Image.FromStream(m));
    return img;
}

Espérons que cette aide.

7
répondu HU. 2011-07-22 16:19:30

résolu - j'avais ce même problème. La solution, pour moi, était d'augmenter le quota de disque pour IUSR sur le serveur IIS. Dans ce cas, nous avons une application de catalogue avec des images d'articles et autres. Le quota de téléchargement pour l '"utilisateur web anonyme" a été fixé à 100 Mo, ce qui est la valeur par défaut pour les serveurs IIS de cette société d'hébergement en particulier. Je l'ai augmenté à 400 Mo et j'ai pu télécharger des images sans erreur.

peut-être pas votre problème, mais si elle l'est, c'est une solution facile.

5
répondu Marco 2011-01-29 07:21:22

erreur due à la Permission. assurez-vous que le dossier a toutes les permissions.

public Image Base64ToImage(string base64String)
    {
        // Convert Base64 String to byte[]
        byte[] imageBytes = Convert.FromBase64String(base64String);
        MemoryStream ms = new MemoryStream(imageBytes, 0,
          imageBytes.Length);

        // Convert byte[] to Image
        ms.Write(imageBytes, 0, imageBytes.Length);
        Image image = Image.FromStream(ms, true);
        return image;
    }

 img.Save("YOUR PATH TO SAVE IMAGE")
5
répondu vivek shaushi 2015-11-17 20:35:16

dans mon cas, le problème était dans le chemin que je sauvais (la racine C:\ ). Le changer en D:1\ a fait disparaître l'exception.

4
répondu Ani 2011-10-11 05:42:23

une autre cause de cette erreur - le chemin que vous indiquez dans la méthode de sauvegarde de L'instance Bitmap n'existe pas ou vous n'avez pas fourni de chemin complet / valide.

vient D'avoir cette erreur parce que je passais dans un nom de fichier et pas un chemin complet!

ça arrive!

4
répondu MytyMyky 2012-08-29 14:20:18

à mon tour!

using (System.Drawing.Image img = Bitmap.FromFile(fileName))
{
      ... do some manipulation of img ...
      img.Save(fileName, System.Drawing.Imaging.ImageFormat.Jpeg);
}

est sur le .Enregistrer... parce que l'utilisation de () maintient le fichier ouvert, donc je ne peux pas l'écraser. Peut-être que cela va aider quelqu'un dans le futur.

4
répondu Andy 2013-03-11 20:38:48

même problème que moi. Mais dans mon cas, j'essayais de sauvegarder le fichier dans le lecteur C et il n'était pas accessible. J'ai donc essayé d'économiser en d drive qui était entièrement accessible et j'ai réussi.

Donc d'abord vérifier vos dossiers dans lesquels vous essayez d'enregistrer. Vous devez avoir tous les droits (lire et écrire) pour ce dossier particulier.

3
répondu jimmy 2017-10-23 08:45:50

je remarque que votre cas "jpeg" est en fait:

            default:
                format = ImageFormat.Jpeg;
                break;

Êtes-vous sûr que le format jpeg et pas autre chose?

je voudrais essayer:

            case "image/jpg": // or "image/jpeg" !
                format = ImageFormat.Jpeg;
                break;

ou vérifiez ce que imageToConvert.MimeType() est réellement de retour.

mise à JOUR

y a-t-il une autre initialisation que vous devez faire à L'objet MemoryStream?

2
répondu ChrisF 2009-06-27 16:17:26

juste pour lancer une autre solution possible sur la pile, je vais mentionner le cas que j'ai rencontré avec ce message d'erreur. La méthode Bitmap.Save devait passer par cette exception lors de l'enregistrement d'un bitmap que j'avais transformé et que j'affichais. J'ai découvert qu'il ne serait pas jeter l'exception si la déclaration avait un point de rupture sur elle, ni serait-il si le Bitmap.Save a été précédé par Thread.Sleep(500) donc je suppose qu'il ya une sorte de conflit de ressources en cours.

simplement copier l'image vers un nouvel objet Bitmap était suffisant pour empêcher cette exception d'apparaître:

new Bitmap(oldbitmap).Save(filename);
1
répondu Segfault 2012-05-08 22:37:20

si vous essayez de sauvegarder une image dans un remote location assurez-vous d'ajouter le compte d'utilisateur NETWORK_SERVICE dans les paramètres de sécurité et de donner à cet utilisateur lire et écrire des permissions. Sinon, il n'est pas d'aller travailler.

1
répondu JAH 2013-01-11 19:33:24
byte[] bts = (byte[])page1.EnhMetaFileBits; 
using (var ms = new MemoryStream(bts)) 
{ 
    var image = System.Drawing.Image.FromStream(ms); 
    System.Drawing.Image img = image.GetThumbnailImage(200, 260, null, IntPtr.Zero);      
    img.Save(NewPath, System.Drawing.Imaging.ImageFormat.Png);
}
1
répondu jeka 2013-09-09 09:38:36

j'ai aussi cette erreur parce que j'essaie de sauvegarder des images avec le même nom que les images précédemment sauvegardées.

assurez-vous que vous ne sauvegardez pas des images avec le nom dupliqué.

utilisez pour thar par exemple une fonction "aléatoire" ( Comment fonctionne le générateur de nombres aléatoires de C#? ) ou par exemple générer un Guid ( http://betterexplained.com/articles/the-quick-guide-to-guids / )

1
répondu Bruno Ferreira 2017-05-23 12:34:50
  • j'ai eu ce problème sur un serveur de test mais pas sur le serveur live.
  • j'écrivais l'image à un ruisseau, donc ce n'était pas un problème de permission.
  • j'étais en train de déployer une partie du .dll vers le serveur de test.
  • déployer toute la solution a résolu le problème, donc c'était probablement une erreur de compilation étrange
1
répondu Chris Halcrow 2016-08-03 00:30:38

nous avions en quelque sorte le même problème sur la génération D'un PDF sur le serveur de production.

Recyclage de l'application de la piscine "151940920 de" résoudre le problème.

J'espère que cela aidera quelqu'un.

1
répondu tech-gayan 2018-07-02 16:29:04

pour moi, j'utilisais le Image.Save(Stream, ImageCodecInfo, EncoderParameters) et apparemment cela causait l'infâme erreur A generic error occurred in GDI+ .

j'essayais d'utiliser EncoderParameter pour sauver les jpegs en qualité 100%. Cela fonctionnait parfaitement sur "ma machine" (doh!) et non sur la production.

quand j'ai utilisé le Image.Save(Stream, ImageFormat) à la place, l'erreur a disparu! Donc comme un idiot j'ai continué à utiliser ce dernier bien qu'il les sauve dans la qualité par défaut qui je suppose est de seulement 50%.

J'espère que cette info aidera quelqu'un.

0
répondu Ε Г И І И О 2013-02-11 06:50:46

j'ai rencontré le problème. Le problème était dû au fait que le courant de chargement était éliminé. Mais je ne l'ai pas jeté, il était à L'intérieur de .net framework. Tout ce que j'avais à faire était d'utiliser:

image_instance = Image.FromFile(file_name);

au lieu de

image_instance.Load(file_name);

image_instance est de type Système.Windows.Forme.PictureBox! Le Load() de PictureBox élimine le flux d'où l'image a été chargée, et je ne le savais pas.

0
répondu Klaus 2013-02-16 11:07:31

basé sur la réponse de @savindra , si vous RHM sur votre application et essayer d'exécuter comme un administrateur alors il devrait résoudre votre problème.

Mine semblait être un problème de permission.

0
répondu AltF4_ 2016-01-07 11:08:02