Loading

毫秒级的时间处理上G的图片(生成缩略图)

测试环境:

测试图片(30M):

测试计时方法:

Stopwatch sw1 = new Stopwatch();
sw1.Start();
//TODO......
sw1.Stop();
string xx = sw1.ElapsedMilliseconds.ToString();
MessageBox.Show(xx);


方法一,(1张30M图片,用时799毫秒)

public Image getThumbNailUsingGetThumbnailImage(string fileName)
{
    Image img = Image.FromFile(fileName);
    return img.GetThumbnailImage(300, 300, null, IntPtr.Zero);
}


方法二,(1张30M图片,用时1329毫秒)

public Image createThumbnailUsingGDI(ref Image imgPhoto, int destWidth, int destHeight)
{
    int sourceX = 0;
    int sourceY = 0;

    int destX = 0;
    int destY = 0;
    int sourceWidth = imgPhoto.Width;
    int sourceHeight = imgPhoto.Height;

    Bitmap b = new Bitmap(destWidth, destHeight);

    Graphics grPhoto = Graphics.FromImage(b);

    grPhoto.FillRectangle(Brushes.DarkGray, new Rectangle(destX, destY, destWidth, destHeight));
    grPhoto.DrawLine(new Pen(Brushes.LightGray), new Point(0, destHeight - 1), new Point(destWidth, destHeight - 1));
    grPhoto.DrawLine(new Pen(Brushes.LightGray), new Point(destWidth - 1, 0), new Point(destWidth - 1, destHeight));
    //shade right
    grPhoto.FillRectangle(Brushes.White, new Rectangle(destWidth - 3, 0, 7, 2));
    grPhoto.FillRectangle(Brushes.White, new Rectangle(destWidth - 2, 0, 7, 4));
    grPhoto.FillRectangle(Brushes.White, new Rectangle(destWidth - 1, 0, 7, 6));

    //shade botton
    grPhoto.FillRectangle(Brushes.White, new Rectangle(0, destHeight - 3, 2, 7));
    grPhoto.FillRectangle(Brushes.White, new Rectangle(0, destHeight - 2, 4, 7));
    grPhoto.FillRectangle(Brushes.White, new Rectangle(0, destHeight - 1, 6, 7));
    grPhoto.DrawImage(imgPhoto, new Rectangle(destX + 2, destY + 2, destWidth - 7, destHeight - 7), new Rectangle(sourceX, sourceY, sourceWidth, sourceHeight), GraphicsUnit.Pixel);

    grPhoto.Dispose();
    return b;

}


方法三,(1张30M图片,用时1636毫秒)

public Image getThumbNailWithFrame(string fileName)
{
    FileStream fs = new FileStream(fileName, FileMode.Open);
    Image im = Image.FromStream(fs);
    Size szMax = new Size(300, 300);
    Size sz = getProportionalSize(szMax, im.Size);
    // superior image quality   
    Bitmap bmpResized = new Bitmap(sz.Width, sz.Height);
    using (Graphics g = Graphics.FromImage(bmpResized))
    {
        g.InterpolationMode = InterpolationMode.HighQualityBicubic;
        g.FillRectangle(Brushes.White, 0, 0, sz.Width, sz.Height);
        int FrameWidth = 5;//decides the frame border width
        g.DrawRectangle(new Pen(Color.Silver, FrameWidth - 2), 0, 0, sz.Width - 1, sz.Height - 1);
        FrameWidth += 5;//decide the frame width
        g.DrawImage(im, new Rectangle(FrameWidth, FrameWidth, sz.Width - FrameWidth * 2, sz.Height - FrameWidth * 2), new Rectangle(Point.Empty, im.Size), GraphicsUnit.Pixel);
    }
    im.Dispose(); im = null;
    fs.Close(); fs.Dispose(); fs = null;
    return bmpResized;
}

