近期共组需要进行图片的上传以及切割,网上搜集了下资料,采用了jquery.imgareaselect.js 插件进行了图片的切割(也可考虑Jcrop),以及ajaxFileupload.js进行文件上传。
图片切割的原理是根据起始坐标以及宽高(或者终点坐标),对图片进行切割。
方法一:本地上传图片,使用插件预览本地图片(premage.js插件),使用插件进行切割获取坐标、宽高传回后台进行截取,但是遇到一些问题,首先就是图片最终上传问题以及宽高比例(显示图片的DIV宽高固定),所以最终采取了方法二。
方法二:本地上传图片,ajax上传到后台,返回地址显示切割框(后台把宽高比例计算好),使用插件进行切割,提交坐标以及宽高数据到后台对后台存在的图片进行切割替换。
开始上代码
采取框架:后台Java spingMVC,前台bootstrap(裁剪框就是modal模拟框)。
资源: imgareaselect-animated.css imgareaselect.js ajaxfileupload.js jquery.js
前台代码
上传图片标签
<pre name="code" class="html"> <div class="form-group">
<label class="col-md-3 control-label" for="img">Image</label>
<div class="col-md-4">
<input type="file" id="img" name="img" οnchange="uploadImage();">
<input type="hidden" id="pic-address" name="pic-address">
</div>
</div>
modal显示代码 用于上传图片后显示图片进行裁剪
<div class= "modal" id="modal-picture" data-backdrop ="true" tabindex="-1" role= "dialog" aria-hidden ="true">
<div class ="modal-dialog">
<div class ="modal-content">
<div class ="block block-themed block-transparent remove-margin-b">
<div class ="block-header bg-primary-dark">
<ul class ="block-options">
<li >
<button data-dismiss ="modal" type= "button"><i class ="si si-close"></ i></ button>
</li >
</ul >
<h3 class ="block-title">Picture Tailor</ h3>
</div >
<div class ="block-content">
<div class ="row">
<div class ="form-group">
<div class ="col-xs-12" style=" width: 330px; height: 300px;" >
<input type ="hidden" id= "width" value ="40"/>
<input type ="hidden" id= "height" value ="30"/>
<input type ="hidden" id="x" value= "0"/>
<input type ="hidden" id="y" value= "0"/>
</div >
</div >
</div >
</div >
</div >
<div class ="modal-footer">
<button class ="btn btn-sm btn-default" type= "button" data-dismiss= "modal">Close</button >
<button class ="btn btn-sm btn-primary" type= "button" data-dismiss= "modal" id="pic-tailor" >< i class= "fa fa-check"></i > Ok</button>
</div >
</div >
</div >
</div>
//---ajax 上传图片 以及返回数据 显示图片 显示modal进行裁剪
function uploadImage() {
if(isPicType($('#img').val())){
$.ajaxFileUpload({
url : 'restaurant/picture/upload',// 需要链接到服务器地址
fileElementId : 'img',// 文件选择框的id属性
dataType : 'json',// 服务器返回的格式,可以是json
type : 'post',
// data : {"operation":1},
success : function(data) {
if (data['result'] == 1) {
$("#modal-picture").modal();
$('#preview-img').remove();
$('<img id="preview-img" />').insertAfter($('#width'));
$("#preview-img").attr("src", data['path']);
// ---根据高宽 设置 等比例
$("#preview-img").removeAttr("style");
if (data['scale'] > 1.0) {
$("#preview-img").css(data['style'], "100%");
}
$('#preview-img').imgAreaSelect({
aspectRatio : '4:3',
handles : true,
x1 : 0,y1 : 0,x2 : 40,y2 : 30,
onSelectEnd : function(img, selection) {
$('#x').val(selection.x1 * data['scale']);
$('#y').val(selection.y1 * data['scale']);
$('#width').val(selection.width * data['scale']);
$('#height').val(selection.height * data['scale']);
}
});
$('#pic-tailor').click(function() {
cutImage(data['path']);
});
$('#pic-address').val(data['path']);
}
},
error : function(data) {
}
});
}
};
//---图片裁剪方法----
function cutImage(path) {
$.ajax({
type : "POST",
url : "restaurant/picture/imgCrop",
dateType : "json",
data : {
"x" : $('#x').val(),
"y" : $('#y').val(),
"width" : $('#width').val(),
"height" : $('#height').val(),
"path" : path
},
success : function(data) {
$('#pic-cut-show').attr('src', data);
}
});
};
//---判断文件是否是图片 错误使用notify悬浮框插件显示
function isPicType(picValue) {
var allowExtention = new Array("jpg", "png");
var len = picValue.length;
var math = picValue.substring(len - 3, len);
var f = false;
for (var i = 0; i < allowExtention.length; i++) {
if (allowExtention[i] == math) {
f = true;
}
}
if (!f) {
$.notify({
title : '<strong>Failure! </strong>',
message : 'Please choose correct image format.'
}, {
type : 'danger',
z_index : 2000
});
}
return f;
};
$("#modal-picture").on('hide.bs.modal',function(){
$('#preview-img').imgAreaSelect({ instance: true }).cancelSelection();
$("#preview-img").remove();
//---no handle --
$.ajax({
'url': 'restaurant/picture/delete',
type: 'POST',
data:{
path:$('#pic-address').val()
}});
});
springMVC 后台代码:
//----文件上传controller 以及返回必要信息
@RequestMapping(value = "/upload", method = RequestMethod.POST, produces = "text/plain; charset=utf-8")
@ResponseBody
public String upload(MultipartHttpServletRequest request)
throws IllegalStateException, IOException {
request.setCharacterEncoding("utf-8");
MultipartFile img = request.getFile("img");
String uPath = (String) request.getServletContext().getAttribute(
"uPath");
File dir = new File(uPath + tempImg_path);
if (!dir.exists()) {
dir.mkdirs();
}
SimpleDateFormat format = new SimpleDateFormat("yyyyMMddhhmmssSSS");
Date date = new Date();
String pic_path = null;
String result = "0"; // --标识是否成功--
int srcWidth = 0;
int srcHeight = 0;
if (img != null && !img.isEmpty()) {
int index = img.getOriginalFilename().lastIndexOf('.');
String picName = format.format(date)
+ img.getOriginalFilename().substring(index);
pic_path = "/assets" + tempImg_path + picName;
img.transferTo(new File(uPath + tempImg_path + picName));
BufferedImage bi = ImageIO.read(new File(uPath + tempImg_path
+ picName));
srcWidth = bi.getWidth();
srcHeight = bi.getHeight();
result = "1";
}
Map<String, String> data = new HashMap<String, String>();
data.put("result", result);
data.put("path", pic_path);
data.put("width", String.valueOf(srcWidth));
data.put("height", String.valueOf(srcHeight));
data.put("scale", ImgUtils.imgScale(srcWidth, srcHeight, 300, 300));
data.put("style", srcWidth >= srcHeight ? "width" : "height");
ObjectMapper mapper = new ObjectMapper();
String json = mapper.writeValueAsString(data);
return json;
}
//----图片裁剪方法---
@RequestMapping(value = "/imgCrop")
@ResponseBody
public String imgCrop(HttpServletRequest request) {
double x = Double.valueOf(request.getParameter("x"));
double y = Double.valueOf(request.getParameter("y"));
double width = Double.valueOf(request.getParameter("width"));
double height = Double.valueOf(request.getParameter("height"));
String path = request.getParameter("path");
// ---img path ----
String realPath = request.getServletContext().getRealPath("/");
String imgPath = realPath + ".." + path;
ImgUtils.imgCrop(imgPath, (int) x, (int) y, (int) width, (int) height);
return path;
}
/**
* 截取图片
*
* @param srcImageFilePath
* 原图片地址
* @param x
* 截取时的x坐标
* @param y
* 截取时的y坐标
* @param desWidth
* 截取的宽度
* @param desHeight
* 截取的高度
*/
public static void imgCrop(String srcImageFilePath, int x, int y,
int desWidth, int desHeight) {
try {
Image img;
ImageFilter cropFilter;
BufferedImage bi = ImageIO.read(new File(srcImageFilePath));
int srcWidth = bi.getWidth();
int srcHeight = bi.getHeight();
if (srcWidth >= desWidth && srcHeight >= desHeight) {
Image image = bi.getScaledInstance(srcWidth, srcHeight,
Image.SCALE_DEFAULT);
cropFilter = new CropImageFilter(x, y, desWidth, desHeight);
img = Toolkit.getDefaultToolkit().createImage(
new FilteredImageSource(image.getSource(), cropFilter));
BufferedImage tag = new BufferedImage(desWidth, desHeight,
BufferedImage.TYPE_INT_RGB);
Graphics g = tag.getGraphics();
g.drawImage(img, 0, 0, null);
g.dispose();
// 输出文件
ImageIO.write(tag, "JPEG", new File(srcImageFilePath));
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 分析图片的尺寸比例
* 2015年10月19日 下午2:22:34
*
* @param width
* @param height
* @param divWidth
* @param divHeight
* @return
*/
public static String imgScale(int width, int height, int divWidth,
int divHeight) {
Double scale = 1.0;
if (divWidth >= width && divHeight >= height) {
scale = 1.0;
}
if (width >= height && width >= divWidth) {
scale = (double) width / divWidth;
}
if (height > width && height >= divHeight) {
scale = (double) height / divHeight;
}
return String.valueOf(scale);
}