您的位置:首页 > 其它

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

2016-06-07 08:12 274 查看
测试环境:

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)图片总大小用时
方法一50301500M39950毫秒=40秒
方法二50301500M66450毫秒=66秒
方法三50301500M81800毫秒=81秒
方法四50301500M83200毫秒=83秒
方法五50301500M36750毫秒=37秒
方法六50301500M237毫秒
方法七50301500M96毫秒
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: