web-dev-qa-db-fra.com

Exception de mémoire insuffisante sur System.Drawing.Image.FromFile ()

J'ai un outil de téléchargement et de découpe d'image qui crée des vignettes et j'obtiens parfois une exception de mémoire insuffisante sur la ligne suivante:

Dim bm As Bitmap = System.Drawing.Image.FromFile(imageFile)

La survenue de l’erreur est minuscule et très rare, mais j’aime toujours savoir quelle en est la cause. La variable imageFile est simplement Server.MapPath du chemin de l'image.

J'étais curieux de savoir si quelqu'un avait déjà rencontré ce problème et s'il avait des idées sur ce qui pourrait le provoquer. Est-ce la taille de l'image peut-être?

Je peux poster le code si nécessaire et toute information à l'appui que je possède, mais j'aimerais connaître l'opinion des gens à ce sujet.

41
dooburt

Il est bon de savoir que OutOfMemoryException ne signifie pas toujours vraiment que sa mémoire est insuffisante, en particulier quand il s’agit de fichiers. Je crois que cela peut aussi arriver si vous manquez de poignées pour une raison quelconque.

Disposez-vous de toutes vos bitmaps une fois que vous en avez terminé? Cela se produit-il de manière répétée pour une seule image?

40
Jon Skeet

Si ce n'était pas un mauvais fichier image mais était en fait le problème normal avec Image.FromFile dans lequel il garde les descripteurs de fichiers ouverts, la solution est d'utiliser plutôt Image.FromStream.

