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.
- Cloner l'image et travailler dessus.
- récupérant l'encodeur pour ce MIME passant celui avec le paramètre de qualité jpeg.
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
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.
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
.
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.
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.
Enregistrer l'image bitmap variable
using (var ms = new MemoryStream())
{
Bitmap bmp = new Bitmap(imageToConvert);
bmp.Save(ms, format);
return ms.ToArray();
}
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.
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.
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+ "
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);
}
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
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.
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.
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")
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.
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!
à 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.
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.
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?
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);
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.
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);
}
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 / )
- 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
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.
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.
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.
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.