Search code examples
c#winformsimagelist

Imagefrom.File(). Out of memory exception


I am trying to load about 60 pictures in a list. Each picture is about 1MB. For 20 pictures no problem but above that I get Out of memory exception on the code line below. I have searched vastly of related issues, some stating about "using" key word and stream but since I am a beginner can someone please help me.

Image image = Bitmap.FromFile(Filename);

Here is my code

  private void LoadBtn_Click_1(object sender, EventArgs e)
    {
        OpenFileDialog newDialog = new OpenFileDialog();
        if (newDialog.ShowDialog() == DialogResult.OK)
        {
            images.Clear();

            string dirPath  = System.IO.Path.GetDirectoryName(newDialog.FileName.ToLower()); 
            DirectoryInfo di = new DirectoryInfo(dirPath);
            FileInfo[] finfos = di.GetFiles("*.*");

            foreach (FileInfo fi in finfos)
            {
                string ext = fi.Extension.ToLower();
                if ((ext.Equals(".png")) || (ext.Equals(".jpg")) || (ext.Equals(".tif")) ||                  (ext.Equals(".gif")))
                {
                    string Filename = fi.FullName;
                    Image image = Bitmap.FromFile(Filename); //exception occurs HERE
                    images.Add(image);
                    //this.imageList1.Images.Add(image);
                    //image.Dispose();
                }
            } 
        }

        pictureBox3.Image = images[0];

    }

I am using C#, windows forms. thanks


Solution

  • After taking a look at the software you mentioned, as I told you you don't need to load the whole image in memory if you only need a thumbnail.

    So I'd create I class

    class ImageAndThumb
    {
        public Image Thumb;
        public Image Big;
        private string ImagePath;
        public ImageAndThumb(string fileName)
        {         
            ImagePath = fileName;
            Image image = Image.FromFile(fileName)
            Image thumb = img.GetThumbnailImage(200, 200, ()=>false, IntPtr.Zero);
        }
        public Image LoadBigImage()
        {
            Big = Image.FromFile(ImagePath);
            return Big;
        }
        public void UnloadImage()
        {
            Big = null;
        }
    
    }
    

    Now we use that class:

    List<ImageAndThumb> Images = new List<ImageAndThumb>();
      private void LoadBtn_Click_1(object sender, EventArgs e)
        {
            OpenFileDialog newDialog = new OpenFileDialog();
            if (newDialog.ShowDialog() == DialogResult.OK)
            {
                Images.Clear();
    
                string dirPath  = System.IO.Path.GetDirectoryName(newDialog.FileName.ToLower()); 
                DirectoryInfo di = new DirectoryInfo(dirPath);
                FileInfo[] finfos = di.GetFiles("*.*");
    
                foreach (FileInfo fi in finfos)
                {
                    string ext = fi.Extension.ToLower();
                    if ((ext.Equals(".png")) || (ext.Equals(".jpg")) || (ext.Equals(".tif")) ||                  (ext.Equals(".gif")))
                    {
                        string Filename = fi.FullName;
                        ImageAndThumb image = new ImageAndThumb(Filename); 
                        Images.Add(image);
                    }
                } 
            }
    
            pictureBox3.Image = Images[0].Thumb; // << Much less memory usage;
    
        }
    

    And now whenever you need to use an image load it first For example:

    void ShowPicture(int index)
    {
        Images[index].LoadBigImage();
        PictureBoxBig.image = Images[index].Big;
    }
    void ClosePicture(int index)
    {
        Images[index].UnloadImage();
    }
    

    one good idea is to unload an image once you load another:

    int currentPictureIndex = -1;
        void ShowPicture(int index)
        {
            Images[index].LoadBigImage();
            PictureBoxBig.image = Images[index].Big;
            if(CurrentPictureIndex > -1) ClosePicture(CurrentPictureIndex);
            currentPictureIndex = index;
        }