using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read))
{
   using (Image original = Image.FromStream(fs))
   {
      ...

L'utilisation d'une Dispose() explicite, d'une instruction using() ou la définition de la valeur null sur le bitmap ne résout pas le problème avec Image.FromFile.

Donc, si votre application fonctionne pendant un certain temps et ouvre beaucoup de fichiers, envisagez plutôt d'utiliser Image.FromStream().

33
Ian Mercer

Je soulève le même problème aujourd'hui en créant des images miniatures pour un dossier plein d'images. Il s'avère que la "mémoire insuffisante" s'est produite exactement au même point à chaque fois. Lorsque j'ai consulté le dossier contenant les images à convertir, j'ai constaté que le fichier à l'origine du problème était thumbs.db. J'ai ajouté du code pour m'assurer que seuls les fichiers d'image étaient en cours de conversion et que le problème était résolu.

Mon code est fondamentalement

For Each imageFile as FileInfo in fileList
If imageFile.Extension = ".jpg" Or imageFile.Extension = ".gif" Then
    ...proceed with the conversion
End If
Next

J'espère que cela t'aides.

6
Gilbert Biro Simon

Vous pouvez aussi l'ouvrir en mode lecture (si vous voulez l'utiliser deux fois en même temps)

 public Image OpenImage(string previewFile)
        {
            FileStream fs = new FileStream(previewFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
            return Image.FromStream(fs);
        }
3
Avram

Vérifiez également si vous n'avez pas ouvert le même fichier ailleurs. Apparemment, lorsque vous ouvrez un fichier deux fois (même avec File.Open ()), OutOfMemoryException est également levé ...

2
pinus.acer

J'ai eu le même problème avec un utilitaire que j'ai écrit pour convertir le (s) fichier (s) TIFF en fichier (s) PDF. Souvent, j'obtenais l'erreur «mémoire insuffisante» sur la même ligne que vous.

System.Drawing.Image.FromFile(imageFile)

Ensuite, j'ai découvert que l'erreur ne s'était produite que lorsque l'extension de fichier était ".tiff" et fonctionnait correctement après l'avoir renommée avec une extension de ".tif"

1
Jeff Chapin

J'ai eu un problème similaire aujourd'hui lorsque j'essayais de redimensionner une image, puis de la recadrer. Ce qui s'est passé, c'est que j'ai utilisé ce code pour redimensionner l'image.

private static Image resizeImage(Image imgToResize, Size size)
{
   int sourceWidth = imgToResize.Width;
   int sourceHeight = imgToResize.Height;

   float nPercent = 0;
   float nPercentW = 0;
   float nPercentH = 0;

   nPercentW = ((float)size.Width / (float)sourceWidth);
   nPercentH = ((float)size.Height / (float)sourceHeight);

   if (nPercentH < nPercentW)
      nPercent = nPercentH;
   else
      nPercent = nPercentW;

   int destWidth = (int)(sourceWidth * nPercent);
   int destHeight = (int)(sourceHeight * nPercent);

   Bitmap b = new Bitmap(destWidth, destHeight);
   Graphics g = Graphics.FromImage((Image)b);
   g.InterpolationMode = InterpolationMode.HighQualityBicubic;

   g.DrawImage(imgToResize, 0, 0, destWidth, destHeight);
   g.Dispose();

   return (Image)b;
}

Et puis ce code pour la culture ...

private static Image cropImage(Image img, Rectangle cropArea)
{
   Bitmap bmpImage = new Bitmap(img);
   Bitmap bmpCrop = bmpImage.Clone(cropArea,
   bmpImage.PixelFormat);
   return (Image)(bmpCrop);
}

Alors voici comment j'ai appelé le code ci-dessus ...

Image img = Image.FromFile(@"C:\Users\****\Pictures\image.jpg");
img = ImageHandler.ResizeImage(img, new Size(400, 300));
img = ImageHandler.CropImage(img, new Rectangle(0, 25, 400, 250));
long quality = 90;

J'ai continué à avoir des erreurs sur la partie recadrée, le resizer a bien fonctionné!

Il s’est avéré que ce qui se passait à l’intérieur du resizer jetterait des erreurs dans la fonction de recadrage. Les calculs redimensionnés faisaient apparaître les dimensions réelles de l’image comme étant 399 au lieu des 400 que j’ai transmises.

Donc, quand je suis passé en 400 comme argument pour le recadrage, il essayait de recadrer une image large de 399 pixels avec un bmp de 400 pixels en largeur et cela provoquait une erreur de mémoire insuffisante!

La plupart du code ci-dessus a été trouvé sur http://www.switchonthecode.com/tutorials/csharp-tutorial-image-editing-saving-cropping-and-resizing

1
jcreamer898

Si une image est une icône, un chargement différent est requis, comme dans la fonction suivante:

public static Image loadImage(string imagePath)
    {
        Image loadedImage = null;
        if (!File.Exists(imagePath)) return loadedImage;
        try
        {
            FileInfo fileInfo = new FileInfo(imagePath);
            if (fileInfo.Extension.Equals(".jpg") || fileInfo.Extension.Equals(".jpeg") ||
               fileInfo.Extension.Equals(".bmp") || fileInfo.Extension.Equals(".png") ||
               fileInfo.Extension.Equals(".gif"))
            {
                loadedImage = Image.FromFile(imagePath);
            }
            else if (fileInfo.Extension.Equals(".ico"))
            {
                Bitmap aBitmap = Bitmap.FromHicon(new
                                           Icon(imagePath, new Size(200, 200)).Handle);
                loadedImage = ImageFuncs.ResizeImage(aBitmap, new Size(30, 30));
            }
        }
        catch (Exception eLocal)
        {
            MessageBox.Show(imagePath + " loading error: " + eLocal.Message);
        }
        return loadedImage;
    }
1
IrinaL

J'ai eu le même problème, avant de regarder ailleurs où dans le code voulait m'assurer si je pouvais ouvrir l'image avec n'importe quel visualiseur d'image et comprendre que l'image est corrompue/endommagée bien qu'il s'agisse d'un fichier .PNG d'une taille de 1Ko. Ajout d'une nouvelle image au même endroit, puis cela a bien fonctionné.

0
Kiran Modini

Je rencontre le même problème de traitement par lots des fichiers Tiff. La plupart des fichiers ne génèrent pas d'exception, mais rares sont ceux qui génèrent une exception "Mémoire insuffisante" dans ASP.NET 4.0. J'ai utilisé des données binaires pour savoir pourquoi, pour quelques fichiers et dans le même dossier. Il ne peut s'agir d'un problème d'autorisation pour un compte ASP.NET ASPNET ou NETWORK SERVICE car d'autres fichiers sont des fichiers de travail. 

J'ai ouvert la classe iTextSharp.text.Image et constaté qu'il existe de nombreuses méthodes surchargées pour GetInstance (). J'ai résolu mon problème en utilisant le code suivant: note: le bloc catch sera exécuté pour les fichiers problématiques.

                iTextSharp.text.Image image = null;
            try
                {
                    var imgStream = GetImageStream(path);
                     image = iTextSharp.text.Image.GetInstance(imgStream);
                }
                catch {
                    iTextSharp.text.pdf.RandomAccessFileOrArray ra = null;
                    ra = new iTextSharp.text.pdf.RandomAccessFileOrArray(path);
                    image = iTextSharp.text.pdf.codec.TiffImage.GetTiffImage(ra, 1);

                    if (ra != null)
                        ra.Close();

                }
0
Nilesh Hirpara