/* * Copyright (c) 2008-2016 Computer Network Information Center (CNIC), Chinese Academy of Sciences. * * This file is part of Duckling project. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ package cn.vlabs.umt.common.util; import java.awt.Graphics; import java.awt.Image; import java.awt.Rectangle; import java.awt.image.BufferedImage; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; 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; import javax.imageio.stream.ImageOutputStream; import org.apache.log4j.Logger; /** * 图片剪切, 缩放等工具类 * * @author lvly * @since 2012-08-09 */ public final class ImageUtils { private ImageUtils() { } private static final Logger LOG = Logger.getLogger(ImageUtils.class); public static final String PATH = File.separator + "resources" + File.separator + "temp" + File.separator; public static final String CUT_PREFIX = "_cut"; public static final String SCALE_PREFIX = "_scale"; public static final String SCALE_ORG_PREFIX = "_orgscale"; public static final int DEFAULT_SCALE_WIDTH = 100; public static final int DEFAULT_SCALE_HEIGHT = 100; public static final int DEFAULT_CUT_WIDTH = 100; public static final int DEFAULT_CUT_HEIGHT = 100; public static final String TYPE_IMG_GIF = "gif"; public static final String TYPE_IMG_JPG = "jpg"; public static final String TYPE_IMG_PNG = "png"; public static final String TYPE_IMG_UNKOWN = "jpg"; /** * 默认裁剪图片 * */ public static File defaultCut(File file){ File result=null; try { BufferedImage src = ImageIO.read(file); int width=src.getWidth(); int height=src.getHeight(); int x=0; int y=0; if(width<DEFAULT_CUT_WIDTH&&height<DEFAULT_CUT_HEIGHT){ result= cutting(file,0,0,width,height,1); } else if(width>height){ x=(width-height)/2; width=height; result= cutting(file, x, y, width, height, 1); }else if(width<height){ y=(height-width)/2; height=width; result= cutting(file,x,y,width,height,1); }else{ result= cutting(file,0,0,width,height,1); } } catch (IOException e) { LOG.error(e.getMessage(),e); } return scale(result); } /** * 剪切图片 * * @param file * 需要剪切的文件 * @param x * 剪切点的x坐标 * @param y * 剪切点的y坐标 * @param width * 剪切宽度 * @param height * 剪切高度 * @param scale * 很明显,大于1就是放大,小于1就是缩小 * @return */ private static File cutting(File file, int x, int y, int width, int height, float scale) { int xOrg = Math.round((x / scale)); int yOrg = Math.round((y / scale)); int widthOrg = Math.round((width / scale)); int heightOrg = Math.round((height / scale)); File newFile = null; InputStream is = null; ImageInputStream iis = null; ImageOutputStream out = null; try { is = new FileInputStream(file); iis = ImageIO.createImageInputStream(is); String endName = getType(file); Iterator<ImageReader> readers = ImageIO.getImageReadersByFormatName(endName); ImageReader reader = readers.next(); reader.setInput(iis, true); ImageReadParam param = reader.getDefaultReadParam(); param.setSourceRegion(new Rectangle(xOrg, yOrg, widthOrg, heightOrg)); BufferedImage bi = reader.read(0, param); newFile =File.createTempFile(System.nanoTime()+"", ".cut.end"); out = ImageIO.createImageOutputStream(new FileOutputStream(newFile)); ImageIO.write(bi, reader.getFormatName(), out); } catch (IOException e) { LOG.error(e.getMessage(), e); } finally { try {if (iis != null) {iis.close();} if (is != null) {is.close();} if (out != null) {out.close();} } catch (IOException e) { LOG.error(e); } } return newFile; } /** 获取暂存源文件 */ /** * @param cutPath * xxxx/xxxx/xx/xx.jpg_cut * @return xxx/xxx/xx/xx.jpg */ public static String getOrgPath(String finalPath) { return finalPath.replace(CUT_PREFIX, "").replace(SCALE_PREFIX, "").replace(SCALE_ORG_PREFIX, ""); } /** 获取暂存文件 */ /** * @param cutPath * xxxx/xxxx/xx/xx.jpg * @return xxx/xxx/xx/xx.jpg_cut */ public static String getCutPath(String orgPath) { return getOrgPath(orgPath) + CUT_PREFIX; } /** 获取缩放文件地址 */ /** * @param orgPath * 一般为裁剪完后的图片,xxx.jpg_cut_scale * @return 返回缩放地址 */ public static String getScalePath(String orgPath) { return getOrgPath(orgPath) + SCALE_PREFIX; } /** * 缩放图像 * * @param srcImageFile * 源图像文件地址 * @return 返回缩放后的图片 */ private static File scale(File srcImageFile) { return scale(srcImageFile, DEFAULT_SCALE_WIDTH, DEFAULT_SCALE_HEIGHT); } /** * 缩放图像 * * @param srcImageFile * 源图像文件地址 * @return 返回缩放后的图片 */ public static File scale(File srcImageFile, int defaultWidth, int defaultHeight) { try { BufferedImage src = ImageIO.read(srcImageFile); // 读入文件 int width = src.getWidth(); int height = src.getHeight(); if (width > defaultWidth || height > defaultHeight) { Rect r = proportation(width, height, defaultWidth, defaultHeight); width = r.getWidth(); height = r.getHeight(); } else { return srcImageFile; } Image image = src.getScaledInstance(width, height, Image.SCALE_DEFAULT); BufferedImage tag = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); Graphics g = tag.getGraphics(); g.drawImage(image, 0, 0, null); // 绘制缩小后的图 g.dispose(); File resultFile = File.createTempFile(System.nanoTime()+"", ".scale."+defaultWidth+"."+defaultHeight); ImageIO.write(tag, "JPEG", resultFile);// 输出到文件流 return resultFile; } catch (IOException e) { LOG.error(e); } return null; } /** * 填满原则,获得一个矩形实例 * * @param width * 物体宽 * @param height * 物体高 * @param maxWidth * 容器宽 * @param maxHeight * 容器高 * @return */ public static Rect proportation(int width, int height, int maxWidth, int maxHeight) { // 原图的高宽比例 float proportion = height / (float) width; // 框的高宽比例 float needProportation = maxHeight / (float) maxWidth; Rect r = new Rect(); // 说明物体偏高了 if (proportion > needProportation) { r.setHeight(maxHeight); r.setWidth((int) (maxHeight / proportion)); } // 说明物体偏宽了 else if (proportion < needProportation) { r.setHeight((int) (maxWidth * proportion)); r.setWidth(maxWidth); } else {// 长和宽一样 r.setHeight(maxHeight); r.setWidth(maxWidth); } return r; } private static String toStringBuffer(byte[] bytes,int...index){ StringBuffer sb=new StringBuffer(); for(int i:index){ sb.append((char)bytes[i]); } return sb.toString().toUpperCase(); } private static String getTypeFromLByte(byte[] b){ if ("GIF".equals(toStringBuffer(b,0,1,2))){ return TYPE_IMG_GIF; }else if ("PNG".equals(toStringBuffer(b,1,2,3))){ return TYPE_IMG_PNG; }else if ("JFIF".equals(toStringBuffer(b,6,7,8,9))){ return TYPE_IMG_JPG; }else if ("EXIF".equals(toStringBuffer(b,6,7,8,9))){ return TYPE_IMG_JPG; }else{ return TYPE_IMG_JPG; } } /*** * 根据文件头信息,判断图片格式 * * @param file * 文件(img) * */ public static String getType(File file) { FileInputStream fis = null; try { fis = new FileInputStream(file); byte[] b = new byte[10]; int byteNum = fis.read(b); if (byteNum < 10) { return TYPE_IMG_UNKOWN; } else { return getTypeFromLByte(b); } } catch (IOException e) { LOG.error(e.getMessage()); return TYPE_IMG_UNKOWN; } finally { if (fis != null) { try { fis.close(); } catch (IOException e) { LOG.error(e); } } } } } class Rect { private int width; private int height; public int getWidth() { return width; } public void setWidth(int width) { this.width = width; } public int getHeight() { return height; } public void setHeight(int height) { this.height = height; } }