优快云广告是越来越多了,所有博客笔记不再更新,新网址 DotNet笔记
效果:
添加两个类:
using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Drawing.Imaging;
using System.Drawing.Drawing2D;
using System.Security.Cryptography;
using System.IO;
using System.Net;
using System.Web;
namespace okpower.Utility
{
/// <summary>
/// 图像处理类
/// </summary>
public class ImageLibrary
{
/// <summary>
/// 两张图片的对比结果
/// </summary>
public enum CompareResult
{
ciCompareOk,
ciPixelMismatch,
ciSizeMismatch
};
/// <summary>
/// 对比两张图片
/// </summary>
/// <param name="bmp1">The first bitmap image</param>
/// <param name="bmp2">The second bitmap image</param>
/// <returns>CompareResult</returns>
public static CompareResult CompareTwoImages(Bitmap bmp1, Bitmap bmp2)
{
CompareResult cr = CompareResult.ciCompareOk;
//Test to see if we have the same size of image
if (bmp1.Size != bmp2.Size)
{
cr = CompareResult.ciSizeMismatch;
}
else
{
//Convert each image to a byte array
System.Drawing.ImageConverter ic =
new System.Drawing.ImageConverter();
byte[] btImage1 = new byte[1];
btImage1 = (byte[])ic.ConvertTo(bmp1, btImage1.GetType());
byte[] btImage2 = new byte[1];
btImage2 = (byte[])ic.ConvertTo(bmp2, btImage2.GetType());
//Compute a hash for each image
SHA256Managed shaM = new SHA256Managed();
byte[] hash1 = shaM.ComputeHash(btImage1);
byte[] hash2 = shaM.ComputeHash(btImage2);
//Compare the hash values
for (int i = 0; i < hash1.Length && i < hash2.Length
&& cr == CompareResult.ciCompareOk; i++)
{
if (hash1[i] != hash2[i])
cr = CompareResult.ciPixelMismatch;
}
}
return cr;
}
public enum ScaleMode
{
/// <summary>
/// 指定高宽缩放(可能变形)
/// </summary>
HW,
/// <summary>
/// 指定宽,高按比例
/// </summary>
W,
/// <summary>
/// 指定高,宽按比例
/// </summary>
H,
/// <summary>
/// 指定高宽裁减(不变形)
/// </summary>
Cut
};
/// <summary>
/// Resizes the image by a percentage
/// </summary>
/// <param name="imgPhoto">The img photo.</param>
/// <param name="Percent">The percentage</param>
/// <returns></returns>
// http://www.codeproject.com/csharp/imageresize.asp
public static Image ResizeImageByPercent(Image imgPhoto, int Percent)
{
float nPercent = ((float)Percent / 100);
int sourceWidth = imgPhoto.Width;
int sourceHeight = imgPhoto.Height;
int sourceX = 0;
int sourceY = 0;
int destX = 0;
int destY = 0;
int destWidth = (int)(sourceWidth * nPercent);
int destHeight = (int)(sourceHeight * nPercent);
Bitmap bmPhoto = new Bitmap(destWidth, destHeight,
PixelFormat.Format24bppRgb);
bmPhoto.SetResolution(imgPhoto.HorizontalResolution,
imgPhoto.VerticalResolution);
Graphics grPhoto = Graphics.FromImage(bmPhoto);
grPhoto.InterpolationMode = InterpolationMode.HighQualityBicubic;
grPhoto.DrawImage(imgPhoto,
new Rectangle(destX, destY, destWidth, destHeight),
new Rectangle(sourceX, sourceY, sourceWidth, sourceHeight),
GraphicsUnit.Pixel);
grPhoto.Dispose();
return bmPhoto;
}
/// <summary>
/// 缩放、裁切图片
/// </summary>
/// <param name="originalImage"></param>
/// <param name="width"></param>
/// <param name="height"></param>
/// <param name="mode"></param>
/// <returns></returns>
public static Image ResizeImageToAFixedSize(Image originalImage, int width, int height, ScaleMode mode)
{
int towidth = width;
int toheight = height;
int x = 0;
int y = 0;
int ow = originalImage.Width;
int oh = originalImage.Height;
switch (mode)
{
case ScaleMode.HW:
break;
case ScaleMode.W:
toheight = originalImage.Height * width / originalImage.Width;
break;
case ScaleMode.H:
towidth = originalImage.Width * height / originalImage.Height;
break;
case ScaleMode.Cut:
if ((double)originalImage.Width / (double)originalImage.Height > (double)towidth / (double)toheight)
{
oh = originalImage.Height;
ow = originalImage.Height * towidth / toheight;
y = 0;
x = (originalImage.Width - ow) / 2;
}
else
{
ow = originalImage.Width;
oh = originalImage.Width * height / towidth;
x = 0;
y = (originalImage.Height - oh) / 2;
}
break;
default:
break;
}
//新建一个bmp图片
Image bitmap = new System.Drawing.Bitmap(towidth, toheight);
//新建一个画布
Graphics g = System.Drawing.Graphics.FromImage(bitmap);
//设置画布的描绘质量
g.CompositingQuality = CompositingQuality.HighQuality;
g.SmoothingMode = SmoothingMode.HighQuality;
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
//清空画布并以透明背景色填充
g.Clear(Color.Transparent);
//在指定位置并且按指定大小绘制原图片的指定部分
g.DrawImage(originalImage, new Rectangle(0, 0, towidth, toheight),
new Rectangle(x, y, ow, oh),
GraphicsUnit.Pixel);
g.Dispose();
return bitmap;
}
}
}
using System;
using System.Collections.Generic;
using System.Text;
using System.Security;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
using System.Drawing;
using System.Windows.Forms;
using System.Threading;
namespace okpower.Utility
{
/// <summary>
/// 供Asp.Net直接调用的包装类
/// 作者:Kai.Ma http://kaima.cnblogs.com
/// </summary>
public class WebPreview
{
private Uri _uri = null;
private Exception _ex = null;
private Bitmap _bitmap = null;
private int _timeout = 30 * 1000;//设置线程超时时长
private int _width = 200;//缩图宽
private int _height = 150;//缩图高
private bool _fullPage = true;
private WebPreview(Uri uri): this(uri, 30 * 1000, 200, 150, true)
{
}
private WebPreview(Uri uri, int timeout, int width, int height, bool fullPage)
{
_uri = uri;
_timeout = timeout;
_width = width;
_height = height;
_fullPage = fullPage;
}
internal Bitmap GetWebPreview()
{
//Asp.Net引用Winform(类似ActiveX)控件,必须开单线程
Thread t = new Thread(new ParameterizedThreadStart(StaRun));
t.SetApartmentState(ApartmentState.STA);
t.Start(this);
if (!t.Join(_timeout))
{
t.Abort();
throw new TimeoutException();
}
if (_ex != null) throw _ex;
if (_bitmap == null) throw new ExecutionEngineException();
return _bitmap;
}
public static Bitmap GetWebPreview(Uri uri)
{
WebPreview wp = new WebPreview(uri);
return wp.GetWebPreview();
}
public static Bitmap GetWebPreview(Uri uri, int timeout, int width, int height, bool fullPage)
{
WebPreview wp = new WebPreview(uri,timeout,width,height,fullPage);
return wp.GetWebPreview();
}
/// <summary>
/// 为WebBrowser所开线程的启动入口函数,相当于Winform里面的Main()
/// </summary>
/// <param name="_wp"></param>
private static void StaRun(object _wp)
{
WebPreview wp = (WebPreview)_wp;
try
{
WebPreviewBase wpb = new WebPreviewBase(wp._uri,wp._width,wp._height,wp._fullPage);
wp._bitmap = wpb.GetWebPreview();
}
catch (Exception ex)
{
wp._ex = ex;
}
}
}
/// <summary>
/// 包装后的抓图基类。WebBrowser自带的BrawToBitmap不能抓到一些网站的图片,
/// 对于一些转向的网站会返回空白图片,所以采用原生的通过IViewObject接口
/// 取浏览器的图象,实现SNAP。感谢类库的作者“随飞”。
/// 原作者:随 飞 http://chinasf.cnblogs.com
/// 包装者:Kai.Ma http://kaima.cnblogs.com
/// </summary>
class WebPreviewBase: IDisposable
{
Uri _uri = new Uri("about:blank");//原始uri
int _thumbW = 1024; //缩略图高度
int _thumbH = 768; //缩略图宽度
WebBrowser _wb; //浏览器对象
bool _fullpage = false; //是否抓取全图
public WebPreviewBase(Uri uri, int thumbW, int thumbH, bool fullpage)
{
_wb = new WebBrowser();
_wb.ScriptErrorsSuppressed = true;
//_wb.ScriptErrorsSuppressed = false;
_wb.ScrollBarsEnabled = false;
_wb.Size = new Size(1024, 768);//浏览器分辨率为1024x768
_wb.NewWindow += new System.ComponentModel.CancelEventHandler(CancelEventHandler);
_thumbW = thumbW;
_thumbH = thumbH;
_uri = uri;
}
/// <summary>
/// URI 地址
/// </summary>
public Uri Uri
{
get { return _uri; }
set { _uri = value; }
}
/// <summary>
/// 缩略图宽度
/// </summary>
public int ThumbW
{
get { return _thumbW; }
set { _thumbW = value; }
}
/// <summary>
/// 缩略图高度
/// </summary>
public int ThumbH
{
get { return _thumbH; }
set { _thumbH = value; }
}
//防止弹窗
public void CancelEventHandler(object sender,System.ComponentModel.CancelEventArgs e)
{
e.Cancel = true;
}
/// <summary>
/// 初始化
/// </summary>
protected void InitComobject()
{
try
{
_wb.Navigate(this._uri);
//因为没有窗体,所以必须如此
while (_wb.ReadyState != WebBrowserReadyState.Complete)
{
//立即重绘
Application.DoEvents();
}
//这句最好注释,不然网页上的动画都抓不到了
_wb.Stop();
if (_wb.ActiveXInstance == null) throw new Exception("实例不能为空");
}
catch (Exception ex)
{
throw ex;
}
}
/// <summary>
/// 获取Web预览图
/// </summary>
/// <returns>Bitmap</returns>
public Bitmap GetWebPreview()
{
#region 调整图片高宽,并调整浏览器高宽适应图片高宽
int w = _wb.Width;
int h = _wb.Height;
Size sz = _wb.Size;
if (_fullpage)
{
h = _wb.Document.Body.ScrollRectangle.Height; // +SystemInformation.VerticalScrollBarWidth;
w = _wb.Document.Body.ScrollRectangle.Width; // +SystemInformation.HorizontalScrollBarHeight;
}
// 最小宽度不能小于缩略图宽度
if (w < _thumbW)
w = _thumbW;
// 调整最小高度,充满浏览器
if (h < sz.Height)
h = sz.Height;
_wb.Size = new Size(w, h);
#endregion
try
{
InitComobject();
//构造snapshot类,抓取浏览器ActiveX的图象
Snapshot snap = new Snapshot();
Bitmap thumBitmap = snap.TakeSnapshot(_wb.ActiveXInstance, new Rectangle(0, 0, w, h));
//调整图片大小,这里选择以宽度为标准,高度保持比例
thumBitmap = (Bitmap)ImageLibrary.ResizeImageToAFixedSize(thumBitmap, _thumbW, _thumbH, ImageLibrary.ScaleMode.W);
return thumBitmap;
}
catch (Exception ex)
{
throw ex;
}
}
public void Dispose()
{
_wb.Dispose();
}
}
#region WebPreview的类库
/// <summary>
/// ActiveX 组件快照类
/// AcitveX 必须实现 IViewObject 接口
///
/// 作者:随飞
/// http://chinasf.cnblogs.com
/// chinasf@hotmail.com
/// </summary>
class Snapshot
{
/// <summary>
/// 取快照
/// </summary>
/// <param name="pUnknown">Com 对象</param>
/// <param name="bmpRect">图象大小</param>
/// <returns></returns>
public Bitmap TakeSnapshot(object pUnknown, Rectangle bmpRect)
{
if (pUnknown == null)
return null;
//必须为com对象
if (!Marshal.IsComObject(pUnknown))
return null;
//IViewObject 接口
UnsafeNativeMethods.IViewObject ViewObject = null;
IntPtr pViewObject = IntPtr.Zero;
//内存图
Bitmap pPicture = new Bitmap(bmpRect.Width, bmpRect.Height);
Graphics hDrawDC = Graphics.FromImage(pPicture);
//获取接口
object hret = Marshal.QueryInterface(Marshal.GetIUnknownForObject(pUnknown),
ref UnsafeNativeMethods.IID_IViewObject, out pViewObject);
try
{
ViewObject = Marshal.GetTypedObjectForIUnknown(pViewObject, typeof(UnsafeNativeMethods.IViewObject)) as UnsafeNativeMethods.IViewObject;
//调用Draw方法
ViewObject.Draw((int)DVASPECT.DVASPECT_CONTENT,
-1,
IntPtr.Zero,
null,
IntPtr.Zero,
hDrawDC.GetHdc(),
new NativeMethods.COMRECT(bmpRect),
null,
IntPtr.Zero,
0);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
throw ex;
}
//释放
hDrawDC.Dispose();
return pPicture;
}
}
/// <summary>
/// 从 .Net 2.0 的 System.Windows.Forms.Dll 库提取
/// 版权所有:微软公司
/// </summary>
internal static class NativeMethods
{
[StructLayout(LayoutKind.Sequential)]
public sealed class tagDVTARGETDEVICE
{
[MarshalAs(UnmanagedType.U4)]
public int tdSize;
[MarshalAs(UnmanagedType.U2)]
public short tdDriverNameOffset;
[MarshalAs(UnmanagedType.U2)]
public short tdDeviceNameOffset;
[MarshalAs(UnmanagedType.U2)]
public short tdPortNameOffset;
[MarshalAs(UnmanagedType.U2)]
public short tdExtDevmodeOffset;
}
[StructLayout(LayoutKind.Sequential)]
public class COMRECT
{
public int left;
public int top;
public int right;
public int bottom;
public COMRECT()
{
}
public COMRECT(Rectangle r)
{
this.left = r.X;
this.top = r.Y;
this.right = r.Right;
this.bottom = r.Bottom;
}
public COMRECT(int left, int top, int right, int bottom)
{
this.left = left;
this.top = top;
this.right = right;
this.bottom = bottom;
}
public static NativeMethods.COMRECT FromXYWH(int x, int y, int width, int height)
{
return new NativeMethods.COMRECT(x, y, x + width, y + height);
}
public override string ToString()
{
return string.Concat(new object[] { "Left = ", this.left, " Top ", this.top, " Right = ", this.right, " Bottom = ", this.bottom });
}
}
[StructLayout(LayoutKind.Sequential)]
public sealed class tagLOGPALETTE
{
[MarshalAs(UnmanagedType.U2)]
public short palVersion;
[MarshalAs(UnmanagedType.U2)]
public short palNumEntries;
}
}
/// <summary>
/// 从 .Net 2.0 的 System.Windows.Forms.Dll 库提取
/// 版权所有:微软公司
/// </summary>
[SuppressUnmanagedCodeSecurity]
internal static class UnsafeNativeMethods
{
public static Guid IID_IViewObject = new Guid("{0000010d-0000-0000-C000-000000000046}");
[ComImport, Guid("0000010d-0000-0000-C000-000000000046"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IViewObject
{
[PreserveSig]
int Draw([In, MarshalAs(UnmanagedType.U4)] int dwDrawAspect, int lindex, IntPtr pvAspect, [In] NativeMethods.tagDVTARGETDEVICE ptd, IntPtr hdcTargetDev, IntPtr hdcDraw, [In] NativeMethods.COMRECT lprcBounds, [In] NativeMethods.COMRECT lprcWBounds, IntPtr pfnContinue, [In] int dwContinue);
[PreserveSig]
int GetColorSet([In, MarshalAs(UnmanagedType.U4)] int dwDrawAspect, int lindex, IntPtr pvAspect, [In] NativeMethods.tagDVTARGETDEVICE ptd, IntPtr hicTargetDev, [Out] NativeMethods.tagLOGPALETTE ppColorSet);
[PreserveSig]
int Freeze([In, MarshalAs(UnmanagedType.U4)] int dwDrawAspect, int lindex, IntPtr pvAspect, [Out] IntPtr pdwFreeze);
[PreserveSig]
int Unfreeze([In, MarshalAs(UnmanagedType.U4)] int dwFreeze);
void SetAdvise([In, MarshalAs(UnmanagedType.U4)] int aspects, [In, MarshalAs(UnmanagedType.U4)] int advf, [In, MarshalAs(UnmanagedType.Interface)] IAdviseSink pAdvSink);
void GetAdvise([In, Out, MarshalAs(UnmanagedType.LPArray)] int[] paspects, [In, Out, MarshalAs(UnmanagedType.LPArray)] int[] advf, [In, Out, MarshalAs(UnmanagedType.LPArray)] IAdviseSink[] pAdvSink);
}
}
#endregion
}
页面中使用方式:
default.aspx页面代码:
<div>
网址<asp:TextBox ID="TextBox1" runat="server" Width="427px">http://</asp:TextBox>
<asp:Button ID="bt" runat="server" OnClick="bt_Click" Text="抓取" /><br />
<br />
<div id="Preview" runat="server"></div>
</div>
对应的cs代码:
using okpower.Utility;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace HtmlToImg
{
public partial class _Default : Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
public string WebPreview(string url)
{
if (string.IsNullOrEmpty(url)) return string.Empty;
string fold = "_images/";//图片存放目录
string physicsFold = Server.MapPath(fold);
string name = url;
name = name.Replace('/', '-');
name = name.Replace(':', '_');
name = name.Replace('&', '_');
name = name.Replace(',', '_');
name = name.Replace('\'', '_');
name = name.Replace('"', '_');
string fileName = name + ".jpg";
if (!System.IO.File.Exists(physicsFold + fileName))
{
try
{
Bitmap image = okpower.Utility.WebPreview.GetWebPreview(new Uri(url));
//保存图片数据
image.Save(physicsFold + fileName, ImageFormat.Jpeg);
}
catch (Exception ee)
{
throw;
}
}
return fold + fileName;
}
protected void bt_Click(object sender, EventArgs e)
{
this.Preview.InnerHtml = "<img src=\"" + WebPreview(TextBox1.Text) + "\"/>";
}
}
}
效果图如顶部