private Size getProportionalSize(Size szMax, Size szReal)
{
    int nWidth;
    int nHeight;
    double sMaxRatio;
    double sRealRatio;

    if (szMax.Width < 1 || szMax.Height < 1 || szReal.Width < 1 || szReal.Height < 1)
        return Size.Empty;

    sMaxRatio = (double)szMax.Width / (double)szMax.Height;
    sRealRatio = (double)szReal.Width / (double)szReal.Height;

    if (sMaxRatio < sRealRatio)
    {
        nWidth = Math.Min(szMax.Width, szReal.Width);
        nHeight = (int)Math.Round(nWidth / sRealRatio);
    }
    else
    {
        nHeight = Math.Min(szMax.Height, szReal.Height);
        nWidth = (int)Math.Round(nHeight * sRealRatio);
    }

    return new Size(nWidth, nHeight);
}


方法四,(1张30M图片,用时1664毫秒)

public Image getThumbNail(string fileName)
{
    FileStream fs = new FileStream(fileName, FileMode.Open);
    Image im = Image.FromStream(fs);
    Size szMax = new Size(300, 300);
    Size sz = getProportionalSize(szMax, im.Size);
    // superior image quality   
    Bitmap bmpResized = new Bitmap(sz.Width, sz.Height);
    using (Graphics g = Graphics.FromImage(bmpResized))
    {
        g.InterpolationMode = InterpolationMode.HighQualityBicubic;
        g.DrawImage(
            im,
            new Rectangle(Point.Empty, sz),
            new Rectangle(Point.Empty, im.Size),
            GraphicsUnit.Pixel);
    }
    im.Dispose(); im = null;
    fs.Close(); fs.Dispose(); fs = null;
    return bmpResized;
}

private Size getProportionalSize(Size szMax, Size szReal)
{
    int nWidth;
    int nHeight;
    double sMaxRatio;
    double sRealRatio;

    if (szMax.Width < 1 || szMax.Height < 1 || szReal.Width < 1 || szReal.Height < 1)
        return Size.Empty;

    sMaxRatio = (double)szMax.Width / (double)szMax.Height;
    sRealRatio = (double)szReal.Width / (double)szReal.Height;

    if (sMaxRatio < sRealRatio)
    {
        nWidth = Math.Min(szMax.Width, szReal.Width);
        nHeight = (int)Math.Round(nWidth / sRealRatio);
    }
    else
    {
        nHeight = Math.Min(szMax.Height, szReal.Height);
        nWidth = (int)Math.Round(nHeight * sRealRatio);
    }

    return new Size(nWidth, nHeight);
}


方法五,(1张30M图片,用时735毫秒)

public Image createThumbFromProperty(string file)
{
    Image image = new Bitmap(file);
    Image Thumb = null;
    PropertyItem[] propItems = image.PropertyItems;
    foreach (PropertyItem propItem in propItems)
    {
        if (propItem.Id == 0x501B)
        {
            byte[] imageBytes = propItem.Value;
            MemoryStream stream = new MemoryStream(imageBytes.Length);
            stream.Write(imageBytes, 0, imageBytes.Length);
            Thumb = Image.FromStream(stream);
            break;
        }
    }
    return Thumb;
}


方法六,(50张30M图片,237毫秒)

using System;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;

//网址:https://www.experts-exchange.com/questions/21789724/How-to-create-thumbnail.html
namespace 缩略图查看
{
    public class ShellThumbnail : IDisposable
    {

        [Flags]
        private enum ESTRRET
        {
            STRRET_WSTR = 0,
            STRRET_OFFSET = 1,
            STRRET_CSTR = 2
        }

        [Flags]
        private enum ESHCONTF
        {
            SHCONTF_FOLDERS = 32,
            SHCONTF_NONFOLDERS = 64,
            SHCONTF_INCLUDEHIDDEN = 128,
        }

        [Flags]
        private enum ESHGDN
        {
            SHGDN_NORMAL = 0,
            SHGDN_INFOLDER = 1,
            SHGDN_FORADDRESSBAR = 16384,
            SHGDN_FORPARSING = 32768
        }

