这几天在写一个博客的Demo,然后就碰到了这么一个问题,那些网站上点击个人头像就可以更换编辑的功能是怎么实现的?带着这么一个需求,我就在网络上搜集资料。整理了一下。图片真正被裁剪是在后端实现的。至于前端页面。则是使用javascript选择区域而已。然后把参数传到后端。由后端去处理。前端javascript的代码我就贴个网址,大家参考一下:http://www.yxsss.com/ui/img.html。这是个应用。直接查看其网页源代码就行了。
后端的开发。我这里贴个工具类。大家参考一下。不懂的可以查一下jdk文档。
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Iterator;
import javax.imageio.ImageIO;
import javax.imageio.ImageReadParam;
import javax.imageio.ImageReader;
import javax.imageio.stream.ImageInputStream;
/**
* 图像裁剪工具类
* @author Administrator
*
*/
public class ImageUtil {
/**
* 根据尺寸将图像居中裁剪
* @param src 源图像的存储路径
* @param desc 处理后的图像准备存储的路径
* @param w 裁剪要求的宽
* @param h 裁剪要求的高
* @throws FileNotFoundException
*/
public static void cutImageByCenter(String src, String desc, int w, int h) throws Exception{
//获得一个迭代器
Iterator iterator = ImageIO.getImageReadersByFormatName("jpg");
//使用迭代器将图片读取到一个图片字符流对象中
ImageReader reader = (ImageReader) iterator.next();
//获取图片的输入字节流
InputStream in = new FileInputStream(src);
//ImageInputStream是供 ImageReader 使用的可查找输入流接口。
ImageInputStream iis = ImageIO.createImageInputStream(in);
//设置用于给定的ImageInputStream 或其他Object的输入源
reader.setInput(iis,true);
//返回一个可以使用一组默认设置控制解码过程的 ImageReadParam 对象
ImageReadParam param = reader.getDefaultReadParam();
//图像索引
int imageIndex = 0;
//设置一个矩形区域。
Rectangle rect = new Rectangle((reader.getWidth(imageIndex)-w)/2,(reader.getHeight(imageIndex)-w)/2,w,h);
/*
* 设置感兴趣的源区域。感兴趣的区域杯描述成一个矩形。
* 源图像左上角为像素(0,0),该值向下向右递增。
*/
param.setSourceRegion(rect);
//将字符流图片加一个缓冲了流。
BufferedImage bi = reader.read(0, param);
//写进新文件中
ImageIO.write(bi, "jpg", new File(desc));
}
/**
* 将图片裁剪至二分之一
* @param src 源图像路径
* @param dest 裁剪后图像路径
* @throws IOException
*/
public static void cutHalfImage(String src,String dest) throws IOException{
Iterator iterator = ImageIO.getImageReadersByFormatName("jpg");
ImageReader reader = (ImageReader)iterator.next();
InputStream in=new FileInputStream(src);
ImageInputStream iis = ImageIO.createImageInputStream(in);
reader.setInput(iis, true);
ImageReadParam param = reader.getDefaultReadParam();
int imageIndex = 0;
int width = reader.getWidth(imageIndex)/2;
int height = reader.getHeight(imageIndex)/2;
Rectangle rect = new Rectangle(width/2, height/2, width, height);
param.setSourceRegion(rect);
BufferedImage bi = reader.read(0,param);
ImageIO.write(bi, "jpg", new File(dest));
}
/**
* 图片裁剪通用接口
* @param src 源图像路径
* @param dest 裁剪后图像路径
* @param x 裁剪的图像左上角横坐标
* @param y 裁剪的图像左上角纵坐标
* @param w 裁剪的图像的宽
* @param h 裁剪的图像的高
* @throws IOException
**/
public static void cutImage(String src,String dest,int x,int y,int w,int h) throws IOException{
Iterator iterator = ImageIO.getImageReadersByFormatName("jpg");
ImageReader reader = (ImageReader)iterator.next();
InputStream in=new FileInputStream(src);
ImageInputStream iis = ImageIO.createImageInputStream(in);
reader.setInput(iis, true);
ImageReadParam param = reader.getDefaultReadParam();
Rectangle rect = new Rectangle(x, y, w,h);
param.setSourceRegion(rect);
BufferedImage bi = reader.read(0,param);
ImageIO.write(bi, "jpg", new File(dest));
}
/**
* 将图像缩放
* @param src 源图像路径
* @param dest 缩放后图像路径
* @param w 缩放的图像的宽
* @param h 缩放的图像的高
* @throws Exception
*/
public static void zoomImage(String src,String dest,int w,int h) throws Exception {
double wr=0,hr=0;
File srcFile = new File(src);
File destFile = new File(dest);
BufferedImage bufImg = ImageIO.read(srcFile);
/*
* w - 将图像缩放到的宽度。
* h - 将图像缩放到的高度。
* bufImg.SCALE_SMOOTH - 指示用于图像重新取样的算法类型的标志。选择图像平滑度比缩放速度具有更高优先级的图像缩放算法
*/
Image Itemp = bufImg.getScaledInstance(w, h, bufImg.SCALE_SMOOTH);
//获得缩放比例值
wr=w*1.0/bufImg.getWidth();
hr=h*1.0 / bufImg.getHeight();
/*
* 此类使用仿射转换来执行从源图像或 Raster 中 2D 坐标到目标图像或 Raster 中 2D 坐标的线性映射。
* 参数:AffineTransform.getScaleInstance(wr, hr)表示缩放变换的变换矩阵,矩阵为:
* ----- [ sx 0 0 ] -----
* ----- [ 0 sy 0 ] -----
* ----- [ 0 0 1 ] -----
*/
AffineTransformOp ato = new AffineTransformOp(AffineTransform.getScaleInstance(wr, hr), null);
/*
* 转换源 BufferedImage 并将结果存储在目标 BufferedImage 中。
* 参数一:要转换的BufferedImage
* 参数二:要在其中存储转换结果的BufferedImage。
* 返回值:过滤后的BuffereedImage
*/
Itemp = ato.filter(bufImg, null);
try {
//写入图片。
ImageIO.write((BufferedImage) Itemp,dest.substring(dest.lastIndexOf(".")+1), destFile);
} catch (Exception ex) {
ex.printStackTrace();
}
}
}