惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

C
CXSECURITY Database RSS Feed - CXSecurity.com
Stack Overflow Blog
Stack Overflow Blog
月光博客
月光博客
T
Threat Research - Cisco Blogs
小众软件
小众软件
有赞技术团队
有赞技术团队
酷 壳 – CoolShell
酷 壳 – CoolShell
Apple Machine Learning Research
Apple Machine Learning Research
C
Cyber Attacks, Cyber Crime and Cyber Security
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
T
Tailwind CSS Blog
Cisco Talos Blog
Cisco Talos Blog
V
V2EX
博客园 - 【当耐特】
C
Cybersecurity and Infrastructure Security Agency CISA
Hugging Face - Blog
Hugging Face - Blog
The Cloudflare Blog
The Last Watchdog
The Last Watchdog
Simon Willison's Weblog
Simon Willison's Weblog
T
Threatpost
S
Secure Thoughts
O
OpenAI News
P
Proofpoint News Feed
S
SegmentFault 最新的问题
Forbes - Security
Forbes - Security
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
Application and Cybersecurity Blog
Application and Cybersecurity Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
Last Week in AI
Last Week in AI
宝玉的分享
宝玉的分享
Scott Helme
Scott Helme
T
Tenable Blog
A
Arctic Wolf
L
LINUX DO - 热门话题
爱范儿
爱范儿
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
www.infosecurity-magazine.com
www.infosecurity-magazine.com
V
Visual Studio Blog
Hacker News: Ask HN
Hacker News: Ask HN
Hacker News - Newest:
Hacker News - Newest: "LLM"
腾讯CDC
博客园 - Franky
WordPress大学
WordPress大学
Know Your Adversary
Know Your Adversary
博客园_首页
雷峰网
雷峰网
IT之家
IT之家
PCI Perspectives
PCI Perspectives
L
LINUX DO - 最新话题
H
Heimdal Security Blog

博客园 - pboy2925

博客搬家 http://jorkin.me [导入][转]一个经典的Access数据库 [导入][转]阿D SQL注入工具常用的一些注入命令 [导入]jQuery插件推荐(最后更新2009年01月18日) [导入][原创]正则分析二级或多级域名的主域名 [导入][原创]级联checkbox,自用权限管理模块,需jQuery [导入][转]跨越域的Cookie [导入]Select的OnChange()事件 [导入]ASP常用函数:RadioScript() [导入][转]读取汉字点阵数据 [导入]可爱的小动物们 [导入]值得收藏经典民间偏方 [导入]如何学习英语(英语学习中最重要的五点) [导入]Oracle常用函数:IDCARD15TO18() 身份证15位转18位函数 [导入][转]地产忽悠大全 [导入]scrollLeft scrollTop clientWidth clientHeight 各浏览器修正 [导入]试用了一下Dreamweaver CS4 [导入]中文 Windows 95 GBK 代码集字符定义表 [导入]千万千万不要买宏图三胞的东西
[导入][转]js + .Net 图片切割系统
pboy2925 · 2008-12-05 · via 博客园 - pboy2925

上一阵子做过一个 JavaScript 图片切割效果 ,得到很多人关注。其中有很多人向我询问如何做一个真正的图片切割(裁剪),这里需要声明一下:
首先js是不能操作客户端文件的(除非特殊情况),所以图片的切割必须在后台处理,对于客户端的图片可以先上传再切割或者把图片和切割参数一起传递到服务器再处理(上传文件不在本次讨论范围,请自行修改);
还有是通过客户端传递的参数来处理图片,确实能得到展示图或预览图的效果(这是针对有些提出在后台处理的图片得不到预览图的效果来说的),下面会举例说明如何生成展示图那样的图片。

程序说明:

【客户端部分】

