package img; import java.awt.Color; import java.awt.geom.AffineTransform; import java.awt.image.AffineTransformOp; import java.awt.image.BufferedImage; 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 javax.imageio.ImageIO; import javax.media.jai.PlanarImage; import org.apache.commons.io.IOUtils; import com.alibaba.simpleimage.ImageFormat; import com.alibaba.simpleimage.ImageWrapper; import com.alibaba.simpleimage.SimpleImageException; import com.alibaba.simpleimage.render.CropParameter; import com.alibaba.simpleimage.render.ScaleParameter; import com.alibaba.simpleimage.render.WriteParameter; import com.alibaba.simpleimage.render.ScaleParameter.Algorithm; import com.alibaba.simpleimage.util.ImageCropHelper; import com.alibaba.simpleimage.util.ImageReadHelper; import com.alibaba.simpleimage.util.ImageScaleHelper; import com.alibaba.simpleimage.util.ImageWriteHelper; /** * 圖片的壓縮、裁剪 */ public class Test { public static void main(String[] args) throws Exception { // 輸入輸出文件路徑/文件 String src = "D:\\test\\map.jpg"; String dest = "D:\\test\\map1.jpg"; File srcFile = new File(src); File destFile = new File(dest); // 將輸入文件轉換為字節數組 byte[] bytes = getByte(srcFile); // 構造輸入輸出字節流 ByteArrayInputStream is = new ByteArrayInputStream(bytes); ByteArrayOutputStream os = new ByteArrayOutputStream(); // 處理圖片 zoomAndCut2(is, os, 400, 400); // 將字節輸出流寫到輸出文件路徑下 writeFile(os, destFile); } /** * 按固定長寬進行縮放 * @param is 輸入流 * @param os 輸出流 * @param width 指定長度 * @param height 指定寬度 * @throws Exception */ public static void zoomImage(InputStream is, OutputStream os, int width, int height) throws Exception { //讀取圖片 BufferedImage bufImg = ImageIO.read(is); is.close(); //獲取縮放比例 double wRatio = width * 1.0/ bufImg.getWidth(); double hRatio = height * 1.0 / bufImg.getHeight(); AffineTransformOp ato = new AffineTransformOp(AffineTransform.getScaleInstance(wRatio, hRatio), null); BufferedImage bufferedImage = ato.filter(bufImg, null); //寫入縮減后的圖片 ImageIO.write(bufferedImage, "jpg", os); } /** * 按固定文件大小進行縮放 * @param is 輸入流 * @param os 輸出流 * @param size 文件大小指定 * @throws Exception */ public static void zoomImage(InputStream is, OutputStream os, Integer size) throws Exception { /*FileInputStream的available()方法返回的是int類型,當數據大於1.99G(2147483647字節)后將無法計量, 故求取流文件大小最好的方式是使用FileChannel的size()方法,其求取結果與File的length()方法的結果一致 參考:http://blog.csdn.net/chaijunkun/article/details/22387305*/ int fileSize = is.available(); //文件大於size時,才進行縮放。注意:size以K為單位 if(fileSize < size * 1024){ return; } // 獲取長*寬(面積)縮放比例 double sizeRate = (size * 1024 * 0.5) / fileSize; // 獲取長和寬分別的縮放比例,即面積縮放比例的2次方根 double sideRate = Math.sqrt(sizeRate); BufferedImage bufImg = ImageIO.read(is); AffineTransformOp ato = new AffineTransformOp(AffineTransform.getScaleInstance(sideRate, sideRate), null); BufferedImage bufferedImage = ato.filter(bufImg, null); ImageIO.write(bufferedImage, "jpg", os); } /** * 等比例縮放,以寬或高較大者達到指定長度為准 * @param src 輸入文件路徑 * @param dest 輸出文件路徑 * @param width 指定寬 * @param height 指定高 */ public static void zoomTo400(String src, String dest, Integer width, Integer height){ try { File srcFile = new File(src); File destFile = new File(dest); BufferedImage bufImg = ImageIO.read(srcFile); int w0 = bufImg.getWidth(); int h0 = bufImg.getHeight(); // 獲取較大的一個縮放比率作為整體縮放比率 double wRatio = 1.0 * width / w0; double hRatio = 1.0 * height / h0; double ratio = Math.min(wRatio, hRatio); // 縮放 AffineTransformOp ato = new AffineTransformOp(AffineTransform.getScaleInstance(ratio, ratio), null); BufferedImage bufferedImage = ato.filter(bufImg, null); // 輸出 ImageIO.write(bufferedImage, dest.substring(dest.lastIndexOf(".")+1), destFile); } catch (IOException e) { e.printStackTrace(); } } /** * 等比例圖片壓縮,以寬或高較大者達到指定長度為准 * @param is 輸入流 * @param os 輸出流 * @param width 寬 * @param height 高 * @throws IOException */ public static void changeSize(InputStream is, OutputStream os, int width, int height) throws IOException { BufferedImage bis = ImageIO.read(is); // 構造Image對象 is.close(); int srcWidth = bis.getWidth(null); // 得到源圖寬 int srcHeight = bis.getHeight(null); // 得到源圖高 if (width <= 0 || width > srcWidth) { width = bis.getWidth(); } if (height <= 0 || height > srcHeight) { height = bis.getHeight(); } // 若寬高小於指定最大值,不需重新繪制 if (srcWidth <= width && srcHeight <= height) { ImageIO.write(bis, "jpg", os); os.close(); } else { double scale = ((double) width / srcWidth) > ((double) height / srcHeight) ? ((double) height / srcHeight) : ((double) width / srcWidth); width = (int) (srcWidth * scale); height = (int) (srcHeight * scale); BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); bufferedImage.getGraphics().drawImage(bis, 0, 0, width, height, Color.WHITE, null); // 繪制縮小后的圖 ImageIO.write(bufferedImage, "jpg", os); os.close(); } } /** * 先等比例縮放,小邊縮放至指定長度后, 大邊直接裁剪指指定長度 * @param is * @param os * @param width * @param height */ public final static void zoomAndCut1(InputStream is, OutputStream os, int width, int height) throws SimpleImageException { // 讀文件 ImageWrapper imageWrapper = ImageReadHelper.read(is); int w = imageWrapper.getWidth(); int h = imageWrapper.getHeight(); double wRatio = 1.0 * width / w; double hRatio = 1.0 * height / h; double ratio = Math.max(wRatio, hRatio); /*1.縮放*/ // 縮放參數 如果圖片寬和高都小於目標圖片則不做縮放處理 ScaleParameter scaleParam = null; if (w < width && h < height) { scaleParam = new ScaleParameter(w, h, Algorithm.LANCZOS); } // 為防止強轉int時小數部分丟失,故加1,防止出現異常錯誤 scaleParam = new ScaleParameter((int)(w * ratio) + 1, (int)(h * ratio) + 1, Algorithm.LANCZOS); // 縮放 PlanarImage planarImage = ImageScaleHelper.scale(imageWrapper.getAsPlanarImage(), scaleParam); /*2.裁切*/ // 獲取裁剪偏移量 imageWrapper = new ImageWrapper(planarImage); int w2 = imageWrapper.getWidth(); int h2 = imageWrapper.getHeight(); int x = (w2 - width) / 2; int y = (h2 - height) / 2; // 裁切參數 如果圖片寬和高都小於目標圖片則處理 CropParameter cropParam = new CropParameter(x, y, width, height); if (x < 0 || y < 0) { cropParam = new CropParameter(0, 0, w, h); } // 裁剪 planarImage = ImageCropHelper.crop(planarImage, cropParam); /*輸出*/ imageWrapper = new ImageWrapper(planarImage); String prefix = "jpg"; ImageWriteHelper.write(imageWrapper, os, ImageFormat.getImageFormat(prefix), new WriteParameter()); } /** * 先等比例縮放,小邊縮放至指定長度后, 大邊直接裁剪指指定長度 * @param is * @param os * @param width * @param height */ public static void zoomAndCut2(InputStream is, OutputStream os, Integer width, Integer height) throws IOException, SimpleImageException{ // 讀文件 BufferedImage bufferedImage = ImageIO.read(is); int w = bufferedImage.getWidth(); int h = bufferedImage.getHeight(); // 獲取縮放比例 double wRatio = 1.0 * width / w; double hRatio = 1.0 * height / h; double ratio = Math.max(wRatio, hRatio); // 縮放 AffineTransformOp ato = new AffineTransformOp(AffineTransform.getScaleInstance(ratio, ratio), null); bufferedImage = ato.filter(bufferedImage, null); // 對象轉換 ImageWrapper imageWrapper = new ImageWrapper(bufferedImage); // 獲得裁剪偏移量 int w2 = imageWrapper.getWidth(); int h2 = imageWrapper.getHeight(); float x = (w2 - width) / 2.0f; float y = (h2 - height) / 2.0f; // 裁剪參數 如果圖片寬和高都小於目標圖片則處理 CropParameter cropParameter = new CropParameter(x, y, width, height); if (x < 0 && y < 0) { cropParameter = new CropParameter(0, 0, width, height); } PlanarImage crop = ImageCropHelper.crop(imageWrapper.getAsPlanarImage(), cropParameter); imageWrapper = new ImageWrapper(crop); // 后綴 String prefix = "jpg"; // 寫文件 ImageWriteHelper.write(imageWrapper, os, ImageFormat.getImageFormat(prefix), new WriteParameter()); } /** * 從中間裁切需要的大小 * @param is * @param os * @param width * @param height */ public static void CutCenter(InputStream is, OutputStream os, Integer width, Integer height) { try { ImageWrapper imageWrapper = ImageReadHelper.read(is); int w = imageWrapper.getWidth(); int h = imageWrapper.getHeight(); int x = (w - width) / 2; int y = (h - height) / 2; CropParameter cropParam = new CropParameter(x, y, width, height);// 裁切參數 if (x < 0 || y < 0) { cropParam = new CropParameter(0, 0, w, h);// 裁切參數 } PlanarImage planrImage = ImageCropHelper.crop(imageWrapper.getAsPlanarImage(), cropParam); imageWrapper = new ImageWrapper(planrImage); String prefix = "JPG"; ImageWriteHelper.write(imageWrapper, os, ImageFormat.getImageFormat(prefix), new WriteParameter()); } catch (Exception e) { e.printStackTrace(); } finally { IOUtils.closeQuietly(is); } } /** * 將file文件轉為字節數組 * @param file * @return */ public static byte[] getByte(File file){ byte[] bytes = null; try { FileInputStream fis = new FileInputStream(file); bytes = new byte[fis.available()]; fis.read(bytes); fis.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return bytes; } /** * 將字節流寫到指定文件 * @param os * @param file */ public static void writeFile(ByteArrayOutputStream os, File file){ FileOutputStream fos = null; try { byte[] bytes = os.toByteArray(); if (file.exists()) { file.delete(); } fos = new FileOutputStream(file); fos.write(bytes); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { try { fos.close(); } catch (IOException e) { e.printStackTrace(); } } } }