0

i am trying to create thumbnails. my path to original folder is: suppose I:\my images**, and i want to generate it to **i:\new images. i got two problem, first problem is that if my images folder contains subfolder then in the new images it should also be in the sub folder not as a parent folder .

  • second i got an Error.**A generic error occurred in GDI+.

    3rd i get this error: Out of memory.**

its a csharp console application

at System.Drawing.Image.Save(String filename, ImageCodecInfo encoder, EncoderParameters encoderParams)
at System.Drawing.Image.Save(String filename, ImageFormat format)
at ConsoleApplication1.Program.CreateThumbnail(String[] b, Double wid, Double hght, Boolean Isprint)

public void CreateThumbnail(string[] b, double wid, double hght, bool Isprint)
{
    string[] path;
    path = new string [64];
    path = b;
    string saveath = "i:\\check\\a test\\";
    for (int i = 0; i < b.Length; i++)
    {
        DirectoryInfo dir = new DirectoryInfo(path[i]);
        string dir1 = dir.ToString();
        dir1 = dir1.Substring(dir1.LastIndexOf("\\"));

        FileInfo[] files1 = dir.GetFiles();

        foreach (FileInfo f in files1)
        {
            string gh = f.ToString();
            try
            {
                System.Drawing.Image myThumbnail150;
                System.Drawing.Image.GetThumbnailImageAbort myCallback = new System.Drawing.Image.GetThumbnailImageAbort(ThumbnailCallback);
                System.Drawing.Image imagesize = System.Drawing.Image.FromFile(f.FullName);
                Bitmap bitmapNew = new Bitmap(imagesize);
                double maxWidth = wid;
                double maxHeight = hght;
                int w = imagesize.Width;
                int h = imagesize.Height;
                // Longest and shortest dimension 
                int longestDimension = (w > h) ? w : h;
                int shortestDimension = (w < h) ? w : h;
                // propotionality  
                float factor = ((float)longestDimension) / shortestDimension;
                // default width is greater than height    
                double newWidth = maxWidth;
                double newHeight = maxWidth / factor;
                // if height greater than width recalculate  
                if (w < h)
                {
                    newWidth = maxHeight / factor;
                    newHeight = maxHeight;
                }
                myThumbnail150 = bitmapNew.GetThumbnailImage((int)newWidth, (int)newHeight, myCallback, IntPtr.Zero);

                string ext = Path.GetExtension(f.Name);

                if (!Directory.Exists(saveath + dir1))
                {
                    Directory.CreateDirectory(saveath + dir1);
                    myThumbnail150.Save(saveath + dir1 + "\\" + f.Name.Replace(ext, ".Jpeg"), System.Drawing.Imaging.ImageFormat.Jpeg);
                }
                else if(Directory.Exists(saveath+dir1))
                {
                    myThumbnail150.Save(saveath + dir1+" \\"+ f.Name.Replace(ext, ".Jpeg"), System.Drawing.Imaging.ImageFormat.Jpeg);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("something went wrong" + ex.ToString());
            }
        }
    }
}
safi
  • 3,636
  • 8
  • 24
  • 37
  • Where exactly are you getting exceptions 2 and 3? I remember getting those exceptions while working with SQL Server Reporting Services building reports full of images. The exceptions fired after the process tried to consume more than 2gb of memory on a 32bit Windows install. Remember that processes are limited to how much memory they can address (no matter how much memory you actually have in your computer). Also, you might want to look into disposing your GDI objects. I've worked with unmanaged GDI+ before and you need to clean up after using the objects. – enriquein Mar 21 '11 at 20:32
  • @Ernriquein I get those error after processing of some file, let say the folder contains 30 images, after processing 17 images it gives this error. i have 64 bit windows 7 installed. – safi Mar 21 '11 at 20:37

2 Answers2

3

I have just refactored a bit the code and now it works (on my machine):

private static void CreateThumbnail(string[] b, double wid, double hght, bool Isprint)
{
    string saveAt = "D:\\check";
    foreach (string path in b)
    {
        var directory = new DirectoryInfo(path);
        string outputPath = Path.Combine(saveAt, directory.Name);
        foreach (FileInfo f in directory.GetFiles("*.*", SearchOption.AllDirectories))
        {
            if (f.DirectoryName != directory.FullName)
            {
                outputPath = Path.Combine(saveAt, directory.Name, f.Directory.Name);
            }
            if (!Directory.Exists(outputPath))
            {
                Directory.CreateDirectory(outputPath);
            }

            using (Image imagesize = Image.FromFile(f.FullName))
            using (Bitmap bitmapNew = new Bitmap(imagesize))
            {
                double maxWidth = wid;
                double maxHeight = hght;
                int w = imagesize.Width;
                int h = imagesize.Height;
                // Longest and shortest dimension 
                int longestDimension = (w > h) ? w : h;
                int shortestDimension = (w < h) ? w : h;
                // propotionality  
                float factor = ((float)longestDimension) / shortestDimension;
                // default width is greater than height    
                double newWidth = maxWidth;
                double newHeight = maxWidth / factor;
                // if height greater than width recalculate  
                if (w < h)
                {
                    newWidth = maxHeight / factor;
                    newHeight = maxHeight;
                }

                string fileName = Path.Combine(outputPath, Path.GetFileNameWithoutExtension(f.Name) + ".jpeg");
                bitmapNew.GetThumbnailImage((int)newWidth, (int)newHeight, () => false, IntPtr.Zero)
                    .Save(fileName, System.Drawing.Imaging.ImageFormat.Jpeg);
            }
        }
    }
}

I have to say few things about your old code:

  • use foreach when possible;
  • avoid the first three lines, they are useless;
  • avoid unused variables;
  • keep your code as clean as possible;
as-cii
  • 12,819
  • 4
  • 41
  • 43
  • @As-CII thanks alot i will try it now, does it resolve the sub-folder issue as well? – safi Mar 21 '11 at 20:41
  • @AS-CII `Bitmap bitmapNew = new Bitmap(imagesize);` Out of memory at this line. – safi Mar 21 '11 at 20:47
  • I have tested it against some images and it worked quite well. How much do your images weigh? – as-cii Mar 21 '11 at 20:51
  • @AS-CII 270 MB, but it may varies it can be 1 Gb, but i am testing it now on 270 MB – safi Mar 21 '11 at 20:53
  • Ok, modified. I haven't noticed you weren't disposing images. – as-cii Mar 21 '11 at 20:54
  • @AS-CII, What i didnt get the point, did you changed the code? or add a dispose method? – safi Mar 21 '11 at 20:55
  • Yes, I have used some `using` statements. – as-cii Mar 21 '11 at 20:56
  • 2
    Using "using" statements to dispose is what I meant on my other comment on cleaning up after using the GDI+ objects. Good on AS-CII for providing a refactored version of the code to drive the point across. – enriquein Mar 21 '11 at 20:59
  • @AS-CII, thanks and its working now, but the subfolder isnt working, suppose the original folder contian, I:\images\cars, so in the thumbnails its is like I:\Thumb\images\Cars, I:\Thumb\cars. and it also exist – safi Mar 21 '11 at 21:10
  • @AS-CII hi, I am looking forward to solve the issue with recursive folder reading as currently it is not:) – safi Mar 22 '11 at 14:49
1

About the "GDI+ generic error" and the "Out Of Memory" exceptions, you should take a look at that link on SO: What is the "best" way to create a thumbnail using ASP.NET?

You must use the C# using statement to make sure unmanaged GDI+ resources underneath the .NET surface are freed as quickly as possible to avoid out of memory errors.

The GDI+ generic can happen if the image cannot be converted for example.

Community
  • 1
  • 1
Simon Mourier
  • 132,049
  • 21
  • 248
  • 298