客户端部分详细请参考 JavaScript 图片切割效果 (建议没有看过的先看那里的例子),这里说说要传递到后台的参数,这些参数包括:
图片地址:ic.Url;
水平切割点:ic.Drag.offsetLeft;
垂直切割点:ic.Drag.offsetTop;
切割宽度:ic.Drag.offsetWidth;
切割高度:ic.Drag.offsetHeight;
图片宽度:ic.Width;
图片高度:ic.Height。

在前台传递这些参数:

var p = ic.Url,
= ic.Drag.offsetLeft,
= ic.Drag.offsetTop,
= ic.Drag.offsetWidth,
= ic.Drag.offsetHeight,
pw 
= ic.Width,
ph 
= ic.Height;

$(

"imgCreat").src = "ImgCropper.ashx?p=" + p + "&x=" + x + "&y=" + y + "&w=" + w + "&h=" + h + "&pw=" + pw + "&ph=" + ph + "&" + Math.random();

其中图片地址、图片宽度、图片高度如果是预先设定好的话就可以不传递了。

【后台部分】

后台主要是进行图片的处理和输出。

【图片切割】

在后台获取前台传递的参数:

string Pic = Convert.ToString(context.Request["p"]);
int PointX = Convert.ToInt32(context.Request["x"]);
int PointY = Convert.ToInt32(context.Request["y"]);
int CutWidth = Convert.ToInt32(context.Request["w"]);
int CutHeight = Convert.ToInt32(context.Request["h"]);
int PicWidth = Convert.ToInt32(context.Request["pw"]);
int PicHeight = Convert.ToInt32(context.Request["ph"]);

然后就用这些参数对图片进行切割了,先说说切割的原理,主要分两部:切割和缩放。

切割和缩放的程序关键在这里:

gbmPhoto.DrawImage(imgPhoto, new Rectangle(00, CutWidth, CutHeight), PointX * imgPhoto.Width / PicWidth, PointY * imgPhoto.Height / PicHeight, CutWidth * imgPhoto.Width / PicWidth, CutHeight * imgPhoto.Height / PicHeight, GraphicsUnit.Pixel);

首先是在原图切割出需要的部分。切割需要的参数是PointX、PointY、CutWidth、CutHeight,因为在客户端的程序中是可以缩放原图来进行切割的,所以要在在切割原图时需要先按比例缩放这些参数,还要注意PointX和CutWidth需要水平方向的比例,PointY和CutHeight需要垂直方向的比例。例如(其中imgPhoto是原图):
水平切割点:PointX * imgPhoto.Width / PicWidth;
切割宽度:CutWidth * imgPhoto.Width / PicWidth;
垂直切割点:PointY * imgPhoto.Height / PicHeight;
切割高度:CutHeight * imgPhoto.Height / PicHeight。

用这些参数就可以对原图进行切割了。

然后是缩放原图。可以想象,当切割好原图后,只要把图宽高缩放到CutWidth和CutHeight就可以得到跟展示图一样的图片了:

new Rectangle(00, CutWidth, CutHeight), 

下面是处理图片的程序:

    public MemoryStream ResetImg(string ImgFile, int PicWidth, int PicHeight, int PointX, int PointY, int CutWidth, int CutHeight)
    {
        Image imgPhoto 
= Image.FromFile(ImgFile);
        Bitmap bmPhoto 
= new Bitmap(CutWidth, CutHeight, System.Drawing.Imaging.PixelFormat.Format24bppRgb);

        Graphics gbmPhoto 

= Graphics.FromImage(bmPhoto);
        gbmPhoto.DrawImage(imgPhoto, 
new Rectangle(00, CutWidth, CutHeight), PointX * imgPhoto.Width / PicWidth, PointY * imgPhoto.Height / PicHeight, CutWidth * imgPhoto.Width / PicWidth, CutHeight * imgPhoto.Height / PicHeight, GraphicsUnit.Pixel);

        MemoryStream ms2 

= new MemoryStream();
        bmPhoto.Save(ms2, System.Drawing.Imaging.ImageFormat.Jpeg);

        imgPhoto.Dispose();
        gbmPhoto.Dispose();
        bmPhoto.Dispose();

return ms2;
    }

