Saturday, March 23, 2013

Get thumbnails without reading the entire image

I just thought this could be useful to someone, i was searching for a method to read the thumbnail data of a Jpeg file without loading the entire file into memory, and i stumbled upon this code written by Kourosh Derakshan (Extract thumbnail image from a file without reading the whole file). The only problem was that i needed the thumbnails to have the correct orientation based on the EXIF data of the photo, so i modified it to implement that feature.
private const int THUMBNAIL_DATA = 0x501B;
private const int ORIENTATION_DATA = 0x0112;

public static Image GetThumbnail(string path)
{
    try
    {
        // Please do not remove :)
        // Written by Kourosh Derakshan
        // Modified by Phate for automatic exif orientation
        FileStream fs = File.OpenRead(path);
        Image img = Image.FromStream(fs, false, false);
        // Last parameter tells GDI+ not the load the actual image data

        // GDI+ throws an error if we try to read a property when the image
        // doesn't have that property. Check to make sure the thumbnail property
        // item exists.
        bool propertyFound = false, orientFound = false;
        for (int i = 0; i < img.PropertyIdList.Length; i++)
        {
            if (img.PropertyIdList[i] == ORIENTATION_DATA)
            {
                orientFound = true;
            }
            if (img.PropertyIdList[i] == THUMBNAIL_DATA)
            {
                propertyFound = true;
                break;
            }
        }

        if (!propertyFound)
        {
            fs.Dispose();
            img.Dispose();
            return null;
        }

        PropertyItem o = null;
        if (orientFound)
            o = img.GetPropertyItem(ORIENTATION_DATA);

        PropertyItem p = img.GetPropertyItem(THUMBNAIL_DATA);
        fs.Close();
        img.Dispose();


        // The image data is in the form of a byte array. Write all 
        // the bytes to a stream and create a new image from that stream
        byte[] imageBytes = p.Value;
        MemoryStream stream = new MemoryStream(imageBytes.Length);
        stream.Write(imageBytes, 0, imageBytes.Length);

        Image temp = Image.FromStream(stream);

        if (o != null && Form1.ini.IniReadValue("settings", "automaticEXIF") == "true")
        {
            switch (int.Parse(string.Format("{0}", BitConverter.ToInt16(o.Value, 0))))
            {
                case 1:
                    temp.RotateFlip(RotateFlipType.RotateNoneFlipNone);
                    break;
                case 2:
                    temp.RotateFlip(RotateFlipType.RotateNoneFlipX);
                    break;
                case 3:
                    temp.RotateFlip(RotateFlipType.Rotate180FlipNone);
                    break;
                case 4:
                    temp.RotateFlip(RotateFlipType.Rotate180FlipX);
                    break;
                case 5:
                    temp.RotateFlip(RotateFlipType.Rotate90FlipX);
                    break;
                case 6:
                    temp.RotateFlip(RotateFlipType.Rotate90FlipNone);
                    break;
                case 7:
                    temp.RotateFlip(RotateFlipType.Rotate270FlipX);
                    break;
                case 8:
                    temp.RotateFlip(RotateFlipType.Rotate270FlipNone);
                    break;
                default:
                    temp.RotateFlip(RotateFlipType.RotateNoneFlipNone);
                    break;
            }
        }
        return temp;
    }
    catch (Exception) { return null; }
}

No comments:

Post a Comment

prettyprint