C# RAM läuft voll

Xidus

Lieutenant
Registriert
Jan. 2011
Beiträge
739
Hab ein Problem die Funktion die ich geschrieben hat läst den Ram voll laufen

Code:
        private static Bitmap resizeImage(Bitmap 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 = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;

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

            return b;
        }

Das Objekt b was zurück gegeben wird, wird wohl nicht gelöscht wenn ich es Manuel in den Quelltext einfüge (ohne Funktion) kann ich es mit Dispose() freigeben nur wie mach ich das wenn es ein return wert ist in ner Funktion

mfg Xidus
 
du rufst einfach Dispose dort auf, wo du die Grafik nicht mehr brauchst!

Also zerst resizeImage aufrufen, das Bild z.B. abspeichern -> danach Dispose aufrufen!
 
Du kannst deine Funktion auch in einer using-Anweisung aufrufen.

Code:
using(Bitmap m = resizeImage(imgToResize,size))
{

// your Code goes here!

}

Nach verlassen des using-Blocks wird IDisposable.Dispose aufgerufen.
Zu deiner Formulierung "Der Ram läuft voll" wollte ich noch etwas sagen.
Der Ram kann unter Managed Sprache wie C# nicht voll laufen. Du kriegst höchstens ne Exception.
 
hmm hab sogar beides schon probiert gehabt soagr zusammen

using(Bitmap m = resizeImage(imgToResize,size))
{

m.Dispose();
}

aber geht nicht speicher wird voller und voller
 
Code:
public void GetFileListTumb(String folder, String save)
{
    string[] Files = System.IO.Directory.GetFiles(folder);
    List<String> onlyBilder = new List<string>();

    for (int i = 0; i < Files.Length; i++)
        if (truePicture(Files[i].ToString()))
            onlyBilder.Add(Files[i]);

    if (onlyBilder.Count != 0)
    {
        Int32 ab = (Int32)(Math.Sqrt(onlyBilder.Count));
        Bitmap thumb = new Bitmap((ab) * thumbSize, (ab + 1) * thumbSize);

        for (Int32 a = 0; a < ab + 1; a++)
            for (Int32 b = 0; b < ab; b++)
                if ((b + ab * a) < onlyBilder.Count)
                {
                    Bitmap tmp = resizeImage(new Bitmap(Files[b + ab * a].ToString()), new Size(thumbSize, thumbSize));

                    for (Int32 x = 0; x < tmp.Width; x++)
                        for (Int32 y = 0; y < tmp.Height; y++)
                            thumb.SetPixel(x + b * thumbSize, y + a * thumbSize, tmp.GetPixel(x, y));

                    tmp.Dispose();
                }
                
        thumb.Save(save + folder.Substring(folder.LastIndexOf('\\')) + ".png", ImageFormat.Png);
        thumb.Dispose();
    }
}

Code:
private static Bitmap resizeImage(Bitmap 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 = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;

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

    return b;
}


so sollte es eigentlich sein, jedoch macht er so jedes Bild in den RAM und gibt erst wenn er mit allem fertig ist den Speicher wieder frei

Code:
public void GetFileListTumb(String folder, String save)
{
    string[] Files = System.IO.Directory.GetFiles(folder);
    List<String> onlyBilder = new List<string>();

    for (int i = 0; i < Files.Length; i++)
        if (truePicture(Files[i].ToString()))
            onlyBilder.Add(Files[i]);

    if (onlyBilder.Count != 0)
    {
        Int32 ab = (Int32)(Math.Sqrt(onlyBilder.Count));
        Bitmap thumb = new Bitmap((ab) * thumbSize, (ab + 1) * thumbSize);

        for (Int32 a = 0; a < ab + 1; a++)
            for (Int32 b = 0; b < ab; b++)
                if ((b + ab * a) < onlyBilder.Count)
                {
                    Bitmap imgToResize = new Bitmap(Files[b + ab * a]);
                    int sourceWidth = imgToResize.Width;
                    int sourceHeight = imgToResize.Height;

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

                    nPercentW = ((float)thumbSize / (float)sourceWidth);
                    nPercentH = ((float)thumbSize / (float)sourceHeight);

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

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

                    Bitmap bm = new Bitmap(destWidth, destHeight);
                    Graphics g = Graphics.FromImage((Image)bm);
                    g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;

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

                    for (Int32 x = 0; x < bm.Width; x++)
                        for (Int32 y = 0; y < bm.Height; y++)
                            thumb.SetPixel(x + b * thumbSize, y + a * thumbSize, bm.GetPixel(x, y));
                    bm.Dispose();
                }
        thumb.Save(save + folder.Substring(folder.LastIndexOf('\\')) + ".png", ImageFormat.Png);
        thumb.Dispose();
    }

}