当然对于不同的需求可能要生成的效果也不一样,但只要能灵活运用对于一般的需求基本都能实现了。
如果需要保存图片到服务器,那么可以用下面的方法保存图片:

bmPhoto.Save(文件物理路径, System.Drawing.Imaging.ImageFormat.Jpeg);

【IHttpHandler】

程序通过ashx文件用IHttpHandler发送切割生成的图片,参考 使用.ashx文件处理IHttpHandler实现发送文本及二进制数据的方法
“利用.ashx文件是一个更好的方法,这个文件类似于.aspx文件,可以通过它来调用HttpHandler类,从而免去了普通.aspx页面的控件解析以及页面处理的过程。这个文件特别适合于生成动态图片,生成动态文本等内容。”

最后设置数据输出类型context.Response.ContentType,并使用context.Response.OutputStream向客户端输出图片数据:

context.Response.ContentType = "image/jpeg";
ResetImg(System.Web.HttpContext.Current.Server.MapPath(Pic), PicWidth, PicHeight, PointX, PointY, CutWidth, CutHeight).WriteTo(context.Response.OutputStream);

这个输出数据的方法适合用在不需要回发的数据输出中,例如ajax、动态图片等,关于这方面更详细的内容请看 IHttpHandler接口

下面是完整服务器端代码:

<%@ WebHandler Language="c#" Class="ImgCropper_WebHandler" Debug="true" %>using System;
using System.Web;
using System.Drawing;
using System.IO;public class ImgCropper_WebHandler : IHttpHandler
{
    
public void ProcessRequest(HttpContext context)
    {
        
string Pic = Convert.ToString(context.Request["p"]);
        
int PointX = Convert.ToInt32(context.Request["x"]);
        
int PointY = Convert.ToInt32(context.Request["y"]);
        
int CutWidth = Convert.ToInt32(context.Request["w"]);
        
int CutHeight = Convert.ToInt32(context.Request["h"]);
        
int PicWidth = Convert.ToInt32(context.Request["pw"]);
        
int PicHeight = Convert.ToInt32(context.Request["ph"]);

        context.Response.ContentType 

= "image/jpeg";
        ResetImg(System.Web.HttpContext.Current.Server.MapPath(Pic), PicWidth, PicHeight, PointX, PointY, CutWidth, CutHeight).WriteTo(context.Response.OutputStream);
    }
    
    
public MemoryStream ResetImg(string ImgFile, int PicWidth, int PicHeight, int PointX, int PointY, int CutWidth, int CutHeight)
    {
        Image imgPhoto 
= Image.FromFile(ImgFile);
        Bitmap bmPhoto 
= new Bitmap(CutWidth, CutHeight, System.Drawing.Imaging.PixelFormat.Format24bppRgb);

        Graphics gbmPhoto 

= Graphics.FromImage(bmPhoto);
        gbmPhoto.DrawImage(imgPhoto, 
new Rectangle(00, CutWidth, CutHeight), PointX * imgPhoto.Width / PicWidth, PointY * imgPhoto.Height / PicHeight, CutWidth * imgPhoto.Width / PicWidth, CutHeight * imgPhoto.Height / PicHeight, GraphicsUnit.Pixel);

        MemoryStream ms2 

= new MemoryStream();
        bmPhoto.Save(ms2, System.Drawing.Imaging.ImageFormat.Jpeg);

        imgPhoto.Dispose();
        gbmPhoto.Dispose();
        bmPhoto.Dispose();

return ms2;
    }
public bool IsReusable
    {
        
get
        {
            
return false;
        }
    }
}

各位有什么建议或意见欢迎留言讨论,由于涉及后台操作,请下载完整实例测试。

下载完整测试实例

文章来源:http://Jorkin.Reallydo.Com/default.asp?id=554