1
아래 코드를 사용하여 ASP.Net 응용 프로그램 내에서 이미지 축소판을 만들었습니다.HttpHandler에서 Windows API를 통해 이미지의 Thumnail 생성
using System;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
namespace RMA.Shell
{
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;
}
}
}
}
나는이 코드
- 에 대한 약간의 의심이
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Drawing; using System.IO; using RMA.Shell; using System.Drawing.Imaging; namespace DemoApp { /// <summary> /// Summary description for ImageHandler /// </summary> public class ImageHandler : IHttpHandler { public void ProcessRequest(HttpContext context) { byte[] buffer = null; string imgUrl = context.Request.Params["url"].ToString(); if (!string.IsNullOrEmpty(imgUrl)) { ShellThumbnail thumb = new ShellThumbnail(); Bitmap bmp = thumb.GetThumbnail(context.Server.MapPath(imgUrl)); using (MemoryStream stram = new MemoryStream()) { bmp.Save(stram, ImageFormat.Jpeg); buffer = stram.ToArray(); bmp.Dispose(); thumb.Dispose(); } HttpCachePolicy cachePilicy = context.Response.Cache; cachePilicy.SetAllowResponseInBrowserHistory(false); cachePilicy.SetCacheability(HttpCacheability.NoCache); cachePilicy.SetExpires(DateTime.Now.AddDays(-1)); context.Response.Clear(); context.Response.ContentType = "Image/jpeg"; context.Response.OutputStream.Write(buffer, 0, buffer.Length); buffer = null; context.Response.OutputStream.Close(); context.Response.End(); } } public bool IsReusable { get { return true; } } } }
처럼의 getThumbnail() 메서드를 호출 곳에서 HTTP 처리기를 만든 방법이의 getThumbnail() 방법은 작동합니까? 그것은 창 thumnail 캐시 ie.thumb.db를 사용하고 있습니까? 또는 각 통화에 대해 thumnail을 생성합니까?
- 이 COM API를 사용할 때 성능 문제가 있습니까? 동시에 여러 HTTP 요청을 처리 할 수 있습니까?
들리는군요 딜런는 윈도우 API 코드 팩 쉘 구현이 차이는 더 나은 선택 어느 하나 같은
ShellFile shellFile = ShellFile.FromFilePath(pathToYourFile);
Bitmap shellThumb = shellFile.Thumbnail.ExtraLargeBitmap;
입니까?
4. 내부 구현은 무엇입니까? GDI + 또는 IPP와 같은 다른 방법을 사용합니까?
명확히하십시오
하면 이미지 크기 조정에 대한 쉽고 깨끗하게 관리 솔루션이 모든 것을 COM 혼란하고있는 이유
성능을 향상시켜야합니다. 이 메서드는 다른 메서드보다 빠르게 축소판을 생성합니다. – KiranPalode
실제로, 기본 WIC 호출에 오버 헤드를 추가하는 것입니다. Windows 탐색기와 Thumbnail 인터페이스는 WIC API를 사용합니다. [ImageResizer] (http://imageresizing.net)를 사용하면 [WicBuilder 플러그인] (http://imageresizing.net/plugins/wic)을 통해 번거롭고 메모리 누출없이 동일한 WIC API를 사용할 수 있습니다. –
완전 신뢰가 필요하고 WIC가 Windows Server 2008 R2 이상에서만 서버 안전이기 때문에 기본값이 아닙니다. Windows Server 2008 R1에서는 접근 방식을 절대로 사용해서는 안됩니다. –