概述
效果图预览:
用到的图片剪裁插件:http://www.htmleaf.com/jQuery/Image-Effects/201504211716.html
前段ui框架:bootstrap3
java后端框架:spring + mybstis
说明:如果前端ui用的不是bootstrap的框架,则调过第一步,直接将第二步的页面地址作为弹出框的地址即可,然后在做修改
1.首先说一下bootstrap的模态框:
一般的打开模态框要在页面上隐藏一段html代码然后用$("#Id").modal('show')显示模态框或者$("#Id").modal('hide')隐藏模态框,本人觉得有点麻烦,没有easyui这样的直接用js代码打开方便 ,所以我对这个模态框进行了封装。来实现直接用js打开的效果。原理很简单就是应以自定义一个jquery的方法,传递一些设置的参数,然后js动态生成html代码然后将代码追加到页面的body后面,然后在调用$("#Id").modal('show')方法来打开模态框。模态框里面的内容是动态的 所以就需要一个url地址加载页面的内容。下面来看js代码
bootstrap-utils.js
jQuery.extend({
//模态弹出框
openModel:function(options){
var defaults={//设置默认参数
title:'',//模态框的标题
width:'100%',//模态框的默认宽度
height:$(window).height()-130+"px",//模态框的默认高度,默认取浏览器的可视高度
showOkButton:true,//是否显示确定按钮
id:"model_js",//模态框id
frameId:"modal_iframe",//iframeId
okButtonContent:"确定",//确定按钮显示的内容
cancelButtonContent:"关闭"//取消按钮显示的内容
}
var opts = $.extend(defaults,options);
var str = "";
str+="<div class='modal fade' id='"+opts.id+"' tabindex='-1' role='basic' aria-hidden='true'>";
str+=" <div class='modal-dialog'>";
str+=" <div class='modal-content'>";
if(opts.title != ""){
str+=" <div class='modal-header' style='height:30px;'>";
str+=" <button type='button' class='close' data-dismiss='modal' aria-hidden='true' style='margin-top:-10px;'>x</button>";
str+=" <h3 class='modal-title' style='margin-top:-10px;'><b>"+opts.title+"</b></h3>";
str+=" </div>";
}
str+=" <div class='modal-body' style='padding:0px;'>";
str+=" </div>";
str+=" <div class='modal-footer' style='height:35px;padding:0px;'>";
if(opts.showOkButton){
str+=" <button type='button' class='btn btn-primary btn-sm' οnclick='"+opts.ok+"();'>"+opts.okButtonContent+"</button>";
}
str+=" <button type='button' class='btn btn-default btn-sm' data-dismiss='modal'>"+opts.cancelButtonContent+"</button>";
str+=" </div>";
str+=" </div>";
str+=" </div>";
str+="</div>";
//如果当前页面不选在当前id的模态框才追加模态框html
if($("body").find("#"+opts.id+"").length == 0){
$("body").append(str);
}else{
$("body").find("#"+opts.id+"").remove();
$("body").append(str);
}
//如果参数传递的宽度或者高度不是px格式的则加上px
var height = (opts.height+"").indexOf("px") >= 0 ? opts.height : opts.height+"px";
var width = (opts.width+"").indexOf("px") >= 0 || (opts.width+"").indexOf("%") >= 0 ? opts.width : opts.width+"px";
//设置页面iframe的地址
$("#"+opts.id+"").find(".modal-body").html("<iframe name='"+opts.frameId+"' style='width:99%;height:"+height+";border:0px;' scrolling='yes' src='"+opts.url+"'></iframe>");
$("#"+opts.id+"").find(".modal-dialog").css({"width":width,"height":height});
//显示模态框
$("#"+opts.id+"").modal("show");
}
});
下面来看调用方式:
$.openModel({
url:'editPhoto.jsp',
frameId:'bLogoFrame',
id:'bLogoModel',
width:900,
ok:'getCropData'//点击确定按钮执行的函数
});
2.下面来看editPhoto.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%
request.setAttribute("ctx", request.getContextPath());
%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<!-- 引入剪裁插件的css-->
<link rel="stylesheet" type="text/css" href="${ctx}/business/js/crop/css/normalize.css" />
<link rel="stylesheet" type="text/css" href="${ctx}/business/js/crop/css/default.css">
<link href="${ctx }/business/js/crop/assets/css/bootstrap.min.css" rel="stylesheet">
<link href="${ctx }/business/js/crop/dist/cropper.css" rel="stylesheet">
<link href="${ctx }/business/js/crop/css/main.css" rel="stylesheet">
<!--[if IE]>
<script src="http://libs.useso.com/js/html5shiv/3.7/html5shiv.min.js"></script>
<![endif]-->
<style type="text/css">
td{vertical-align:top;padding-left:10px;}
.div_photo{
position:absolute;
width:150px;
height:150px;
border-radius:100px;
}
</style>
<!-- 引入剪裁插件的js-->
<script src="${ctx }/business/js/crop/assets/js/jquery.min.js"></script>
<script src="${ctx }/business/js/crop/assets/css/bootstrap.min.css"></script>
<script src="${ctx }/business/js/crop/dist/cropper.js"></script>
<script src="${ctx }/business/js/crop/js/main.js"></script>
<script type="text/javascript">
var data;
function getData(){
var result= $('#cropper-img').cropper("getCroppedCanvas");
data=result.toDataURL('image/jpeg',1);//获取剪裁的图片并且转为base64格式
$("#data").val(data);//将剪裁后的base64代码保存的隐藏域中
$("#isValidate").val(1);//设置是否校验通过
}
</script>
</head>
<body οnlοad="javascript:$('#cropper-img').cropper('setAspectRatio',1);"><!-- 初始化剪裁你插件的剪裁比例为1:1,如需要其他的查看文档修改-->
<input style="display:none;" id="getData" οnclick="getData();" type="button" value="确定"/>
<input id="isValidate" type="hidden" value="0"/>
<input id="picName" type="hidden" value=""/>
<input id="data" type="hidden" value=""/>
<table style="margin-top:20px;">
<tr style="height:200px;">
<td rowspan="3">
<div class="img-container" style="width:630px;height:400px;margin-left:0px;">
<!-- 传递到这个页面的url不为空则显示要编辑的图片,否则显示默认的图片-->
<c:choose>
<c:when test="${url != null and url !='' }">
<img id="cropper-img" src="${url }">
</c:when>
<c:otherwise>
<img id="cropper-img" src="${ctx }/res/img/upimg.jpg">
</c:otherwise>
</c:choose>
</div>
</td>
<td>
<div class="docs-preview clearfix">
<div class="img-preview preview-lg"></div>
</div>
<div class="docs-preview clearfix">
<div class="img-preview preview-lg div_photo"></div>
</div>
</td>
</tr>
<tr style="height:20px;">
<td>
<div class="btn-group">
<label class="btn btn-primary btn-upload" style="border:0px;background-color:red;" for="inputImage" title="Upload image file">
<input class="sr-only" id="inputImage" name="file" type="file" accept="image/*">
<span class="docs-tooltip pull-left" data-toggle="tooltip" title="选择文件">
<span class="icon icon-upload"></span>
</span>
<span class="pull-right"> 选择图片</span>
</label>
</div>
</td>
</tr>
<tr style="height:20px;">
<td>
<div class="btn-group">
<button class="btn btn-primary" data-method="setDragMode" data-option="move" type="button" title="移动">
<span class="docs-tooltip" data-toggle="tooltip" title="$().cropper("setDragMode", "move")">
<span class="icon icon-move"></span>
</span>
</button>
<button class="btn btn-primary" data-method="setDragMode" data-option="crop" type="button" title="裁剪">
<span class="docs-tooltip" data-toggle="tooltip" title="$().cropper("setDragMode", "crop")">
<span class="icon icon-crop"></span>
</span>
</button>
<button class="btn btn-primary" data-method="zoom" data-option="0.1" type="button" title="放大">
<span class="docs-tooltip" data-toggle="tooltip" title="$().cropper("zoom", 0.1)">
<span class="icon icon-zoom-in"></span>
</span>
</button>
<button class="btn btn-primary" data-method="zoom" data-option="-0.1" type="button" title="缩小">
<span class="docs-tooltip" data-toggle="tooltip" title="$().cropper("zoom", -0.1)">
<span class="icon icon-zoom-out"></span>
</span>
</button>
<button class="btn btn-primary" data-method="rotate" data-option="-45" type="button" title="向左旋转">
<span class="docs-tooltip" data-toggle="tooltip" title="$().cropper("rotate", -45)">
<span class="icon icon-rotate-left"></span>
</span>
</button>
<button class="btn btn-primary" data-method="rotate" data-option="45" type="button" title="向右旋转">
<span class="docs-tooltip" data-toggle="tooltip" title="$().cropper("rotate", 45)">
<span class="icon icon-rotate-right"></span>
</span>
</button>
</div>
</td>
</tr>
</table>
</body>
</html>
说明:如果前端ui用的不是bootstrap,那么为了避免样式的冲突 可以用iframe的方式
例如:<a href="editPhotoInit.jsp">编辑头像</a>
editPhotoInit.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
String serviceId = request.getParameter("serviceId");
%>
<iframe src="<%=path %>/editPhoto.jsp?serviceId=<%=serviceId %>" style="width:99%;height:100%;border:0px;overflow:hidden;"></iframe>
然后在用第三步的方法取iframe对象里的属性
3.点击确定按钮的时候在页面上显示剪裁后的图片
第一步中我们讲到打开模态框的方式为:
$.openModel({
url:'editPhoto.jsp',
frameId:'bLogoFrame',
id:'bLogoModel',
width:900,
ok:'getCropData'//点击确定按钮执行的函数
});
点击ok按钮后执行的函数
var obj = $(window.frames["bLogoFrame"].document);//获取当前模态框内容的iframe对象,id即为上面设置的iframeId.
obj.find("#getData").click();//因为不能直接获取子页面的方法和属性,所以就用间接的点击按钮或者链接的方法,然后再获取隐藏域的内容,方法有点笨 ,有好的方法可以修改
var isValidate = obj.find("#isValidate").val();//校验图片大小及尺寸,1.为校验通过,0.为不通过
if(isValidate == 1){
var data = obj.find("#data").val();//获取剪裁后的base64图片
$("#logo").attr("src",data);//直接将剪裁后的base64图片显示在img控件中
var pos = data.indexOf("4")+2;
data = data.substring(pos, data.length - pos);//去掉Base64:开头的标识字符
$("#pic").val(data);//设置项后台提交的隐藏域的值,去掉base64开头的标示字符后的值
//设置表单中图片为校验通过
if(data != null && data != ""){
$("#addBusinessForm").bootstrapValidator('updateStatus', 'pic', 'VALID');
}
$("#bLogoModel").modal('hide');//关闭模态框
}
}
如果用封装的方法打开模态框,获取模态框的值都需要这样取(获取iframe对象,然后在获取 iframe对象中的元素,属性或者方法只能用间接的方法取),但是我觉得还是比在页面中直接写模态框的代码还是简单可许多呢。
4.上传图片
在第三不我们已经把剪裁后的base64的并且去掉了头部的标示信息的数据已经放到隐藏域中了,需要注意的是,base64的图片格式的数据一般来说都比较大,一般的post传递按理说是不受长度限制的,但是有时候后还是会出现问题,后台取不到值为null的情况,所以我们采用
formData+ajax的方式进行表单提交,下面来看代码
为提交表单的按钮绑定事件
$("#submitForm").click(function(){
var $form = $("#myForm");//获取当前form对象
var bv = $form.data('bootstrapValidator');//获取bootstrap表单校验对象
var formData = new FormData($form[0]);//转换成formData对象
//可以为formData添加数据,例如 :formData.append("file", $("#file_upload")[0].files[0]);
bv.validate();//校验表单
if(bv.isValid()){
$(obj).addClass('disabled');//置提交按钮为不可用,防止多次点击
$.ajax({
url : $form.attr('action'), //获取form表单的提交地址
type : 'POST',
async: false,
data : formData,
/**
* 必须false才会避开jQuery对 formdata 的默认处理
* XMLHttpRequest会对 formdata 进行正确的处理
*/
processData : false,
/**
*必须false才会自动加上正确的Content-Type
*/
contentType : false,
success : function(data) {
var id = data.id;
var opType = data.opType;//操作类型,1.编辑,0.添加
if(data.result == "1"){
alert("提交成功");
}else{
alert(data.message);//显示错误信息
$(obj).removeClass('disabled');
}
},error:function(){
alert("网络异常,请重试!");
$(obj).removeClass('disabled');
}
});
}else{
alert("表单数据不完整!");
}
});
后端代码,上传到七牛(与阿里云类似),如果上传到本地请查看第五步:
//获取上传到七牛的图片地址
String fileBusLogoPath = new QiniuUpload().base64Upload(‘前段传过来的base64格式’, ‘upload/photo/logo’);
说明:upload/photo/logo为logo上传地址,可以配置到属性配置文件中
比如:
systemConfig.properties
#七牛访问地址
qiniuUrl:http://7xsrph.com2.z0.glb.qiniucdn.com
#文件上传根目录
base_path:D:/image/
#商家logo上传地址
logo_path:upload/logo/
#商家二维码大小
qrcode_size:1000
怎么获取属性配置文件的值呢,这个需要在框架启动的时候把属性配置文件的值读取到java对象中,在spring配置文件的配置加如下代码:
spring.xml
<!-- 加载系统配置文件 -->
<property name="locations">
<list>
<value>classpath:systemConfig.properties</value>
</list>
</property>
</bean>
CustomizedPropertyConfigurer.java
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
public class CustomizedPropertyConfigurer extends PropertyPlaceholderConfigurer {
private static Map<String, Object> ctxPropertiesMap;
@Override
protected void processProperties(ConfigurableListableBeanFactory beanFactory,
Properties props)throws BeansException {
super.processProperties(beanFactory, props);
//load properties to ctxPropertiesMap
ctxPropertiesMap = new HashMap<String, Object>();
for (Object key : props.keySet()) {
String keyStr = key.toString();
String value = props.getProperty(keyStr);
ctxPropertiesMap.put(keyStr, value);
}
}
//static method for accessing context properties
public static Object getContextProperty(String name) {
return ctxPropertiesMap.get(name);
}
}
这样就可以通过CustomizedPropertyConfigurer类来获取属性配置文件的值
上传代码可以改为:
//获取logo上传路径
String logoPath = (String)CustomizedPropertyConfigurer.getContextProperty("logo_path");
String fileBusLogoPath = new QiniuUpload().base64Upload(‘前段传过来的base64格式’,logoPath);
然后将 fileBusLogoPath这个地址更新到数据库字段中,数据库保存的字段格式为:upload/logo/201605231403202561.jpg
显示给页面要拼接上七牛的访问地址:
图片完整的路径为:
String qiniuUrl = (String)CustomizedPropertyConfigurer.getContextProperty("qiniuUrl");
String logUrl = qiniuUrl+"/"+fileBusLogoPath;//图片完整路径
七牛上传工具类:QiniuUpload.java
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Random;
import javax.imageio.ImageIO;
import sun.misc.BASE64Decoder;
import com.qiniu.common.QiniuException;
import com.qiniu.http.Response;
import com.qiniu.storage.UploadManager;
import com.qiniu.util.Auth;
public class QiniuUpload {
private final String accessKey = "";
private final String secretKey = "";
private final String bucketname = "test";
private final String qiniuUrl = "http://7xsrph.com2.z0.glb.qiniucdn.com";//七牛地址
//密钥配置
Auth auth = Auth.create(accessKey, secretKey);
//创建上传对象
UploadManager uploadManager = new UploadManager();
//简单上传,使用默认策略,只需要设置上传的空间名就可以了
public String getUpToken(){
return auth.uploadToken(bucketname);
}
/**
* 字节流上传
* @param bytes
* @param filePath
* @return
* @throws IOException
*/
public String upload(byte[] bytes,String filePath) throws IOException{
try {
String fileName = filePath+getFileName();
//调用put方法上传
Response res = uploadManager.put(bytes, fileName, getUpToken());
return fileName;
} catch (QiniuException e) {
Response r = e.response;
// 请求失败时打印的异常的信息
System.out.println(r.toString());
try {
//响应的文本信息
System.out.println(r.bodyString());
} catch (QiniuException e1) {
//ignore
}
}
return null;
}
/**
* base64格式图片上传
* @param base64
* @param filePath
* @return
* @throws IOException
*/
public String base64Upload(String base64,String filePath) throws IOException{
try {
BASE64Decoder decoder = new BASE64Decoder();
// Base64解码
byte[] bytes = decoder.decodeBuffer(base64);
for (int i = 0; i < bytes.length; ++i) {
if (bytes[i] < 0) {// 调整异常数据
bytes[i] += 256;
}
}
String fileName = filePath+getFileName();
//调用put方法上传
Response res = uploadManager.put(bytes, fileName, getUpToken());
return fileName;
} catch (QiniuException e) {
Response r = e.response;
// 请求失败时打印的异常的信息
System.out.println(r.toString());
try {
//响应的文本信息
System.out.println(r.bodyString());
} catch (QiniuException e1) {
//ignore
}
}
return null;
}
/**
* 创建待logo的二维码
* @param filePath
* @param text
* @return
* @throws IOException
*/
public String createQrcode(String filePath,String text) throws IOException{
try {
// fileBusLogoPath.replace(".", "_qrCode.")
URL url = new URL(qiniuUrl+"/"+filePath);
// URLConnection conn = url.openConnection();
// urlcon.connect(); //获取连接
BufferedImage bufferedImg = ImageIO.read(url);
int width = bufferedImg.getWidth();
String fileName = filePath.replace(".", "_qrCode.");
BufferedImage bi = null;
BufferedImage logo = null;
logo = ImageUtils.resizeImage1(bufferedImg,100, 0.9f, true);
bi = QrCodeUtil.createQrCode(logo,text,width,width);
ByteArrayOutputStream os = new ByteArrayOutputStream();
ImageIO.write(bi, "jpg", os);
//调用put方法上传
Response res = uploadManager.put(os.toByteArray(),fileName, getUpToken());
System.out.println(res.toString());
return fileName;
} catch (QiniuException e) {
Response r = e.response;
// 请求失败时打印的异常的信息
System.out.println(r.toString());
try {
//响应的文本信息
System.out.println(r.bodyString());
} catch (QiniuException e1) {
//ignore
}
}
return null;
}
/**
* 获取时间格式的文件名称
* @return
*/
private String getFileName(){
SimpleDateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");
String now = df.format(new Date());
//生成五位随机数字
Random random = new Random();
int rannum = (int) (random.nextDouble() * (99999 - 10000 + 1)) + 10000;// 获取5位随机数
String fileName = now+rannum+".jpg";
return fileName;
}
/**
* 文件转byte[]
* @param filePath
* @return
*/
public static byte[] File2byte(String filePath)
{
byte[] buffer = null;
try
{
File file = new File(filePath);
FileInputStream fis = new FileInputStream(file);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
byte[] b = new byte[1024];
int n;
while ((n = fis.read(b)) != -1)
{
bos.write(b, 0, n);
}
fis.close();
bos.close();
buffer = bos.toByteArray();
}
catch (FileNotFoundException e)
{
e.printStackTrace();
}
catch (IOException e)
{
e.printStackTrace();
}
return buffer;
}
public static void main(String args[]) throws IOException{
URL url = new URL("http://imgz.we-going.com/service/1453884689193.jpg");
BufferedImage bufferedImg = ImageIO.read(url);
int width = bufferedImg.getWidth();
// new QiniuUpload().upload(File2byte("D:/image/upload/photo/business/2016/4/2016040923532026335.jpg"),"");
// new QiniuUpload().createQrcode("D:/image/upload/photo/business/2016/4/2016040923532026335.jpg","http://www.baidu.com");
}
}
二维码工具类:QrCodeUtil.java
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import javax.imageio.ImageIO;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.WriterException;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
/**
* 二维生成工具类,返回图片流或生成文件
* @author ZYL
*
*/
public class QrCodeUtil {
public static void main(String[] args) throws WriterException
{
String content = "766EBCD59621E305170616BA3D3DAC32";
String filePath = "D:/qrCode.jpg";
BufferedImage logo = null;
try
{
File file=new File("D://logo.png");
InputStream is=new FileInputStream(file);
logo = ImageIO.read(is);
// String path= "http://112.126.83.175/laiqu/head/20150612/SERVICE_HEAD_PHOTO_576_20150612123514641.png";
// URL url = new URL(path);
// HttpURLConnection conn = (HttpURLConnection) url.openConnection();
// logo = ImageIO.read(conn.getInputStream());
logo = ImageUtils.resizeImage1(logo,80, 0.9f, true);
createQrCode(logo,content,500,500,filePath);
}
catch (Exception e)
{
e.printStackTrace();
}
}
public static void createQrCode(BufferedImage logo,String content,int width,int height,String filePath){
try {
if(width == 0){width = 500;}
if(height == 0){height = 500;}
QrCodeUtil zp = new QrCodeUtil();
BufferedImage bi = null;
BufferedImage bim = zp.Encode_QR_CODE(content, BarcodeFormat.QR_CODE, width, height, zp.getDecodeHintType());
if(logo != null){
bi = zp.LogoMatrix(bim, logo);
}else{
bi = bim;
}
ImageIO.write(bi, "jpeg", new File(filePath));
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
public static BufferedImage createQrCode(BufferedImage logo,String content,int width,int height){
try {
if(width == 0){width = 500;}
if(height == 0){height = 500;}
QrCodeUtil zp = new QrCodeUtil();
BufferedImage bi = null;
BufferedImage bim = zp.Encode_QR_CODE(content, BarcodeFormat.QR_CODE, width, height, zp.getDecodeHintType());
if(logo != null){
bi = zp.LogoMatrix(bim, logo);
}else{
return bim;
}
// parseQR_CODEImage(bi);
return bi;
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
return null;
}
/**
* 设置 logo
* @param matrixImage 源二维码图片
* @return 返回带有logo的二维码图片
* @throws IOException
*/
public BufferedImage LogoMatrix(BufferedImage matrixImage,BufferedImage logo_) throws IOException{
/**
* 读取二维码图片,并构建绘图对象
*/
Graphics2D g2 = matrixImage.createGraphics();
int matrixWidth = matrixImage.getWidth();
int matrixHeigh = matrixImage.getHeight();
/**
* 读取Logo图片
*/
BufferedImage logo = logo_;
//开始绘制图片
g2.drawImage(logo,matrixWidth/5*2,matrixHeigh/5*2, matrixWidth/5, matrixHeigh/5, null);//绘制
BasicStroke stroke = new BasicStroke(5,BasicStroke.CAP_ROUND,BasicStroke.JOIN_ROUND);
g2.setStroke(stroke);// 设置笔画对象
//指定弧度的圆角矩形
RoundRectangle2D.Float round = new RoundRectangle2D.Float(matrixWidth/5*2, matrixHeigh/5*2, matrixWidth/5, matrixHeigh/5,20,20);
g2.setColor(Color.white);
g2.draw(round);// 绘制圆弧矩形
g2.dispose();
matrixImage.flush() ;
return matrixImage ;
}
/**
* 生成二维码bufferedImage图片
*
* @param content
* 编码内容
* @param barcodeFormat
* 编码类型
* @param width
* 图片宽度
* @param height
* 图片高度
* @param hints
* 设置参数
* @return
*/
public BufferedImage Encode_QR_CODE(String content, BarcodeFormat barcodeFormat, int width, int height, Map<EncodeHintType, ?> hints)
{
MultiFormatWriter multiFormatWriter = null;
BitMatrix bm = null;
BufferedImage image = null;
try
{
multiFormatWriter = new MultiFormatWriter();
// 参数顺序分别为:编码内容,编码类型,生成图片宽度,生成图片高度,设置参数
bm = multiFormatWriter.encode(content, barcodeFormat, width, height, hints);
int w = bm.getWidth();
int h = bm.getHeight();
image = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
// 开始利用二维码数据创建Bitmap图片,分别设为黑(0xFFFFFFFF)白(0xFF000000)两色
for (int x = 0; x < w; x++)
{
for (int y = 0; y < h; y++)
{
image.setRGB(x, y, bm.get(x, y) ? 0xFF000000 : 0xFFFFFFFF);
}
}
}
catch (WriterException e)
{
e.printStackTrace();
}
return image;
}
/**
* 设置二维码的格式参数
*
* @return
*/
public Map<EncodeHintType, Object> getDecodeHintType()
{
// 用于设置QR二维码参数
Map<EncodeHintType, Object> hints = new HashMap<EncodeHintType, Object>();
// 设置QR二维码的纠错级别(H为最高级别)具体级别信息
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
// 设置编码方式
hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
// hints.put(EncodeHintType.MAX_SIZE, 350);
// hints.put(EncodeHintType.MIN_SIZE, 100);
hints.put(EncodeHintType.MARGIN, 0);//设置二维码边的空度,非负数
return hints;
}
}
图片处理工具类:ImageUtils.java
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.HeadlessException;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.Transparency;
import java.awt.geom.Ellipse2D;
import java.awt.image.BufferedImage;
import java.awt.image.ConvolveOp;
import java.awt.image.Kernel;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Iterator;
import java.util.Random;
import javax.imageio.ImageIO;
import javax.imageio.ImageReadParam;
import javax.imageio.ImageReader;
import javax.imageio.stream.ImageInputStream;
import javax.swing.ImageIcon;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
import com.sun.image.codec.jpeg.ImageFormatException;
import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGImageEncoder;
/**
* @作者 王建明
* @创建日期 2012-6-16
* @创建时间 下午02:35:31
* @版本号 V 1.0
*/
public class ImageUtils {
public String path = "";
public ImageUtils(String path) {
this.path = path;
}
public void change(int size) {
compressImg(new File(path), size, null);
}
/**
* @param oldfile
* @param size
* @param newfile
* @return
* @描述 —— 将oldfile的图片文件等比例压缩为size的newfile文件
*/
public static File compressImg(File oldfile, int size, File newfile) {
if(!newfile.exists())
try {
newfile.createNewFile();
} catch (IOException e1) {
// TODO Auto-generated catch block
//e1.printStackTrace();
System.out.println("无法创建文件!!!");
return null;
}
BufferedImage bi;
try {
System.out.println("正在压缩:" + oldfile.getName());
bi = ImageIO.read(new FileInputStream(oldfile));
int width = bi.getWidth();
int height = bi.getHeight();
if (width > size || height > size) {
Image image;
if (width > height) {
height = (int) (bi.getHeight() / (bi.getWidth() * 1d) * size);
image = bi.getScaledInstance(size, height,
Image.SCALE_DEFAULT);
} else {
width = (int) (bi.getWidth() / (bi.getHeight() * 1d) * size);
image = bi.getScaledInstance(width, size,
Image.SCALE_DEFAULT);
}
ImageIO.write(toBufferedImage(image), "jpg",
new FileOutputStream(newfile));
System.out.println("压缩完成:" + newfile.getName());
return newfile;
} else {
System.out.println("无须压缩:" + oldfile.getName());
return oldfile;
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static BufferedImage toBufferedImage(Image image) {
if (image instanceof BufferedImage) {
return (BufferedImage) image;
}
image = new ImageIcon(image).getImage();
BufferedImage bimage = null;
GraphicsEnvironment ge = GraphicsEnvironment
.getLocalGraphicsEnvironment();
try {
int transparency = Transparency.TRANSLUCENT;
GraphicsDevice gs = ge.getDefaultScreenDevice();
GraphicsConfiguration gc = gs.getDefaultConfiguration();
bimage = gc.createCompatibleImage(image.getWidth(null), image
.getHeight(null), transparency);
} catch (HeadlessException e) {
}
if (bimage == null) {
int type = BufferedImage.TYPE_INT_RGB;
bimage = new BufferedImage(image.getWidth(null), image
.getHeight(null), type);
}
Graphics g = bimage.createGraphics();
g.drawImage(image, 0, 0, null);
g.dispose();
return bimage;
}
/**
* @return
* @描述 —— 生成随机名字,不可能重复(用于文件的命名)
*/
public static String getRandomName() {
Random r = new Random();
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd_HHmmssSSS");
StringBuffer sb = new StringBuffer();
sb.append(r.nextInt(100));
sb.append(r.nextInt(100));
sb.append("_");
sb.append(sdf.format(new Date()));
sb.append("_");
sb.append(r.nextInt(100));
sb.append(r.nextInt(100));
return sb.toString();
}
/**
* @param inputFile源文件
* @param outFile生成文件
* @param width指定宽度
* @param height指定高度
* @param proportion是否等比例操作
* @return
* @描述 —— 是否等比例缩放图片
*/
public static boolean compressPic(String inputFile, String outFile,
int width, int height, boolean proportion) {
try {
// 获得源文件
File file = new File(inputFile);
if (!file.exists()) {
return false;
}
Image img = ImageIO.read(file);
// 判断图片格式是否正确
if (img.getWidth(null) == -1) {
return false;
} else {
int newWidth;
int newHeight;
// 判断是否是等比缩放
if (proportion == true) {
// 为等比缩放计算输出的图片宽度及高度
double rate1 = ((double) img.getWidth(null))
/ (double) width + 0.1;
double rate2 = ((double) img.getHeight(null))
/ (double) height + 0.1;
// 根据缩放比率大的进行缩放控制
double rate = rate1 > rate2 ? rate1 : rate2;
newWidth = (int) (((double) img.getWidth(null)) / rate);
newHeight = (int) (((double) img.getHeight(null)) / rate);
} else {
newWidth = width; // 输出的图片宽度
newHeight = height; // 输出的图片高度
}
// 如果图片小于目标图片的宽和高则不进行转换
/*
* if (img.getWidth(null) < width && img.getHeight(null) <
* height) { newWidth = img.getWidth(null); newHeight =
* img.getHeight(null); }
*/
BufferedImage tag = new BufferedImage((int) newWidth,
(int) newHeight, BufferedImage.TYPE_INT_RGB);
// Image.SCALE_SMOOTH 的缩略算法 生成缩略图片的平滑度的,优先级比速度高 生成的图片质量比较好 但速度慢
tag.getGraphics().drawImage(
img.getScaledInstance(newWidth, newHeight,
Image.SCALE_SMOOTH), 0, 0, null);
FileOutputStream out = new FileOutputStream(outFile);
// JPEGImageEncoder可适用于其他图片类型的转换
JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
encoder.encode(tag);
out.close();
}
} catch (IOException ex) {
ex.printStackTrace();
}
return true;
}
/**
* @param srcFile源文件
* @param outFile输出文件
* @param x坐标
* @param y坐标
* @param width宽度
* @param height高度
* @return
* @描述 —— 裁剪图片
*/
public static boolean cutPic(String srcFile, String outFile, int x, int y,
int width, int height) {
FileInputStream is = null;
ImageInputStream iis = null;
try {
// 如果源图片不存在
if (!new File(srcFile).exists()) {
return false;
}
// 读取图片文件
is = new FileInputStream(srcFile);
// 获取文件格式
String ext = srcFile.substring(srcFile.lastIndexOf(".") + 1);
// ImageReader声称能够解码指定格式
Iterator<ImageReader> it = ImageIO.getImageReadersByFormatName(ext);
ImageReader reader = it.next();
// 获取图片流
iis = ImageIO.createImageInputStream(is);
// 输入源中的图像将只按顺序读取
reader.setInput(iis, true);
// 描述如何对流进行解码
ImageReadParam param = reader.getDefaultReadParam();
// 图片裁剪区域
Rectangle rect = new Rectangle(x, y, width, height);
// 提供一个 BufferedImage,将其用作解码像素数据的目标
param.setSourceRegion(rect);
// 使用所提供的 ImageReadParam 读取通过索引 imageIndex 指定的对象
BufferedImage bi = reader.read(0, param);
// 保存新图片
File tempOutFile = new File(outFile);
if (!tempOutFile.exists()) {
tempOutFile.mkdirs();
}
ImageIO.write(bi, ext, new File(outFile));
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
} finally {
try {
if (is != null) {
is.close();
}
if (iis != null) {
iis.close();
}
} catch (IOException e) {
e.printStackTrace();
return false;
}
}
}
/**
* @param doubleValue
* @return
* @描述 —— 将浮点型数据保留整数位转换成int型
*/
public static Integer getRoundIntFromDouble(Double doubleValue) {
return Integer.parseInt(String.valueOf(Math.round(doubleValue)));
}
public static String GetImageStr(String imgFilePath) {// 将图片文件转化为字节数组字符串,并对其进行Base64编码处理
byte[] data = null;
// 读取图片字节数组
try {
InputStream in = new FileInputStream(imgFilePath);
data = new byte[in.available()];
in.read(data);
in.close();
} catch (IOException e) {
e.printStackTrace();
}
// 对字节数组Base64编码
BASE64Encoder encoder = new BASE64Encoder();
return encoder.encode(data);// 返回Base64编码过的字节数组字符串
}
public static byte[] GenerateImage(String imgStr) {// 对字节数组字符串进行Base64解码并生成图片
if (imgStr == null) // 图像数据为空
return null;
BASE64Decoder decoder = new BASE64Decoder();
try {
// Base64解码
byte[] bytes = decoder.decodeBuffer(imgStr);
for (int i = 0; i < bytes.length; ++i) {
if (bytes[i] < 0) {// 调整异常数据
bytes[i] += 256;
}
}
return bytes;
} catch (Exception e) {
return null;
}
}
public static boolean GenerateImage(String imgStr, String imgFilePath) {// 对字节数组字符串进行Base64解码并生成图片
if (imgStr == null) // 图像数据为空
return false;
BASE64Decoder decoder = new BASE64Decoder();
try {
// Base64解码
byte[] bytes = decoder.decodeBuffer(imgStr);
for (int i = 0; i < bytes.length; ++i) {
if (bytes[i] < 0) {// 调整异常数据
bytes[i] += 256;
}
}
// 生成jpeg图片
OutputStream out = new FileOutputStream(imgFilePath);
out.write(bytes);
out.flush();
out.close();
return true;
} catch (Exception e) {
return false;
}
}
//将base64图片剪裁成圆形
public static boolean cutImgToRound(String image,String url){
if(image == null){
return false;
}
try {
BufferedImage bi1 = null;
BASE64Decoder decoder = new BASE64Decoder();
// Base64解码
byte[] bytes = decoder.decodeBuffer(image);
for (int i = 0; i < bytes.length; ++i) {
if (bytes[i] < 0) {// 调整异常数据
bytes[i] += 256;
}
}
ByteArrayInputStream in = new ByteArrayInputStream(bytes); //将b作为输入流;
bi1 = ImageIO.read(in);
// 根据需要是否使用 BufferedImage.TYPE_INT_ARGB
BufferedImage bi2 = new BufferedImage(bi1.getWidth(), bi1.getHeight(),
BufferedImage.TYPE_INT_RGB);
Ellipse2D.Double shape = new Ellipse2D.Double(0, 0, bi1.getWidth(), bi1
.getHeight());
Graphics2D g2 = bi2.createGraphics();
g2.setBackground(Color.WHITE);
g2.fill(new Rectangle(bi2.getWidth(), bi2.getHeight()));
g2.setClip(shape);
// 使用 setRenderingHint 设置抗锯齿
g2.drawImage(bi1, 0, 0, null);
g2.dispose();
ImageIO.write(bi2, "jpg", new File(url));
return true;
} catch (Exception e) {
// TODO: handle exception
return false;
}
}
/*public static void cutImgToRound(String imageUrl,String url){
BufferedImage bi1 = null;
try {
bi1 = ImageIO.read(new File(imageUrl));
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
// 根据需要是否使用 BufferedImage.TYPE_INT_ARGB
BufferedImage bi2 = new BufferedImage(bi1.getWidth(), bi1.getHeight(),
BufferedImage.TYPE_INT_RGB);
Ellipse2D.Double shape = new Ellipse2D.Double(0, 0, bi1.getWidth(), bi1
.getHeight());
Graphics2D g2 = bi2.createGraphics();
g2.setBackground(Color.WHITE);
g2.fill(new Rectangle(bi2.getWidth(), bi2.getHeight()));
g2.setClip(shape);
// 使用 setRenderingHint 设置抗锯齿
g2.drawImage(bi1, 0, 0, null);
g2.dispose();
try {
ImageIO.write(bi2, "jpg", new File(url));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}*/
//生成二维码
public static void createQrCode(String imageUrl,String url,String size,String text){
try {
int qrCodeSize = 100;
if(StringUtil.isNorBlank(size)){
qrCodeSize = Integer.parseInt(size);
}
BufferedImage bi = null;
BufferedImage logo = null;
logo = ImageUtils.resizeImage1(ImageIO.read(new File(imageUrl)),100, 0.9f, true);
bi = QrCodeUtil.createQrCode(logo,text,qrCodeSize,qrCodeSize);
ImageIO.write(bi, "jpg", new File(url));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* 等比缩放图片
*
* @param originalFile 源文件
* @param newLength 新的长度
* @param quality 照片质量(介于0~1之间)
* @param lengthFlag 长度标识(1、true newLength表示新图片宽;2、false newLength表示新图片高)
* @throws IOException
*/
public static BufferedImage resizeImage1(BufferedImage originalFile,int newLength, float quality, boolean lengthFlag) throws IOException {
FileOutputStream out = null;
try {
if (quality > 1) {
throw new IllegalArgumentException("Quality has to be between 0 and 1");
}
Image i = (Image)originalFile;
Image resizedImage = null;
int iWidth = i.getWidth(null);
int iHeight = i.getHeight(null);
if (lengthFlag) {
resizedImage = i.getScaledInstance(newLength, (newLength * iHeight) / iWidth, Image.SCALE_SMOOTH);
} else {
resizedImage = i.getScaledInstance((newLength * iWidth) / iHeight, newLength, Image.SCALE_SMOOTH);
}
// This code ensures that all the pixels in the image are loaded.
Image temp = new ImageIcon(resizedImage).getImage();
// Create the buffered image.
BufferedImage bufferedImage = new BufferedImage(temp.getWidth(null), temp.getHeight(null), BufferedImage.TYPE_INT_RGB);
// Copy image to buffered image.
Graphics g = bufferedImage.createGraphics();
// Clear background and paint the image.
g.setColor(Color.white);
g.fillRect(0, 0, temp.getWidth(null), temp.getHeight(null));
g.drawImage(temp, 0, 0, null);
g.dispose();
// Soften.
float softenFactor = 0.05f;
float[] softenArray = { 0, softenFactor, 0, softenFactor, 1 - (softenFactor * 4), softenFactor, 0, softenFactor, 0 };
Kernel kernel = new Kernel(3, 3, softenArray);
ConvolveOp cOp = new ConvolveOp(kernel, ConvolveOp.EDGE_NO_OP, null);
bufferedImage = cOp.filter(bufferedImage, null);
return bufferedImage;
} catch (ImageFormatException ex) {
System.out.println(ex.getMessage());
} finally {
if (out != null) {
out.close();
}
}
return null;
}
public static byte[] File2byte(String filePath)
{
byte[] buffer = null;
try
{
File file = new File(filePath);
FileInputStream fis = new FileInputStream(file);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
byte[] b = new byte[1024];
int n;
while ((n = fis.read(b)) != -1)
{
bos.write(b, 0, n);
}
fis.close();
bos.close();
buffer = bos.toByteArray();
}
catch (FileNotFoundException e)
{
e.printStackTrace();
}
catch (IOException e)
{
e.printStackTrace();
}
return buffer;
}
public static void main(String[] args) {
createQrCode("D://image/upload/photo/business/2016/4/2016040115190854796.jpg","D://aa.png","400","http://www.baidi.com");
}
}
5.上传到本地
获取文件上传根目录:
String basePath = (String)CustomizedPropertyConfigurer.getContextProperty("base_path");
//获取logo上传路径
Calendar cal = Calendar.getInstance();
//查询年/月
String endPath = cal.get(Calendar.YEAR) + "/" + (cal.get(Calendar.MONTH) + 1);
//上传图片并得到图片地址
String fileBusLogoPath = FileUpload.Base64Upload(basePath+logoPath+endPath, record.getPic());
保存fileBusLogoPath到数据库
图片上传工具类:FileUpload.java
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Random;
public class FileUpload {
public static String Base64Upload(String basePath,String base64File){
SimpleDateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");
String now = df.format(new Date());
//生成五位随机数字
Random random = new Random();
int rannum = (int) (random.nextDouble() * (99999 - 10000 + 1)) + 10000;// 获取5位随机数
String fileName = now+rannum+".jpg";
File file =new File(basePath);
//如果文件夹不存在则创建
if(!file .exists() && !file .isDirectory())
{
file.mkdirs();
}
ImageUtils.GenerateImage(base64File, basePath+"/"+fileName);
return basePath+"/"+fileName;
}
}
最后
以上就是负责悟空为你收集整理的bootstrap图片剪裁预览上传的全部内容,希望文章能够帮你解决bootstrap图片剪裁预览上传所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复