        [Flags]
        private enum ESFGAO
        {
            SFGAO_CANCOPY = 1,
            SFGAO_CANMOVE = 2,
            SFGAO_CANLINK = 4,
            SFGAO_CANRENAME = 16,
            SFGAO_CANDELETE = 32,
            SFGAO_HASPROPSHEET = 64,
            SFGAO_DROPTARGET = 256,
            SFGAO_CAPABILITYMASK = 375,
            SFGAO_LINK = 65536,
            SFGAO_SHARE = 131072,
            SFGAO_READONLY = 262144,
            SFGAO_GHOSTED = 524288,
            SFGAO_DISPLAYATTRMASK = 983040,
            SFGAO_FILESYSANCESTOR = 268435456,
            SFGAO_FOLDER = 536870912,
            SFGAO_FILESYSTEM = 1073741824,
            SFGAO_HASSUBFOLDER = -2147483648,
            SFGAO_CONTENTSMASK = -2147483648,
            SFGAO_VALIDATE = 16777216,
            SFGAO_REMOVABLE = 33554432,
            SFGAO_COMPRESSED = 67108864,
        }

        private enum EIEIFLAG
        {
            IEIFLAG_ASYNC = 1,
            IEIFLAG_CACHE = 2,
            IEIFLAG_ASPECT = 4,
            IEIFLAG_OFFLINE = 8,
            IEIFLAG_GLEAM = 16,
            IEIFLAG_SCREEN = 32,
            IEIFLAG_ORIGSIZE = 64,
            IEIFLAG_NOSTAMP = 128,
            IEIFLAG_NOBORDER = 256,
            IEIFLAG_QUALITY = 512
        }

