views:

296

answers:

3

I know it sounds weird. I have a photo gallery that saves image info(url, name, date modified...) from the hard disk into an in memory collection.

The thing is i want to have the image width/height stored into that collection. I can get it for each file using the Drawing.Image class. But considering the gallery can get quite big, creating a new image object for each file is going to reduce performance significantly.

any ideas?, thanks

+2  A: 

It's been a LONG time since I did raw processing of image files, but I would think that with the most common formats (GIF, BMP, JPG, etc...), you can probably find the height/width within the first few hundred bytes (or less) of the file. You'd have to do some coding to process the header information (probably tons of examples online), but it should speed up your process significantly vs. reading the entire image into memory.

Patrick Steele
A: 

If you want to get that information without actually constructing an Image object instance for each image, you'll need to write code that reads each individual image file and extracts the information. Although certainly possible, you'll find it somewhat involved. First, you'll need code that reads the first few bytes of the file to determine what type of image (.bmp, .gif, .png, .jpg, etc.) is contained in the file, and then you'll need special code to extract the information for each image type that you support.

Whereas the above would almost certainly be faster than code that loads the entire image, extracts the relevant data, and then destroys the image, I can't say how much faster. It's quite possible that the execution time savings doesn't justify the amount of time you'll put into such a solution.

Were I writing this program, my first cut would do as ChrisF suggested, and write something like:

foreach (string filename in ImageFilenames)
{
    using (Bitmap bmp = new Bitmap(filename))
    {
        // extract and store needed information
    }
}

Once you get that working, you can decide if it's fast enough for your purposes. If it's not, then I would suggest a test where you modify that loop to simulate extracting the information by reading the first kilobyte or so from each file:

foreach (string filename in ImageFilenames)
{
    using (File f = File.OpenRead(filename))
    {
        // read the first 1K from the file
        // store some placeholder data for height/width
    }
}

If that performs significantly faster than the first, then it's probably worth investigating the possibility of doing your own image header parsing. Be aware, though, that you're opening a big can of worms. Image header parsing can get quite involved.

Jim Mischel
+1  A: 

Extract information from images like Windows Explorer does.

Take a look here:

or here:

Or you can also read the extended file properties with the following:

public static void Main(string[] args)
{
    List<string> arrHeaders = new List<string>();    
    Shell32.Shell shell = new Shell32.Shell();
    Shell32.Folder objFolder = shell.NameSpace(@"C:\temp\testprop");

    for( int i = 0; i < short.MaxValue; i++) {
        string header = objFolder.GetDetailsOf(null, i);
        if (String.IsNullOrEmpty(header)) break;
        arrHeaders.Add(header);
    }

    foreach(Shell32.FolderItem2 item in objFolder.Items()) {
        for (int i = 0; i < arrHeaders.Count; i++) {
            Console.WriteLine("{0}\t{1}: {2}", i, 
                arrHeaders[i], objFolder.GetDetailsOf(item, i));
        }
    }
}
serhio