2013-08-05 2 views
0

Je viens d'écrire une fonction qui prend un répertoire, crée un nouveau "resizedDirectory" (s'il n'existe pas), redimensionne chaque fichier .bmp, et l'enregistre dans " resizedDirectory ". Ceci est la première fois que je l'ai écrit une fonction comme celui-ci (utilisé Internet pour certaines parties), voici le code:ASP/C#, new Bitmap() "Mémoire insuffisante"

protected void directorySelected(object sender, EventArgs e) { 
    // Make sure the directory exists 
    if (Directory.Exists(inputDirectory.Text)) { 
     string[] filePaths = Directory.GetFiles(inputDirectory.Text); 

     // Determine if there are any files in inputDirectory 
     if (filePaths.Length == 0) messageLog.InnerHtml = "<strong>No files found in:</strong> "+inputDirectory.Text; 
     else { 
      // Determine if "resizedDirectory" exists, create it if it does not exist 
      string resizedDirectory = inputDirectory.Text+"\\"+"resizedDirectory"; 
      if (!Directory.Exists(resizedDirectory)) { 
       Directory.CreateDirectory(resizedDirectory); 
       messageLog.InnerHtml = "<strong>Created:</strong> "+resizedDirectory+"<br/><br/>"; 
      } 

      // For each file in inputDirectory... 
      for (var i = 0; i < filePaths.Length; i++) { 
       string[] extensionSplit = filePaths[i].Split('.'); 

       // Make sure filePath[i] ends with the appropriate extension 
       if (extensionSplit.Length == 2 && extensionSplit[1].Equals("bmp")) { 
        Bitmap currImage = new Bitmap(filePaths[i]); 
        messageLog.InnerHtml += "<strong>"+i.ToString()+":</strong> "+filePaths[i]+"<br/><div class='indent'>"; 

        // Calculate new dimensions 
        int newWidth = maxWidth; 
        int newHeight = maxHeight; 
        if (currImage.Width > currImage.Height) newHeight = (int)(((float)maxWidth)/((float)currImage.Width)*currImage.Height); 
        else newWidth = (int)(((float)maxHeight)/((float)currImage.Height)*currImage.Width); 
        messageLog.InnerHtml += "<strong>Old dimensions:</strong> ("+currImage.Width+","+currImage.Height+")<br/><strong>New dimensions:</strong> ("+newWidth+", "+newHeight+")<br/>"; 

        // Settings before saving 
        Bitmap targetImage = new Bitmap(newWidth, newHeight); 
        using (Graphics g = Graphics.FromImage(targetImage)) { 
         g.CompositingQuality = CompositingQuality.HighQuality; 
         g.InterpolationMode = InterpolationMode.HighQualityBicubic; 
         g.SmoothingMode = SmoothingMode.HighQuality; 
         g.DrawImage(currImage, 0, 0, newWidth, newHeight); 
        } 
        ImageCodecInfo ici = this.GetEncoderInfo(ImageFormat.Bmp); 
        Encoder eq = Encoder.Quality; 
        EncoderParameters eps = new EncoderParameters(1); 
        EncoderParameter ep = new EncoderParameter(eq, 100L); // 100L is the higest quality (goes from 0 - 100) 
        eps.Param[0] = ep; 

        // Save image 
        string targetPath = resizedDirectory+"\\foo"+i.ToString()+".bmp"; 
        targetImage.Save(targetPath, ici, eps); 
        messageLog.InnerHtml += "<strong>Saved:</strong> "+targetPath+"</div><br/>"; 
       } 
       else messageLog.InnerHtml += "<strong>IGNORED "+i.ToString()+":</strong> "+filePaths[i]+"<br/>"; 
      } 
     } 
    } 
    else if (inputDirectory.Text.Equals("")) messageLog.InnerHtml = "<strong>No directory specified</strong>"; 
    else messageLog.InnerHtml = "<strong>Cannot find:</strong> "+inputDirectory.Text; 
} 

protected ImageCodecInfo GetEncoderInfo(ImageFormat format) { 
    return ImageCodecInfo.GetImageDecoders().SingleOrDefault(c => c.FormatID == format.Guid); 
} 

Cela a bien fonctionné avec des petits .bmps. Le problème est que les répertoires de .bmps que j'ai besoin de convertir sont énormes, un exemple .bmp est 16073 x 13231 (ou 608MB). J'ai essayé le code avec un peu de .bmp et l'un des énormes .bmps et il a fait "resizedDirectory", a créé un nouveau .bmp redimensionné du petit là, puis s'est écrasé avec le message "Out of memory".

Comment dois-je procéder pour redimensionner l'énorme .bmps?

Modifier: Il échoue sur un énorme .bmp (mais pas sur les petits)

+0

S'il vous plaît rebaliser votre question: ce n'est pas « asp classique » ... –

Répondre

1

Tout d'abord, testez votre code avec bitmaps unique. Bien qu'ils soient volumineux, vous pouvez constater que votre programme peut toujours les traiter un à la fois, auquel cas vous n'aurez pas besoin de faire grand-chose pour le faire fonctionner. (Si cela ne fonctionne pas pour une seule image massive, vous devrez commencer à rechercher une bibliothèque de chargement ou de traitement d'images différente de celle des classes .net intégrées.)

Si cela fonctionne pour une image mais pas pour une image séquence d'entre eux, puis assurez-vous de libérer toute la mémoire utilisée par un bitmap avant d'essayer de charger le suivant. Essentiellement, vous devez appeler currImage.Dispose(); après tout votre traitement de l'image bitmap (à l'intérieur de la fin de votre boucle) pour libérer la mémoire qu'il utilise.

Cependant, la bonne façon d'y parvenir est d'écrire le code de traitement dans un bloc using, qui appellera automatiquement Éliminez pour vous (même si une exception est levée):

using (Bitmap currImage = new Bitmap(filePaths[i])) 
{ 
    // Process the bitmap here 
} 

Vous devrez Faites une chose similaire pour targetImage afin de vous assurer qu'il est également éliminé après qu'il a été écrit.

Cela libère toute la mémoire utilisée par l'image bitmap dès que vous avez fini de le traiter afin qu'elle soit disponible pour l'image bitmap suivante à utiliser.

+0

Il échoue sur un .bmp énorme, J'ai mis à jour ma question – asimes

0

Toutes les ressources GDI + doivent être éliminées. Je pense que le problème est que votre instruction USING ne dispose pas de l'objet Graphics. C'est une erreur que je l'ai fait moi-même beaucoup de temps :)

http://msdn.microsoft.com/en-us/library/system.drawing.graphics.dispose.aspx

g.Dispose(); 
+0

Il échoue sur un énorme .bmp, j'ai mis à jour ma question – asimes

+0

c'est innacurate. Le but de l'utilisation est de disposer de l'objet lorsque vous quittez sa portée – ghostbust555