Wenn ich es so mache läuft der RAM nicht voll
 
In der ersten Version fehlt das Dispose() für das Bitmap, das du der Methode übergibst "resizeImage(new Bitmap(...".

Nutze immer die using-Klausel für Objekte die IDisposable implementieren, sofern möglich. Dann kannst du 1. sicher sein dass der Speicher wieder freigegeben wird und sparst die 2. das explizite Aufrufen von Dispose().
 
wenn ich das so mache läuft der immer noch voll

Code:
using (Bitmap tmp = resizeImage(new Bitmap(Files[b + ab * a].ToString()), new Size(thumbSize, thumbSize)))
{
    for (Int32 x = 0; x < tmp.Width; x++)
        for (Int32 y = 0; y < tmp.Height; y++)
            thumb.SetPixel(x + b * thumbSize, y + a * thumbSize, tmp.GetPixel(x, y));
}

so gehts aber ( danke)
Code:
Bitmap tp = new Bitmap(Files[b + ab * a].ToString());
Bitmap tmp = resizeImage(new Bitmap(Files[b + ab * a].ToString()), new Size(thumbSize, thumbSize));
    tp.Dispose();

    for (Int32 x = 0; x < tmp.Width; x++)
        for (Int32 y = 0; y < tmp.Height; y++)
            thumb.SetPixel(x + b * thumbSize, y + a * thumbSize, tmp.GetPixel(x, y));

    tmp.Dispose();
 
Im ersten Code erzeugst du wieder ein Bitmap auf dem du kein Dispose() aufrufst: "resizeImage(new Bitmap(Files[b + ab * a].ToString())"

Im zweiten Code machst es genau so aber das scheinst du beim posten vergessen zu haben "new Bitmap(..)" durch "tp" zu ersetzen. Dann hättest du auf jedem Bitmap dispose aufgerufen. Aber wie gesagt, using (auf jedem new Bitmap) ist eleganter und sicherer.
 
Hab das hier grade durch Zufall gefunden, keine Ahnung ob es noch aktuell ist.

So wie ich das sehe, versuchst du Thumbnails zu erstellen und machst dir dabei das Leben schwerer als erforderlich. Falls du nicht grade hoch-auflösende Thumbs haben willst, kannst du auch einfach GetThumbnailImage nutzen.

Siehe Code für eine Console Anwendung zum erstellen der Thumbs.

Code:
namespace ThumbCreator
{
    using System;
    using System.Drawing;
    using System.Drawing.Imaging;
    using System.IO;
    using System.Linq;

    public class Program
    {
        static void Main( string[] args )
        {
            string[] extensions = { "jpg", "png", "bmp", "gif" };
            var pictures = Directory.GetFiles( @"D:\TestPicsWithOtherFiles" ).Where( file => extensions.Any( s => file.ToLower().Contains( s ) ) );
            foreach ( var picture in pictures )
            {
                Image image = Image.FromFile( picture );
                Image thumb = image.GetThumbnailImage( 120, 120, () => false, IntPtr.Zero );
                 
                string newPictureName = String.Format( "{0}_thumb.png", picture.Substring( 0, picture.LastIndexOf( '.' ) ) );
                thumb.Save( newPictureName, ImageFormat.Png );
                
                thumb.Dispose();
                image.Dispose();
            }
        }
    }
}
 
Zurück
Oben