        [StructLayout(LayoutKind.Sequential, Pack = 4, Size = 0, CharSet = CharSet.Auto)]
        private struct STRRET_CSTR
        {
            public ESTRRET uType;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 520)]
            public byte[] cStr;
        }

        [StructLayout(LayoutKind.Explicit, CharSet = CharSet.Auto)]
        private struct STRRET_ANY
        {
            [FieldOffset(0)]
            public ESTRRET uType;
            [FieldOffset(4)]
            public IntPtr pOLEString;
        }
        [StructLayoutAttribute(LayoutKind.Sequential)]
        private struct SIZE
        {
            public int cx;
            public int cy;
        }

        [ComImport(), Guid("00000000-0000-0000-C000-000000000046")]
        [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
        private interface IUnknown
        {

            [PreserveSig()]
            IntPtr QueryInterface(ref Guid riid, ref IntPtr pVoid);

            [PreserveSig()]
            IntPtr AddRef();

            [PreserveSig()]
            IntPtr Release();
        }

        [ComImportAttribute()]
        [GuidAttribute("00000002-0000-0000-C000-000000000046")]
        [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
        private interface IMalloc
        {

            [PreserveSig()]
            IntPtr Alloc(int cb);

            [PreserveSig()]
            IntPtr Realloc(IntPtr pv, int cb);

            [PreserveSig()]
            void Free(IntPtr pv);

            [PreserveSig()]
            int GetSize(IntPtr pv);

            [PreserveSig()]
            int DidAlloc(IntPtr pv);

            [PreserveSig()]
            void HeapMinimize();
        }

        [ComImportAttribute()]
        [GuidAttribute("000214F2-0000-0000-C000-000000000046")]
        [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
        private interface IEnumIDList
        {

            [PreserveSig()]
            int Next(int celt, ref IntPtr rgelt, ref int pceltFetched);

            void Skip(int celt);

            void Reset();

            void Clone(ref IEnumIDList ppenum);
        }

        [ComImportAttribute()]
        [GuidAttribute("000214E6-0000-0000-C000-000000000046")]
        [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
        private interface IShellFolder
        {

            void ParseDisplayName(IntPtr hwndOwner, IntPtr pbcReserved,
                [MarshalAs(UnmanagedType.LPWStr)]string lpszDisplayName,
                ref int pchEaten, ref IntPtr ppidl, ref int pdwAttributes);

            void EnumObjects(IntPtr hwndOwner,
                [MarshalAs(UnmanagedType.U4)]ESHCONTF grfFlags,
                ref IEnumIDList ppenumIDList);

            void BindToObject(IntPtr pidl, IntPtr pbcReserved, ref Guid riid,
                ref IShellFolder ppvOut);

            void BindToStorage(IntPtr pidl, IntPtr pbcReserved, ref Guid riid, IntPtr ppvObj);

            [PreserveSig()]
            int CompareIDs(IntPtr lParam, IntPtr pidl1, IntPtr pidl2);

            void CreateViewObject(IntPtr hwndOwner, ref Guid riid,
                IntPtr ppvOut);

            void GetAttributesOf(int cidl, IntPtr apidl,
                [MarshalAs(UnmanagedType.U4)]ref ESFGAO rgfInOut);

            void GetUIObjectOf(IntPtr hwndOwner, int cidl, ref IntPtr apidl, ref Guid riid, ref int prgfInOut, ref IUnknown ppvOut);

            void GetDisplayNameOf(IntPtr pidl,
                [MarshalAs(UnmanagedType.U4)]ESHGDN uFlags,
                ref STRRET_CSTR lpName);

            void SetNameOf(IntPtr hwndOwner, IntPtr pidl,
                [MarshalAs(UnmanagedType.LPWStr)]string lpszName,
                [MarshalAs(UnmanagedType.U4)] ESHCONTF uFlags,
                ref IntPtr ppidlOut);
        }
        [ComImportAttribute(), GuidAttribute("BB2E617C-0920-11d1-9A0B-00C04FC2D6C1"), InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
        private interface IExtractImage
        {
            void GetLocation([Out(), MarshalAs(UnmanagedType.LPWStr)]
    StringBuilder pszPathBuffer, int cch, ref int pdwPriority, ref SIZE prgSize, int dwRecClrDepth, ref int pdwFlags);

            void Extract(ref IntPtr phBmpThumbnail);
        }

        private class UnmanagedMethods
        {

            [DllImport("shell32", CharSet = CharSet.Auto)]
            internal extern static int SHGetMalloc(ref IMalloc ppMalloc);

            [DllImport("shell32", CharSet = CharSet.Auto)]
            internal extern static int SHGetDesktopFolder(ref IShellFolder ppshf);

            [DllImport("shell32", CharSet = CharSet.Auto)]
            internal extern static int SHGetPathFromIDList(IntPtr pidl, StringBuilder pszPath);

            [DllImport("gdi32", CharSet = CharSet.Auto)]
            internal extern static int DeleteObject(IntPtr hObject);

        }

        ~ShellThumbnail()
        {
            Dispose();
        }

        private IMalloc alloc = null;
        private bool disposed = false;
        private Size _desiredSize = new Size(100, 100);
        private Bitmap _thumbNail;

        public Bitmap ThumbNail
        {
            get
            {
                return _thumbNail;
            }
        }

        public Size DesiredSize
        {
            get { return _desiredSize; }
            set { _desiredSize = value; }
        }
        private IMalloc Allocator
        {
            get
            {
                if (!disposed)
                {
                    if (alloc == null)
                    {
                        UnmanagedMethods.SHGetMalloc(ref alloc);
                    }
                }
                else
                {
                    Debug.Assert(false, "Object has been disposed.");
                }
                return alloc;
            }
        }

        public Bitmap GetThumbnail(string fileName)
        {
            if (string.IsNullOrEmpty(fileName))
                return null;

            if (!File.Exists(fileName) && !Directory.Exists(fileName))
            {
                throw new FileNotFoundException(string.Format("The file '{0}' does not exist", fileName), fileName);
            }
            if (_thumbNail != null)
            {
                _thumbNail.Dispose();
                _thumbNail = null;
            }
            IShellFolder folder = null;
            try
            {
                folder = getDesktopFolder;
            }
            catch (Exception ex)
            {
                throw ex;
            }
            if (folder != null)
            {
                IntPtr pidlMain = IntPtr.Zero;
                try
                {
                    int cParsed = 0;
                    int pdwAttrib = 0;
                    string filePath = Path.GetDirectoryName(fileName);
                    folder.ParseDisplayName(IntPtr.Zero, IntPtr.Zero, filePath, ref cParsed, ref pidlMain, ref pdwAttrib);
                }
                catch (Exception ex)
                {
                    Marshal.ReleaseComObject(folder);
                    throw ex;
                }
                if (pidlMain != IntPtr.Zero)
                {
                    Guid iidShellFolder = new Guid("000214E6-0000-0000-C000-000000000046");
                    IShellFolder item = null;
                    try
                    {
                        folder.BindToObject(pidlMain, IntPtr.Zero, ref iidShellFolder, ref item);
                    }
                    catch (Exception ex)
                    {
                        Marshal.ReleaseComObject(folder);
                        Allocator.Free(pidlMain);
                        throw ex;
                    }
                    if (item != null)
                    {
                        IEnumIDList idEnum = null;
                        try
                        {
                            item.EnumObjects(IntPtr.Zero, (ESHCONTF.SHCONTF_FOLDERS | ESHCONTF.SHCONTF_NONFOLDERS), ref idEnum);
                        }
                        catch (Exception ex)
                        {
                            Marshal.ReleaseComObject(folder);
                            Allocator.Free(pidlMain);
                            throw ex;
                        }
                        if (idEnum != null)
                        {
                            int hRes = 0;
                            IntPtr pidl = IntPtr.Zero;
                            int fetched = 0;
                            bool complete = false;
                            while (!complete)
                            {
                                hRes = idEnum.Next(1, ref pidl, ref fetched);
                                if (hRes != 0)
                                {
                                    pidl = IntPtr.Zero;
                                    complete = true;
                                }
                                else
                                {
                                    if (_getThumbNail(fileName, pidl, item))
                                    {
                                        complete = true;
                                    }
                                }
                                if (pidl != IntPtr.Zero)
                                {
                                    Allocator.Free(pidl);
                                }
                            }
                            Marshal.ReleaseComObject(idEnum);
                        }
                        Marshal.ReleaseComObject(item);
                    }
                    Allocator.Free(pidlMain);
                }
                Marshal.ReleaseComObject(folder);
            }
            return ThumbNail;
        }

        private bool _getThumbNail(string file, IntPtr pidl, IShellFolder item)
        {
            IntPtr hBmp = IntPtr.Zero;
            IExtractImage extractImage = null;
            try
            {
                string pidlPath = PathFromPidl(pidl);
                if (Path.GetFileName(pidlPath).ToUpper().Equals(Path.GetFileName(file).ToUpper()))
                {
                    IUnknown iunk = null;
                    int prgf = 0;
                    Guid iidExtractImage = new Guid("BB2E617C-0920-11d1-9A0B-00C04FC2D6C1");
                    item.GetUIObjectOf(IntPtr.Zero, 1, ref pidl, ref iidExtractImage, ref prgf, ref iunk);
                    extractImage = (IExtractImage)iunk;
                    if (extractImage != null)
                    {
                        Console.WriteLine("Got an IExtractImage object!");
                        SIZE sz = new SIZE();
                        sz.cx = DesiredSize.Width;
                        sz.cy = DesiredSize.Height;
                        StringBuilder location = new StringBuilder(260, 260);
                        int priority = 0;
                        int requestedColourDepth = 32;
                        EIEIFLAG flags = EIEIFLAG.IEIFLAG_ASPECT | EIEIFLAG.IEIFLAG_SCREEN;
                        int uFlags = (int)flags;
                        try
                        {
                            extractImage.GetLocation(location, location.Capacity, ref priority, ref sz, requestedColourDepth, ref uFlags);
                            extractImage.Extract(ref hBmp);
                        }
                        catch (System.Runtime.InteropServices.COMException ex)
                        {

                        }
                        if (hBmp != IntPtr.Zero)
                        {
                            _thumbNail = Bitmap.FromHbitmap(hBmp);
                        }
                        Marshal.ReleaseComObject(extractImage);
                        extractImage = null;
                    }
                    return true;
                }
                else
                {
                    return false;
                }
            }
            catch (Exception ex)
            {
                if (hBmp != IntPtr.Zero)
                {
                    UnmanagedMethods.DeleteObject(hBmp);
                }
                if (extractImage != null)
                {
                    Marshal.ReleaseComObject(extractImage);
                }
                throw ex;
            }
        }

        private string PathFromPidl(IntPtr pidl)
        {
            StringBuilder path = new StringBuilder(260, 260);
            int result = UnmanagedMethods.SHGetPathFromIDList(pidl, path);
            if (result == 0)
            {
                return string.Empty;
            }
            else
            {
                return path.ToString();
            }
        }

        private IShellFolder getDesktopFolder
        {
            get
            {
                IShellFolder ppshf = null;
                int r = UnmanagedMethods.SHGetDesktopFolder(ref ppshf);
                return ppshf;
            }
        }

        public void Dispose()
        {
            if (!disposed)
            {
                if (alloc != null)
                {
                    Marshal.ReleaseComObject(alloc);
                }
                alloc = null;
                if (_thumbNail != null)
                {
                    _thumbNail.Dispose();
                }
                disposed = true;
            }
        }
    }
}
View Code


方法七,(50张30M图片,96毫秒)

速度最快,只要兄弟们推荐的多,我下午公布源码。^_^ 

 

最快速度源码,请接收

using System;
using System.IO;
using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
using System.Drawing.Drawing2D;

namespace 缩略图查看
{
    /// <summary>
    /// Allows reading of embedded thumbnail image from the EXIF information in an image.
    /// </summary>
    //public abstract class ExifThumbReader
    public class ExifThumbReader
    {
        // GDI plus functions
        [DllImport("gdiplus.dll", CharSet = CharSet.Unicode, ExactSpelling = true)]
        internal static extern int GdipGetPropertyItem(IntPtr image, int propid, int size, IntPtr buffer);

        [DllImport("gdiplus.dll", CharSet = CharSet.Unicode, ExactSpelling = true)]
        internal static extern int GdipGetPropertyItemSize(IntPtr image, int propid, out int size);

        [DllImport("gdiplus.dll", CharSet = CharSet.Unicode, ExactSpelling = true)]
        internal static extern int GdipLoadImageFromFile(string filename, out IntPtr image);

        [DllImport("gdiplus.dll", EntryPoint = "GdipDisposeImage", CharSet = CharSet.Unicode, ExactSpelling = true)]
        private static extern int GdipDisposeImage(IntPtr image);

        // EXIT tag value for thumbnail data. Value specified by EXIF standard
        private static int THUMBNAIL_DATA = 0x501B;

        /// <summary>
        /// Reads the thumbnail in the given image. If no thumbnail is found, returns null
        /// </summary>
        //public static Image ReadThumb(string imagePath)
        public  Image ReadThumb(string imagePath)
        {
            const int GDI_ERR_PROP_NOT_FOUND = 19;    // Property not found error
            const int GDI_ERR_OUT_OF_MEMORY = 3;

            IntPtr hImage = IntPtr.Zero;
            IntPtr buffer = IntPtr.Zero;    // Holds the thumbnail data
            int ret;
            ret = GdipLoadImageFromFile(imagePath, out hImage);

            try
            {
                if (ret != 0)
                    throw createException(ret);
                
                int propSize;
               
                ret = GdipGetPropertyItemSize(hImage, THUMBNAIL_DATA, out propSize);
                // Image has no thumbnail data in it. Return null
                if (ret == GDI_ERR_PROP_NOT_FOUND)
                    return null;
                if (ret != 0)
                    throw createException(ret);


                // Allocate a buffer in memory
                buffer = Marshal.AllocHGlobal(propSize);
                if (buffer == IntPtr.Zero)
                    throw createException(GDI_ERR_OUT_OF_MEMORY);

                ret = GdipGetPropertyItem(hImage, THUMBNAIL_DATA, propSize, buffer);
                if (ret != 0)
                    throw createException(ret);

                // buffer has the thumbnail data. Now we have to convert it to
                // an Image
                return convertFromMemory(buffer);
            }

            finally
            {
                // Free the buffer
                if (buffer != IntPtr.Zero)
                    Marshal.FreeHGlobal(buffer);

                GdipDisposeImage(hImage);
            }
        }

        /// <summary>
        /// Generates an exception depending on the GDI+ error codes (I removed some error
        /// codes)
        /// </summary>
        private static Exception createException(int gdipErrorCode)
        {
            switch (gdipErrorCode)
            {
                case 1:
                    return new ExternalException("Gdiplus Generic Error", -2147467259);
                case 2:
                    return new ArgumentException("Gdiplus Invalid Parameter");
                case 3:
                    return new OutOfMemoryException("Gdiplus Out Of Memory");
                case 4:
                    return new InvalidOperationException("Gdiplus Object Busy");
                case 5:
                    return new OutOfMemoryException("Gdiplus Insufficient Buffer");
                case 7:
                    return new ExternalException("Gdiplus Generic Error", -2147467259);
                case 8:
                    return new InvalidOperationException("Gdiplus Wrong State");
                case 9:
                    return new ExternalException("Gdiplus Aborted", -2147467260);
                case 10:
                    return new FileNotFoundException("Gdiplus File Not Found");
                case 11:
                    return new OverflowException("Gdiplus Over flow");
                case 12:
                    return new ExternalException("Gdiplus Access Denied", -2147024891);
                case 13:
                    return new ArgumentException("Gdiplus Unknown Image Format");
                case 18:
                    return new ExternalException("Gdiplus Not Initialized", -2147467259);
                case 20:
                    return new ArgumentException("Gdiplus Property Not Supported Error");
            }

            return new ExternalException("Gdiplus Unknown Error", -2147418113);
        }



        /// <summary>
        /// Converts the IntPtr buffer to a property item and then converts its 
        /// value to a Drawing.Image item
        /// </summary>
        private static Image convertFromMemory(IntPtr thumbData)
        {
            propertyItemInternal prop =
                (propertyItemInternal)Marshal.PtrToStructure
                (thumbData, typeof(propertyItemInternal));

            // 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 = prop.Value;
            MemoryStream stream = new MemoryStream(imageBytes.Length);
            stream.Write(imageBytes, 0, imageBytes.Length);

            return Image.FromStream(stream);
        }

        /// <summary>
        /// Used in Marshal.PtrToStructure().
        /// We need this dummy class because Imaging.PropertyItem is not a "blittable"
        /// class and Marshal.PtrToStructure only accepted blittable classes.
        /// (It's not blitable because it uses a byte[] array and that's not a blittable
        /// type. See MSDN for a definition of Blittable.)
        /// </summary>
        [StructLayout(LayoutKind.Sequential)]
        private class propertyItemInternal
        {
            public int id = 0;
            public int len = 0;
            public short type = 0;
            public IntPtr value = IntPtr.Zero;

            public byte[] Value
            {
                get
                {
                    byte[] bytes = new byte[(uint)len];
                    Marshal.Copy(value, bytes, 0, len);
                    return bytes;
                }
            }
        }
    }
}
View Code

 

测试结果:

方法 图片张数(张) 每张大小(M) 图片总大小 用时
方法一 50 30 1500M 39950毫秒=40秒
方法二 50 30 1500M 66450毫秒=66秒
方法三 50 30 1500M 81800毫秒=81秒
方法四 50 30 1500M 83200毫秒=83秒
方法五 50 30 1500M 36750毫秒=37秒
方法六 50 30 1500M 237毫秒
方法七 50 30 1500M 96毫秒
posted @ 2016-06-07 08:12  Sam Xiao  阅读(13765)  评论(79编辑  收藏  举报