0

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

Basco
  • 87
  • 1
  • 1
  • 7
  • Take a look at http://stackoverflow.com/questions/2610416/is-there-a-reason-image-fromfile-throws-an-outofmemoryexception-for-an-invalid-i – Jason Watkins Mar 23 '13 at 07:06
  • Thanks for your response, but non of the answers there matches my problem. My files are not corrupted, the problem has to really do with the size of total files being loaded. Was thinking if there is a round about way for this memory problem because I have seen neat Picture viewers which does what I want. For example this project "https://sourceforge.net/projects/picturefilter/ " does exactly whatI want but I cannot access the codes. only the .exe file available – Basco Mar 23 '13 at 07:30

2 Answers2

1

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;
    }
Omar Alshaker
  • 879
  • 9
  • 22
  • Thanks Omer 1) my application will load all image files available in folder which the user selects to view a file. All these images will be displayed as thumbnails in a list view sub panel. 2)There is next and back buttons which the user will use to browse to the next and previous images to be displayed on the main window. 3)Why I decided to put all the images in a list is because I have a function which will give colour to all the images if the user desires. Please have a look at this application. It is similar to what i need, sourceforge.net/projects/picturefilter – Basco Mar 23 '13 at 08:52
  • 1
    Thanks Omar, For some reasons which I dont know Image image = Image.FromFile(fileName) gives only about 45 thumbnails and the rest is null but after modifying your code FileStream fs = new FileStream(fileName, FileMode.Open); I can now get even over 300 thumbnails. Thanks a billion, I will use this method you recommended Image img = Image.FromStream(fs); – Basco Mar 23 '13 at 11:48
0

First of all, are you running out of memory ? Cause if you are then the error is valid.

If you are not running out of memory the first thing you will need to do is wrap the code in your foreach loop in a try/catch block as follows:

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

The reason for that is, as Jason Watkins mentioned in the comments it might as well be another form of error that just appears as an out of memory exception because of the lack of error messages in the Class.

coolmine
  • 4,427
  • 2
  • 33
  • 45