测试环境:

测试图片(30M):

测试计时方法:

  1. Stopwatch sw1 = new Stopwatch();
  2. sw1.Start();
  3. //TODO......
  4. sw1.Stop();
  5. string xx = sw1.ElapsedMilliseconds.ToString();
  6. MessageBox.Show(xx);

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

  1. public Image getThumbNailUsingGetThumbnailImage(string fileName)
  2. {
  3. Image img = Image.FromFile(fileName);
  4. return img.GetThumbnailImage(, , null, IntPtr.Zero);
  5. }

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

  1. public Image createThumbnailUsingGDI(ref Image imgPhoto, int destWidth, int destHeight)
  2. {
  3. int sourceX = ;
  4. int sourceY = ;
  5.  
  6. int destX = ;
  7. int destY = ;
  8. int sourceWidth = imgPhoto.Width;
  9. int sourceHeight = imgPhoto.Height;
  10.  
  11. Bitmap b = new Bitmap(destWidth, destHeight);
  12.  
  13. Graphics grPhoto = Graphics.FromImage(b);
  14.  
  15. grPhoto.FillRectangle(Brushes.DarkGray, new Rectangle(destX, destY, destWidth, destHeight));
  16. grPhoto.DrawLine(new Pen(Brushes.LightGray), new Point(, destHeight - ), new Point(destWidth, destHeight - ));
  17. grPhoto.DrawLine(new Pen(Brushes.LightGray), new Point(destWidth - , ), new Point(destWidth - , destHeight));
  18. //shade right
  19. grPhoto.FillRectangle(Brushes.White, new Rectangle(destWidth - , , , ));
  20. grPhoto.FillRectangle(Brushes.White, new Rectangle(destWidth - , , , ));
  21. grPhoto.FillRectangle(Brushes.White, new Rectangle(destWidth - , , , ));
  22.  
  23. //shade botton
  24. grPhoto.FillRectangle(Brushes.White, new Rectangle(, destHeight - , , ));
  25. grPhoto.FillRectangle(Brushes.White, new Rectangle(, destHeight - , , ));
  26. grPhoto.FillRectangle(Brushes.White, new Rectangle(, destHeight - , , ));
  27. grPhoto.DrawImage(imgPhoto, new Rectangle(destX + , destY + , destWidth - , destHeight - ), new Rectangle(sourceX, sourceY, sourceWidth, sourceHeight), GraphicsUnit.Pixel);
  28.  
  29. grPhoto.Dispose();
  30. return b;
  31.  
  32. }

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

  1. public Image getThumbNailWithFrame(string fileName)
  2. {
  3. FileStream fs = new FileStream(fileName, FileMode.Open);
  4. Image im = Image.FromStream(fs);
  5. Size szMax = new Size(, );
  6. Size sz = getProportionalSize(szMax, im.Size);
  7. // superior image quality
  8. Bitmap bmpResized = new Bitmap(sz.Width, sz.Height);
  9. using (Graphics g = Graphics.FromImage(bmpResized))
  10. {
  11. g.InterpolationMode = InterpolationMode.HighQualityBicubic;
  12. g.FillRectangle(Brushes.White, , , sz.Width, sz.Height);
  13. int FrameWidth = ;//decides the frame border width
  14. g.DrawRectangle(new Pen(Color.Silver, FrameWidth - ), , , sz.Width - , sz.Height - );
  15. FrameWidth += ;//decide the frame width
  16. g.DrawImage(im, new Rectangle(FrameWidth, FrameWidth, sz.Width - FrameWidth * , sz.Height - FrameWidth * ), new Rectangle(Point.Empty, im.Size), GraphicsUnit.Pixel);
  17. }
  18. im.Dispose(); im = null;
  19. fs.Close(); fs.Dispose(); fs = null;
  20. return bmpResized;
  21. }
  22.  
  23. private Size getProportionalSize(Size szMax, Size szReal)
  24. {
  25. int nWidth;
  26. int nHeight;
  27. double sMaxRatio;
  28. double sRealRatio;
  29.  
  30. if (szMax.Width < || szMax.Height < || szReal.Width < || szReal.Height < )
  31. return Size.Empty;
  32.  
  33. sMaxRatio = (double)szMax.Width / (double)szMax.Height;
  34. sRealRatio = (double)szReal.Width / (double)szReal.Height;
  35.  
  36. if (sMaxRatio < sRealRatio)
  37. {
  38. nWidth = Math.Min(szMax.Width, szReal.Width);
  39. nHeight = (int)Math.Round(nWidth / sRealRatio);
  40. }
  41. else
  42. {
  43. nHeight = Math.Min(szMax.Height, szReal.Height);
  44. nWidth = (int)Math.Round(nHeight * sRealRatio);
  45. }
  46.  
  47. return new Size(nWidth, nHeight);
  48. }

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

  1. public Image getThumbNail(string fileName)
  2. {
  3. FileStream fs = new FileStream(fileName, FileMode.Open);
  4. Image im = Image.FromStream(fs);
  5. Size szMax = new Size(, );
  6. Size sz = getProportionalSize(szMax, im.Size);
  7. // superior image quality
  8. Bitmap bmpResized = new Bitmap(sz.Width, sz.Height);
  9. using (Graphics g = Graphics.FromImage(bmpResized))
  10. {
  11. g.InterpolationMode = InterpolationMode.HighQualityBicubic;
  12. g.DrawImage(
  13. im,
  14. new Rectangle(Point.Empty, sz),
  15. new Rectangle(Point.Empty, im.Size),
  16. GraphicsUnit.Pixel);
  17. }
  18. im.Dispose(); im = null;
  19. fs.Close(); fs.Dispose(); fs = null;
  20. return bmpResized;
  21. }
  22.  
  23. private Size getProportionalSize(Size szMax, Size szReal)
  24. {
  25. int nWidth;
  26. int nHeight;
  27. double sMaxRatio;
  28. double sRealRatio;
  29.  
  30. if (szMax.Width < || szMax.Height < || szReal.Width < || szReal.Height < )
  31. return Size.Empty;
  32.  
  33. sMaxRatio = (double)szMax.Width / (double)szMax.Height;
  34. sRealRatio = (double)szReal.Width / (double)szReal.Height;
  35.  
  36. if (sMaxRatio < sRealRatio)
  37. {
  38. nWidth = Math.Min(szMax.Width, szReal.Width);
  39. nHeight = (int)Math.Round(nWidth / sRealRatio);
  40. }
  41. else
  42. {
  43. nHeight = Math.Min(szMax.Height, szReal.Height);
  44. nWidth = (int)Math.Round(nHeight * sRealRatio);
  45. }
  46.  
  47. return new Size(nWidth, nHeight);
  48. }

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

  1. public Image createThumbFromProperty(string file)
  2. {
  3. Image image = new Bitmap(file);
  4. Image Thumb = null;
  5. PropertyItem[] propItems = image.PropertyItems;
  6. foreach (PropertyItem propItem in propItems)
  7. {
  8. if (propItem.Id == 0x501B)
  9. {
  10. byte[] imageBytes = propItem.Value;
  11. MemoryStream stream = new MemoryStream(imageBytes.Length);
  12. stream.Write(imageBytes, , imageBytes.Length);
  13. Thumb = Image.FromStream(stream);
  14. break;
  15. }
  16. }
  17. return Thumb;
  18. }

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

  1. using System;
  2. using System.Diagnostics;
  3. using System.Drawing;
  4. using System.IO;
  5. using System.Runtime.InteropServices;
  6. using System.Text;
  7.  
  8. //网址:https://www.experts-exchange.com/questions/21789724/How-to-create-thumbnail.html
  9. namespace 缩略图查看
  10. {
  11. public class ShellThumbnail : IDisposable
  12. {
  13.  
  14. [Flags]
  15. private enum ESTRRET
  16. {
  17. STRRET_WSTR = ,
  18. STRRET_OFFSET = ,
  19. STRRET_CSTR =
  20. }
  21.  
  22. [Flags]
  23. private enum ESHCONTF
  24. {
  25. SHCONTF_FOLDERS = ,
  26. SHCONTF_NONFOLDERS = ,
  27. SHCONTF_INCLUDEHIDDEN = ,
  28. }
  29.  
  30. [Flags]
  31. private enum ESHGDN
  32. {
  33. SHGDN_NORMAL = ,
  34. SHGDN_INFOLDER = ,
  35. SHGDN_FORADDRESSBAR = ,
  36. SHGDN_FORPARSING =
  37. }
  38.  
  39. [Flags]
  40. private enum ESFGAO
  41. {
  42. SFGAO_CANCOPY = ,
  43. SFGAO_CANMOVE = ,
  44. SFGAO_CANLINK = ,
  45. SFGAO_CANRENAME = ,
  46. SFGAO_CANDELETE = ,
  47. SFGAO_HASPROPSHEET = ,
  48. SFGAO_DROPTARGET = ,
  49. SFGAO_CAPABILITYMASK = ,
  50. SFGAO_LINK = ,
  51. SFGAO_SHARE = ,
  52. SFGAO_READONLY = ,
  53. SFGAO_GHOSTED = ,
  54. SFGAO_DISPLAYATTRMASK = ,
  55. SFGAO_FILESYSANCESTOR = ,
  56. SFGAO_FOLDER = ,
  57. SFGAO_FILESYSTEM = ,
  58. SFGAO_HASSUBFOLDER = -,
  59. SFGAO_CONTENTSMASK = -,
  60. SFGAO_VALIDATE = ,
  61. SFGAO_REMOVABLE = ,
  62. SFGAO_COMPRESSED = ,
  63. }
  64.  
  65. private enum EIEIFLAG
  66. {
  67. IEIFLAG_ASYNC = ,
  68. IEIFLAG_CACHE = ,
  69. IEIFLAG_ASPECT = ,
  70. IEIFLAG_OFFLINE = ,
  71. IEIFLAG_GLEAM = ,
  72. IEIFLAG_SCREEN = ,
  73. IEIFLAG_ORIGSIZE = ,
  74. IEIFLAG_NOSTAMP = ,
  75. IEIFLAG_NOBORDER = ,
  76. IEIFLAG_QUALITY =
  77. }
  78.  
  79. [StructLayout(LayoutKind.Sequential, Pack = , Size = , CharSet = CharSet.Auto)]
  80. private struct STRRET_CSTR
  81. {
  82. public ESTRRET uType;
  83. [MarshalAs(UnmanagedType.ByValArray, SizeConst = )]
  84. public byte[] cStr;
  85. }
  86.  
  87. [StructLayout(LayoutKind.Explicit, CharSet = CharSet.Auto)]
  88. private struct STRRET_ANY
  89. {
  90. [FieldOffset()]
  91. public ESTRRET uType;
  92. [FieldOffset()]
  93. public IntPtr pOLEString;
  94. }
  95. [StructLayoutAttribute(LayoutKind.Sequential)]
  96. private struct SIZE
  97. {
  98. public int cx;
  99. public int cy;
  100. }
  101.  
  102. [ComImport(), Guid("00000000-0000-0000-C000-000000000046")]
  103. [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
  104. private interface IUnknown
  105. {
  106.  
  107. [PreserveSig()]
  108. IntPtr QueryInterface(ref Guid riid, ref IntPtr pVoid);
  109.  
  110. [PreserveSig()]
  111. IntPtr AddRef();
  112.  
  113. [PreserveSig()]
  114. IntPtr Release();
  115. }
  116.  
  117. [ComImportAttribute()]
  118. [GuidAttribute("00000002-0000-0000-C000-000000000046")]
  119. [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
  120. private interface IMalloc
  121. {
  122.  
  123. [PreserveSig()]
  124. IntPtr Alloc(int cb);
  125.  
  126. [PreserveSig()]
  127. IntPtr Realloc(IntPtr pv, int cb);
  128.  
  129. [PreserveSig()]
  130. void Free(IntPtr pv);
  131.  
  132. [PreserveSig()]
  133. int GetSize(IntPtr pv);
  134.  
  135. [PreserveSig()]
  136. int DidAlloc(IntPtr pv);
  137.  
  138. [PreserveSig()]
  139. void HeapMinimize();
  140. }
  141.  
  142. [ComImportAttribute()]
  143. [GuidAttribute("000214F2-0000-0000-C000-000000000046")]
  144. [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
  145. private interface IEnumIDList
  146. {
  147.  
  148. [PreserveSig()]
  149. int Next(int celt, ref IntPtr rgelt, ref int pceltFetched);
  150.  
  151. void Skip(int celt);
  152.  
  153. void Reset();
  154.  
  155. void Clone(ref IEnumIDList ppenum);
  156. }
  157.  
  158. [ComImportAttribute()]
  159. [GuidAttribute("000214E6-0000-0000-C000-000000000046")]
  160. [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
  161. private interface IShellFolder
  162. {
  163.  
  164. void ParseDisplayName(IntPtr hwndOwner, IntPtr pbcReserved,
  165. [MarshalAs(UnmanagedType.LPWStr)]string lpszDisplayName,
  166. ref int pchEaten, ref IntPtr ppidl, ref int pdwAttributes);
  167.  
  168. void EnumObjects(IntPtr hwndOwner,
  169. [MarshalAs(UnmanagedType.U4)]ESHCONTF grfFlags,
  170. ref IEnumIDList ppenumIDList);
  171.  
  172. void BindToObject(IntPtr pidl, IntPtr pbcReserved, ref Guid riid,
  173. ref IShellFolder ppvOut);
  174.  
  175. void BindToStorage(IntPtr pidl, IntPtr pbcReserved, ref Guid riid, IntPtr ppvObj);
  176.  
  177. [PreserveSig()]
  178. int CompareIDs(IntPtr lParam, IntPtr pidl1, IntPtr pidl2);
  179.  
  180. void CreateViewObject(IntPtr hwndOwner, ref Guid riid,
  181. IntPtr ppvOut);
  182.  
  183. void GetAttributesOf(int cidl, IntPtr apidl,
  184. [MarshalAs(UnmanagedType.U4)]ref ESFGAO rgfInOut);
  185.  
  186. void GetUIObjectOf(IntPtr hwndOwner, int cidl, ref IntPtr apidl, ref Guid riid, ref int prgfInOut, ref IUnknown ppvOut);
  187.  
  188. void GetDisplayNameOf(IntPtr pidl,
  189. [MarshalAs(UnmanagedType.U4)]ESHGDN uFlags,
  190. ref STRRET_CSTR lpName);
  191.  
  192. void SetNameOf(IntPtr hwndOwner, IntPtr pidl,
  193. [MarshalAs(UnmanagedType.LPWStr)]string lpszName,
  194. [MarshalAs(UnmanagedType.U4)] ESHCONTF uFlags,
  195. ref IntPtr ppidlOut);
  196. }
  197. [ComImportAttribute(), GuidAttribute("BB2E617C-0920-11d1-9A0B-00C04FC2D6C1"), InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
  198. private interface IExtractImage
  199. {
  200. void GetLocation([Out(), MarshalAs(UnmanagedType.LPWStr)]
  201. StringBuilder pszPathBuffer, int cch, ref int pdwPriority, ref SIZE prgSize, int dwRecClrDepth, ref int pdwFlags);
  202.  
  203. void Extract(ref IntPtr phBmpThumbnail);
  204. }
  205.  
  206. private class UnmanagedMethods
  207. {
  208.  
  209. [DllImport("shell32", CharSet = CharSet.Auto)]
  210. internal extern static int SHGetMalloc(ref IMalloc ppMalloc);
  211.  
  212. [DllImport("shell32", CharSet = CharSet.Auto)]
  213. internal extern static int SHGetDesktopFolder(ref IShellFolder ppshf);
  214.  
  215. [DllImport("shell32", CharSet = CharSet.Auto)]
  216. internal extern static int SHGetPathFromIDList(IntPtr pidl, StringBuilder pszPath);
  217.  
  218. [DllImport("gdi32", CharSet = CharSet.Auto)]
  219. internal extern static int DeleteObject(IntPtr hObject);
  220.  
  221. }
  222.  
  223. ~ShellThumbnail()
  224. {
  225. Dispose();
  226. }
  227.  
  228. private IMalloc alloc = null;
  229. private bool disposed = false;
  230. private Size _desiredSize = new Size(, );
  231. private Bitmap _thumbNail;
  232.  
  233. public Bitmap ThumbNail
  234. {
  235. get
  236. {
  237. return _thumbNail;
  238. }
  239. }
  240.  
  241. public Size DesiredSize
  242. {
  243. get { return _desiredSize; }
  244. set { _desiredSize = value; }
  245. }
  246. private IMalloc Allocator
  247. {
  248. get
  249. {
  250. if (!disposed)
  251. {
  252. if (alloc == null)
  253. {
  254. UnmanagedMethods.SHGetMalloc(ref alloc);
  255. }
  256. }
  257. else
  258. {
  259. Debug.Assert(false, "Object has been disposed.");
  260. }
  261. return alloc;
  262. }
  263. }
  264.  
  265. public Bitmap GetThumbnail(string fileName)
  266. {
  267. if (string.IsNullOrEmpty(fileName))
  268. return null;
  269.  
  270. if (!File.Exists(fileName) && !Directory.Exists(fileName))
  271. {
  272. throw new FileNotFoundException(string.Format("The file '{0}' does not exist", fileName), fileName);
  273. }
  274. if (_thumbNail != null)
  275. {
  276. _thumbNail.Dispose();
  277. _thumbNail = null;
  278. }
  279. IShellFolder folder = null;
  280. try
  281. {
  282. folder = getDesktopFolder;
  283. }
  284. catch (Exception ex)
  285. {
  286. throw ex;
  287. }
  288. if (folder != null)
  289. {
  290. IntPtr pidlMain = IntPtr.Zero;
  291. try
  292. {
  293. int cParsed = ;
  294. int pdwAttrib = ;
  295. string filePath = Path.GetDirectoryName(fileName);
  296. folder.ParseDisplayName(IntPtr.Zero, IntPtr.Zero, filePath, ref cParsed, ref pidlMain, ref pdwAttrib);
  297. }
  298. catch (Exception ex)
  299. {
  300. Marshal.ReleaseComObject(folder);
  301. throw ex;
  302. }
  303. if (pidlMain != IntPtr.Zero)
  304. {
  305. Guid iidShellFolder = new Guid("000214E6-0000-0000-C000-000000000046");
  306. IShellFolder item = null;
  307. try
  308. {
  309. folder.BindToObject(pidlMain, IntPtr.Zero, ref iidShellFolder, ref item);
  310. }
  311. catch (Exception ex)
  312. {
  313. Marshal.ReleaseComObject(folder);
  314. Allocator.Free(pidlMain);
  315. throw ex;
  316. }
  317. if (item != null)
  318. {
  319. IEnumIDList idEnum = null;
  320. try
  321. {
  322. item.EnumObjects(IntPtr.Zero, (ESHCONTF.SHCONTF_FOLDERS | ESHCONTF.SHCONTF_NONFOLDERS), ref idEnum);
  323. }
  324. catch (Exception ex)
  325. {
  326. Marshal.ReleaseComObject(folder);
  327. Allocator.Free(pidlMain);
  328. throw ex;
  329. }
  330. if (idEnum != null)
  331. {
  332. int hRes = ;
  333. IntPtr pidl = IntPtr.Zero;
  334. int fetched = ;
  335. bool complete = false;
  336. while (!complete)
  337. {
  338. hRes = idEnum.Next(, ref pidl, ref fetched);
  339. if (hRes != )
  340. {
  341. pidl = IntPtr.Zero;
  342. complete = true;
  343. }
  344. else
  345. {
  346. if (_getThumbNail(fileName, pidl, item))
  347. {
  348. complete = true;
  349. }
  350. }
  351. if (pidl != IntPtr.Zero)
  352. {
  353. Allocator.Free(pidl);
  354. }
  355. }
  356. Marshal.ReleaseComObject(idEnum);
  357. }
  358. Marshal.ReleaseComObject(item);
  359. }
  360. Allocator.Free(pidlMain);
  361. }
  362. Marshal.ReleaseComObject(folder);
  363. }
  364. return ThumbNail;
  365. }
  366.  
  367. private bool _getThumbNail(string file, IntPtr pidl, IShellFolder item)
  368. {
  369. IntPtr hBmp = IntPtr.Zero;
  370. IExtractImage extractImage = null;
  371. try
  372. {
  373. string pidlPath = PathFromPidl(pidl);
  374. if (Path.GetFileName(pidlPath).ToUpper().Equals(Path.GetFileName(file).ToUpper()))
  375. {
  376. IUnknown iunk = null;
  377. int prgf = ;
  378. Guid iidExtractImage = new Guid("BB2E617C-0920-11d1-9A0B-00C04FC2D6C1");
  379. item.GetUIObjectOf(IntPtr.Zero, , ref pidl, ref iidExtractImage, ref prgf, ref iunk);
  380. extractImage = (IExtractImage)iunk;
  381. if (extractImage != null)
  382. {
  383. Console.WriteLine("Got an IExtractImage object!");
  384. SIZE sz = new SIZE();
  385. sz.cx = DesiredSize.Width;
  386. sz.cy = DesiredSize.Height;
  387. StringBuilder location = new StringBuilder(, );
  388. int priority = ;
  389. int requestedColourDepth = ;
  390. EIEIFLAG flags = EIEIFLAG.IEIFLAG_ASPECT | EIEIFLAG.IEIFLAG_SCREEN;
  391. int uFlags = (int)flags;
  392. try
  393. {
  394. extractImage.GetLocation(location, location.Capacity, ref priority, ref sz, requestedColourDepth, ref uFlags);
  395. extractImage.Extract(ref hBmp);
  396. }
  397. catch (System.Runtime.InteropServices.COMException ex)
  398. {
  399.  
  400. }
  401. if (hBmp != IntPtr.Zero)
  402. {
  403. _thumbNail = Bitmap.FromHbitmap(hBmp);
  404. }
  405. Marshal.ReleaseComObject(extractImage);
  406. extractImage = null;
  407. }
  408. return true;
  409. }
  410. else
  411. {
  412. return false;
  413. }
  414. }
  415. catch (Exception ex)
  416. {
  417. if (hBmp != IntPtr.Zero)
  418. {
  419. UnmanagedMethods.DeleteObject(hBmp);
  420. }
  421. if (extractImage != null)
  422. {
  423. Marshal.ReleaseComObject(extractImage);
  424. }
  425. throw ex;
  426. }
  427. }
  428.  
  429. private string PathFromPidl(IntPtr pidl)
  430. {
  431. StringBuilder path = new StringBuilder(, );
  432. int result = UnmanagedMethods.SHGetPathFromIDList(pidl, path);
  433. if (result == )
  434. {
  435. return string.Empty;
  436. }
  437. else
  438. {
  439. return path.ToString();
  440. }
  441. }
  442.  
  443. private IShellFolder getDesktopFolder
  444. {
  445. get
  446. {
  447. IShellFolder ppshf = null;
  448. int r = UnmanagedMethods.SHGetDesktopFolder(ref ppshf);
  449. return ppshf;
  450. }
  451. }
  452.  
  453. public void Dispose()
  454. {
  455. if (!disposed)
  456. {
  457. if (alloc != null)
  458. {
  459. Marshal.ReleaseComObject(alloc);
  460. }
  461. alloc = null;
  462. if (_thumbNail != null)
  463. {
  464. _thumbNail.Dispose();
  465. }
  466. disposed = true;
  467. }
  468. }
  469. }
  470. }

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

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

最快速度源码,请接收

  1. using System;
  2. using System.IO;
  3. using System.Drawing;
  4. using System.Drawing.Imaging;
  5. using System.Runtime.InteropServices;
  6. using System.Drawing.Drawing2D;
  7.  
  8. namespace 缩略图查看
  9. {
  10. /// <summary>
  11. /// Allows reading of embedded thumbnail image from the EXIF information in an image.
  12. /// </summary>
  13. //public abstract class ExifThumbReader
  14. public class ExifThumbReader
  15. {
  16. // GDI plus functions
  17. [DllImport("gdiplus.dll", CharSet = CharSet.Unicode, ExactSpelling = true)]
  18. internal static extern int GdipGetPropertyItem(IntPtr image, int propid, int size, IntPtr buffer);
  19.  
  20. [DllImport("gdiplus.dll", CharSet = CharSet.Unicode, ExactSpelling = true)]
  21. internal static extern int GdipGetPropertyItemSize(IntPtr image, int propid, out int size);
  22.  
  23. [DllImport("gdiplus.dll", CharSet = CharSet.Unicode, ExactSpelling = true)]
  24. internal static extern int GdipLoadImageFromFile(string filename, out IntPtr image);
  25.  
  26. [DllImport("gdiplus.dll", EntryPoint = "GdipDisposeImage", CharSet = CharSet.Unicode, ExactSpelling = true)]
  27. private static extern int GdipDisposeImage(IntPtr image);
  28.  
  29. // EXIT tag value for thumbnail data. Value specified by EXIF standard
  30. private static int THUMBNAIL_DATA = 0x501B;
  31.  
  32. /// <summary>
  33. /// Reads the thumbnail in the given image. If no thumbnail is found, returns null
  34. /// </summary>
  35. //public static Image ReadThumb(string imagePath)
  36. public Image ReadThumb(string imagePath)
  37. {
  38. const int GDI_ERR_PROP_NOT_FOUND = ; // Property not found error
  39. const int GDI_ERR_OUT_OF_MEMORY = ;
  40.  
  41. IntPtr hImage = IntPtr.Zero;
  42. IntPtr buffer = IntPtr.Zero; // Holds the thumbnail data
  43. int ret;
  44. ret = GdipLoadImageFromFile(imagePath, out hImage);
  45.  
  46. try
  47. {
  48. if (ret != )
  49. throw createException(ret);
  50.  
  51. int propSize;
  52.  
  53. ret = GdipGetPropertyItemSize(hImage, THUMBNAIL_DATA, out propSize);
  54. // Image has no thumbnail data in it. Return null
  55. if (ret == GDI_ERR_PROP_NOT_FOUND)
  56. return null;
  57. if (ret != )
  58. throw createException(ret);
  59.  
  60. // Allocate a buffer in memory
  61. buffer = Marshal.AllocHGlobal(propSize);
  62. if (buffer == IntPtr.Zero)
  63. throw createException(GDI_ERR_OUT_OF_MEMORY);
  64.  
  65. ret = GdipGetPropertyItem(hImage, THUMBNAIL_DATA, propSize, buffer);
  66. if (ret != )
  67. throw createException(ret);
  68.  
  69. // buffer has the thumbnail data. Now we have to convert it to
  70. // an Image
  71. return convertFromMemory(buffer);
  72. }
  73.  
  74. finally
  75. {
  76. // Free the buffer
  77. if (buffer != IntPtr.Zero)
  78. Marshal.FreeHGlobal(buffer);
  79.  
  80. GdipDisposeImage(hImage);
  81. }
  82. }
  83.  
  84. /// <summary>
  85. /// Generates an exception depending on the GDI+ error codes (I removed some error
  86. /// codes)
  87. /// </summary>
  88. private static Exception createException(int gdipErrorCode)
  89. {
  90. switch (gdipErrorCode)
  91. {
  92. case :
  93. return new ExternalException("Gdiplus Generic Error", -);
  94. case :
  95. return new ArgumentException("Gdiplus Invalid Parameter");
  96. case :
  97. return new OutOfMemoryException("Gdiplus Out Of Memory");
  98. case :
  99. return new InvalidOperationException("Gdiplus Object Busy");
  100. case :
  101. return new OutOfMemoryException("Gdiplus Insufficient Buffer");
  102. case :
  103. return new ExternalException("Gdiplus Generic Error", -);
  104. case :
  105. return new InvalidOperationException("Gdiplus Wrong State");
  106. case :
  107. return new ExternalException("Gdiplus Aborted", -);
  108. case :
  109. return new FileNotFoundException("Gdiplus File Not Found");
  110. case :
  111. return new OverflowException("Gdiplus Over flow");
  112. case :
  113. return new ExternalException("Gdiplus Access Denied", -);
  114. case :
  115. return new ArgumentException("Gdiplus Unknown Image Format");
  116. case :
  117. return new ExternalException("Gdiplus Not Initialized", -);
  118. case :
  119. return new ArgumentException("Gdiplus Property Not Supported Error");
  120. }
  121.  
  122. return new ExternalException("Gdiplus Unknown Error", -);
  123. }
  124.  
  125. /// <summary>
  126. /// Converts the IntPtr buffer to a property item and then converts its
  127. /// value to a Drawing.Image item
  128. /// </summary>
  129. private static Image convertFromMemory(IntPtr thumbData)
  130. {
  131. propertyItemInternal prop =
  132. (propertyItemInternal)Marshal.PtrToStructure
  133. (thumbData, typeof(propertyItemInternal));
  134.  
  135. // The image data is in the form of a byte array. Write all
  136. // the bytes to a stream and create a new image from that stream
  137. byte[] imageBytes = prop.Value;
  138. MemoryStream stream = new MemoryStream(imageBytes.Length);
  139. stream.Write(imageBytes, , imageBytes.Length);
  140.  
  141. return Image.FromStream(stream);
  142. }
  143.  
  144. /// <summary>
  145. /// Used in Marshal.PtrToStructure().
  146. /// We need this dummy class because Imaging.PropertyItem is not a "blittable"
  147. /// class and Marshal.PtrToStructure only accepted blittable classes.
  148. /// (It's not blitable because it uses a byte[] array and that's not a blittable
  149. /// type. See MSDN for a definition of Blittable.)
  150. /// </summary>
  151. [StructLayout(LayoutKind.Sequential)]
  152. private class propertyItemInternal
  153. {
  154. public int id = ;
  155. public int len = ;
  156. public short type = ;
  157. public IntPtr value = IntPtr.Zero;
  158.  
  159. public byte[] Value
  160. {
  161. get
  162. {
  163. byte[] bytes = new byte[(uint)len];
  164. Marshal.Copy(value, bytes, , len);
  165. return bytes;
  166. }
  167. }
  168. }
  169. }
  170. }

测试结果:

方法 图片张数(张) 每张大小(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毫秒

毫秒级的时间处理上G的图片(生成缩略图)的更多相关文章

  1. 【.NET】上传文件,生成缩略图

    类名:Upload using System; using System.Collections; using System.ComponentModel; using System.Data; us ...

  2. MACOS,LINUX,IOS上可用的毫秒级精度时间获取

    二话不说,先上代码 void outputCurrentTime(uint32_t seq,const char* type){ struct timeval t_curr; gettimeofday ...

  3. spring boot:实现图片文件上传并生成缩略图(spring boot 2.3.1)

    一,为什么要给图片生成缩略图? 1, 用户上传的原始图片如果太大,不能直接展示在网站页面上, 因为不但流费server的流量,而且用户打开时非常费时间, 所以要生成缩略图. 2,服务端管理图片要注意的 ...

  4. VC中如何获取当前时间(精度达到毫秒级)

    标 题: VC中如何获取当前时间(精度达到毫秒级)作 者: 0xFFFFCCCC时 间: 2013-06-24链 接: http://www.cnblogs.com/Y4ng/p/Millisecon ...

  5. Linux下得到毫秒级时间--C语言实现(转-度娘818)

    Linux下得到毫秒级时间--C语言实现 原文链接: http://www.cnblogs.com/nwf5d/archive/2011/06/03/2071247.html #ifdef HAVE_ ...

  6. GetSystemTime API可以得到毫秒级时间

    用Now返回的日期格式中年只有2位,即2000年显示为00, 这似乎不太令人满意. 此外Now和Time都只能获得精确到秒的时间,为了得到更精确的毫秒级时间,可以使用API函数GetSystemTim ...

  7. OKEx交易所交易记录日期时间转毫秒级时间戳

    本文介绍如何将OKEx交易所成交记录数据中的日期时间转毫秒级时间戳. 作者:比特量化 1. OKEx交易记录格式 [ { "time":"2019-09-14T10:29 ...

  8. 使用bitset实现毫秒级查询

    前言 因为业务要求api的一次请求响应时间在10ms以内,所以传统的数据库查询操作直接被排除(网络io和磁盘io).通过调研,最终使用了bieset,目前已经正常运行了很久 *** bitset介绍 ...

  9. 移动端web开发安卓和ios客户端在时间转换上的差异性问题

    作为一名移动前端开发的人员,平时遇到的兼容性问题不在少数.那么,今天就来说一下最近遇到的一个小坑(关于Android和ios在时间转换上的差异性问题)话不多说,直接上重点. 最近接到了一个需求,很简单 ...

随机推荐

  1. 控制台查看原生sql

    情况:当tomcat运行时,项目运行过程中,控制台没有打印出原生sql语句: 解决办法如下: 在 META-INF  文件夹下,查找 persistence.xml 这个文件(这里注意可能一个项目不止 ...

  2. SQL Server 得到数据库中所有表的名称及数据条数

    --方法一if exists ( select * from dbo.sysobjects where id = object_id(N'[dbo].[TableSpace]') and object ...

  3. java io流 图片和字符串之间的转换

    package com.yundongsports.arena.controller.basketballsite;import com.yundongsports.arena.ResponseVo. ...

  4. Android 延时执行任务的三种简单方法

    开启一个新的线程 new Thread() { @Override public void run() { try { Thread.sleep(2000); } catch (Interrupted ...

  5. 苹果mac电脑中brew的安装使用及卸载详细教程

    brew 又叫Homebrew,是Mac OSX上的软件包管理工具,能在Mac中方便的安装软件或者卸载软件, 只需要一个命令, 非常方便 brew类似ubuntu系统下的apt-get的功能 安装br ...

  6. update maven之后jre被改成1.5的问题

    在 pom.xml 中添加如下代码: <build> <plugins> <plugin> <groupId>org.apache.maven.plug ...

  7. 添加ssh key

    我现在根据<github入门和实践>来去摸索github 其实,我发现自己在看github时,感觉不适应,是因为自己太久没有碰到英文了.可以联想到以前当看到一个网页,根据汉字的标题或描述, ...

  8. 测试...外部指针访问private

    #include<iostream> using namespace std; class A{ public: int* getPointer(){ return &m; } v ...

  9. mssql与mysql 数据迁移

    概要: mssql向mysql迁移的实例,所要用到的工具bcp和load data local infile. 由于订单记录的数据是存放在mssql服务器上的,而项目需求把数据迁移到mysql ser ...

  10. Jaunt登陆索尼PSVR,为其提供大量VR视频

    索尼PS VR自从推出就广受用户青睐,当然不仅仅是其低于高端VR头显的价格,还在于PS VR提供的丰富游戏内容.近日,国外视频网站Jaunt还专门为PSVR推出了专版APP,为其提供超过 150 个沉 ...