在做项目的过程中,有很多时候前端的图片会出现拉伸现象,所以在上传图片的时候,图片裁剪是必不可少的。所以有了封装一个图片裁剪工具的念头,下面是实现步骤:
1.首先选择一个前台裁剪工具,我这里使用的是Jcrop-0.9.12。
2.开始编写前端js代码:
我这里把前端封装成一个函数
/**
* 初始化裁剪工具。
* @param divId 定义生成填充页面代码的div(函数产生的代码会填充到此div内)
* @param imagePath 图片地址
* @param ratio 宽长比例
* @param callback 裁剪之后的回调
*/
function initJcrop(divId,imagePath,ratio,callback)
{
var postRatio=1;
var jcrop_api;
//外边框宽度和高度
var divWidth=800;
var divHeitht=divWidth/ratio;
//图片最大宽度和高度
var imageMaxWidth = divWidth*0.8;
var imageMaxHeight = divHeitht*0.8;
if($("#tempDiv").html()==null){
var tempDivHtml=‘<div id="tempDiv" style="position: fixed; border: 1px solid #ddd; left: 50%; top: 50%; width: ‘+divWidth+‘px; margin-left: -400px; margin-top: -400px; z-index: 3; background:#fff; border-radius: 10px; box-shadow: 0px 0px 20px 0px #000; text-align: center;align:center">‘+
‘<h1 style="text-align: center; font-size: 20px; padding-top: 20px;">图片裁剪</h1>‘+
‘<div style="margin: 20px 50px; overflow: hidden; height:auto;">‘+
‘<img id="jcropImg" src="‘+imagePath+‘">‘+
‘<p>‘+
‘<input type="button" id="saveButton" value="确定" style="width: 120px; height: 40px; margin: 10px 80px; background: #fff; border: 1px solid #ddd; font-size: 14px; outline: 0; cursor: pointer;">‘+
‘<input type="button" id="closeButton" value="取消" style="width: 120px; height: 40px; margin: 10px 80px; background: #fff; border: 1px solid #ddd; font-size: 14px; outline: 0; cursor: pointer;" >‘+
‘</p>‘+
‘</div>‘+
‘</div>‘;
$("#"+divId).html(tempDivHtml);
}
$(‘#jcropImg‘).attr("src", imagePath);
$("#saveButton").on(‘click‘,function(){
var width=Math.abs(jcrop_api.tellSelect().x2-jcrop_api.tellSelect().x);
var height=Math.abs(jcrop_api.tellSelect().y2-jcrop_api.tellSelect().y);
$.ajax({
type : "post",
url : "imagecut",
data : {"imagepath":imagePath,
"ratio":postRatio,
"width":width,
"height":height,
"x":jcrop_api.tellSelect().x,
"y":jcrop_api.tellSelect().y,
},
async : false,
success : function(data){
callback(imagePath);
$("#tempDiv").remove();
}
});
});
$("#closeButton").on(‘click‘,function(){
$("#tempDiv").remove();
});
document.getElementById("jcropImg").onload = function(){
var imageRatio = 0;
// 缩放比例
var imageWidth = $(‘#jcropImg‘).width();
// 图片实际宽度
var imageHeight = $(‘#jcropImg‘).height();
// 图片实际高度
// 检查图片是否超宽
if(imageWidth > imageMaxWidth) {
imageRatio = imageMaxWidth / imageWidth;
postRatio=postRatio*imageRatio;
imageWidth=imageMaxWidth;
imageHeight = imageHeight * imageRatio;
$(‘#jcropImg‘).css("width", imageWidth);
$(‘#jcropImg‘).css("height", imageHeight);
}
// 检查图片是否超高
if(imageHeight > imageMaxHeight) {
imageRatio = imageMaxHeight / imageHeight;
postRatio=postRatio*imageRatio;
imageHeight=imageMaxHeight;
imageWidth = imageWidth * imageRatio;
$(‘#jcropImg‘).css("width", imageWidth);
$(‘#jcropImg‘).css("height", imageHeight);
}
$(‘#jcropImg‘).Jcrop({
onRelease:releaseCheck,
aspectRatio:ratio, //长宽比例
minSize: [50,50], //最小长宽
},function(){
jcrop_api = this;
jcrop_api.animateTo([0,0,50,50*ratio]);//初始化位置,大小
});
}
};
function releaseCheck()
{
jcrop_api.setOptions({allowSelect:true});
};
3.action层声明(我这里使用的是springMVC框架,所以使用注解方式声明):
@RequestMapping(value="/imagecut")
@ResponseBody
public void imagecut(String imagepath,double ratio,double width,double height,double x,double y){
try {
imagepath=request.getSession().getServletContext().getRealPath("/images/"+imagepath.split("/")[3]+"/"+imagepath.split("/")[4]);;
Common.imageCut(imagepath, (int)(x/ratio), (int)(y/ratio), (int)(width/ratio), (int)(height/ratio));
} catch (IOException e) {
e.printStackTrace();
}
}
4.业务层编写(这里写的是替换原图,如果需求是另存为可以修改部分代码)
/**
* 对图片裁剪,并把裁剪新图片保存 。
* @param imagePath 图片路径
* @param x 左上角x坐标
* @param y 左上角y坐标
* @param width 截取宽度
* @param height 截取高度
*/
public static void imageCut(String imagePath,int x,int y,int width,int height) throws IOException {
FileInputStream is = null;
ImageInputStream iis = null;
try {
// 读取图片文件
is = new FileInputStream(imagePath);
/**
* 返回包含所有当前已注册 ImageReader 的 Iterator,这些 ImageReader
* 声称能够解码指定格式。 参数:formatName - 包含非正式格式名称 .
* (例如 "jpeg" 或 "tiff")等 。
*/
Iterator<ImageReader> it = ImageIO.getImageReadersByFormatName("jpg");
ImageReader reader = it.next();
// 获取图片流
iis = ImageIO.createImageInputStream(is);
/**
* <p>
* iis:读取源。true:只向前搜索
* </p>
* .将它标记为 ‘只向前搜索’。
* 此设置意味着包含在输入源中的图像将只按顺序读取,可能允许 reader
* 避免缓存包含与以前已经读取的图像关联的数据的那些输入部分。
*/
reader.setInput(iis, true);
/**
* <p>
* 描述如何对流进行解码的类
* <p>
* .用于指定如何在输入时从 Java Image I/O
* 框架的上下文中的流转换一幅图像或一组图像。用于特定图像格式的插件
* 将从其 ImageReader 实现的 getDefaultReadParam 方法中返回
* ImageReadParam 的实例。
*/
ImageReadParam param = reader.getDefaultReadParam();
/**
* 图片裁剪区域。Rectangle 指定了坐标空间中的一个区域,通过 Rectangle 对象
* 的左上顶点的坐标(x,y)、宽度和高度可以定义这个区域。
*/
Rectangle rect = new Rectangle(x,y,width,height);
// 提供一个 BufferedImage,将其用作解码像素数据的目标。
param.setSourceRegion(rect);
/**
* 使用所提供的 ImageReadParam 读取通过索引 imageIndex 指定的对象,并将
* 它作为一个完整的 BufferedImage 返回。
*/
BufferedImage bi = reader.read(0, param);
// 保存新图片
ImageIO.write(bi, "jpg", new File(imagePath));
} finally {
if (is != null)
is.close();
if (iis != null)
iis.close();
}
}
5.最后更新图片等操作,就可以在回调函数里自己编写
没有做过多测试,如果哪里有问题,可以联系我!