Java之~ 上傳 圖片壓縮,圖片壓縮,圖片旋轉方法工具類
package com.javajy.util;
import java.awt.Dimension; import java.awt.Graphics2D; import java.awt.Image; import java.awt.Point; 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.util.Date;
import javax.imageio.ImageIO; import javax.media.jai.PlanarImage;
import org.apache.commons.io.IOUtils; import org.apache.commons.lang.StringUtils; 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.WatermarkParameter; import com.alibaba.simpleimage.render.WriteParameter; import com.alibaba.simpleimage.render.ScaleParameter.Algorithm; import com.alibaba.simpleimage.util.ImageCropHelper; import com.alibaba.simpleimage.util.ImageDrawHelper; import com.alibaba.simpleimage.util.ImageReadHelper; import com.alibaba.simpleimage.util.ImageScaleHelper; import com.alibaba.simpleimage.util.ImageWriteHelper; import com.drew.imaging.jpeg.JpegMetadataReader; import com.drew.imaging.jpeg.JpegProcessingException; import com.drew.metadata.Directory; import com.drew.metadata.Metadata; import com.drew.metadata.MetadataException; import com.drew.metadata.exif.ExifDirectory; import com.sun.image.codec.jpeg.*;
public class YasuoUtil {
/* @SuppressWarnings("deprecation") public static void main(String[] args) throws Exception { String path = resizeFix("D:\\workspace/frshop/src/main/webapp/image/123.jpg", "D:\\workspace/frshop/src/main/webapp/image/456.jpg");
System.out.println(path); System.out.println(path.substring(path.lastIndexOf("/") + 1)); System.out.println("結束:" + new Date().toLocaleString()); }*/ //--------------方法一----------------------
/** * @param fileName 原圖片路徑 * @param postPath 存放的壓縮圖片路徑 * @return * @throws IOException */ public static String resizeFix(String fileName, String postPath) throws IOException {
String path = ""; //此處是用來處理上傳圖片旋轉 int angel = getRotateAngleForPhoto(fileName);//旋轉圖片角度 fileName = rotatePhonePhoto(fileName, angel); //獲取旋轉後的圖片 File file = new File(fileName);// 讀入伺服器檔案 Image img = ImageIO.read(file); // 構造Image物件 int width = img.getWidth(null); // 得到源圖寬 int height = img.getHeight(null); // 得到源圖長 //把長跟寬等比縮小,大於1000就壓縮 if (width > 1000 || height > 1000) { int w = 500; int h = 500; if ((width >= 1000 && width < 3000) || (height >= 1000 && height < 3000)) { w = (int) (width / 2);//w int 新寬度 h = (int) (height / 2);//h int 新高度 } else if ((width >= 3000 && width < 5000) || (height >= 3000 && height < 5000)) { w = (int) (width / 3);//w int 新寬度 h = (int) (height / 3);//h int 新高度 } else if ((width >= 5000) || (height >= 5000)) { w = (int) (width / 5);//w int 新寬度 h = (int) (height / 5);//h int 新高度 } resize(img, w, h, postPath);//源寬度或長度大於1000的時候進行壓縮圖片 path = postPath; } else {//圖片寬高小於1000的時候顯示原圖 path = fileName;//路徑 } return path; }
/** * 強制壓縮/放大圖片到固定的大小 * * @param w int 新寬度 * @param h int 新高度 */ public static void resize(Image img, int w, int h, String postPath) throws IOException { String path = ""; // SCALE_SMOOTH 的縮略演算法 生成縮圖片的平滑度的 優先順序比速度高 生成的圖片質量比較好 但速度慢 BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB); image.getGraphics().drawImage(img, 0, 0, w, h, null); // 繪製縮小後的圖 // File destFile = new File("D:\\專案/鏈焙/圖片/654.png"); File destFile = new File(postPath); FileOutputStream out = new FileOutputStream(destFile); // 輸出到檔案流 // 可以正常實現bmp、png、gif轉jpg JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out); encoder.encode(image); // JPEG編碼 out.close(); } //----------------------------以下為阿里壓縮 多種型別 方法二------------------- /** * 阿里巴巴 simpleimage 圖片處理工具類 功能 等比例縮放 裁切 加水印 複合操作 * */ // public static String WATER_IMAGE_URL = "D:\\img\\watermark.png";//打水印 protected static ImageFormat outputFormat = ImageFormat.JPEG;
/* public static void main(String[] args) { // 1.等比例縮放 scaleNormal("D:\\workspace/frshop/src/main/webapp/image/123.jpg", "D:\\workspace/frshop/src/main/webapp/image/456.jpg"); // 2.等比例縮放加水印 // scaleWithWaterMark("D:\\img\\src.jpg", // "D:\\img\\scaleWithWaterMark.jpg",720, 1080); // 3.縮放到指定寬度 // scaleWithWidth("D:\\123.png", "D:\\456.jpg",400); // 4.縮放到指定高度 // scaleWithHeight("D:\\img\\src.jpg", "D:\\img\\scaleWithHeight.jpg", // 600); // 5.裁切成正方形 // Cut("D:\\img\\src.jpg", "D:\\img\\cut.jpg"); // 6.從中間裁切 // CutCenter("D:\\img\\src.jpg", "D:\\img\\cutCenter.jpg", 600,800); // print(40,20, 4,2); // print(20,40, 4,2); // print(40,20, 4,3);
}*/ //等比例壓縮(不剪裁) public final static String scaleNormal(String src, String target) { String path=""; File out = new File(target); // 目的圖片 FileOutputStream outStream = null; int angel = getRotateAngleForPhoto(src);//此處是用來處理上傳圖片旋轉 src = rotatePhonePhoto(src, angel); File in = new File(src); // 原圖片路徑 FileInputStream inStream = null; try { inStream = new FileInputStream(in); ImageWrapper imageWrapper = ImageReadHelper.read(inStream); int w = imageWrapper.getWidth();//原圖寬 int h = imageWrapper.getHeight();//原圖高 int width = 720;//新寬度 int height = 1080;//新高度
int cw=w, ch=h,x=0,y=0; boolean isDeal=true; if(height>h || width>w){ isDeal=false; }else if((w - width)>(h-height)){ ch=h; cw=(h*width)/height; x=(w-cw)/2; if(cw>h){ cw=w; ch=(w*height)/width; y=(h-ch)/2; x=0; } }else if((w - width)<=(h-height)){ cw=w; ch=(w*height)/width; y=(h-ch)/2; if(ch>h){ ch=h; cw=(h*width)/height; x=(w-cw)/2; y=0; } } System.out.println("x: "+x+" y" +y+"cw: "+cw+" ch"+ch+""); if(isDeal){ // CropParameter cropParam = new CropParameter(x, y, cw, ch);// 裁切引數 // PlanarImage planrImage = ImageCropHelper.crop(imageWrapper.getAsPlanarImage(), cropParam); // ScaleParameter scaleParam = new ScaleParameter(width, height, Algorithm.LANCZOS); // 縮放參數 // planrImage = ImageScaleHelper.scale(planrImage, scaleParam); // imageWrapper = new ImageWrapper(planrImage); // 1.縮放 ScaleParameter scaleParam = new ScaleParameter(w, h, Algorithm.LANCZOS); // 縮放參數 if (w < width) {// 如果圖片寬和高都小於目標圖片則不做縮放處理 scaleParam = new ScaleParameter(w, h, Algorithm.LANCZOS); } else { int newHeight = getHeight(w, h, width); scaleParam = new ScaleParameter(width, newHeight + 1, Algorithm.LANCZOS); } PlanarImage planrImage = ImageScaleHelper.scale(imageWrapper.getAsPlanarImage(), scaleParam); imageWrapper = new ImageWrapper(planrImage); } // 4.輸出 outStream = new FileOutputStream(out); String prefix = out.getName().substring(out.getName().lastIndexOf(".") + 1); ImageWriteHelper.write(imageWrapper, outStream, outputFormat.getImageFormat(prefix), new WriteParameter()); if(!isDeal){ path = src; }else { path = target; } } catch (IOException e) { e.printStackTrace(); } catch (SimpleImageException e) { } finally { IOUtils.closeQuietly(inStream); // 圖片檔案輸入輸出流必須記得關閉 IOUtils.closeQuietly(outStream);
} System.out.println("原圖-------"+src+"壓縮--------"+target); return path; } /** * * @param pInput * @param pImgeFlag * @return * @throws Exception */ public static boolean isPicture(String pInput, String pImgeFlag) throws Exception { if (StringUtils.isBlank(pInput)) { return false; } String tmpName = pInput.substring(pInput.lastIndexOf(".") + 1, pInput.length()); String imgeArray[][] = {{"bmp", "0"}, {"dib", "1"}, {"gif", "2"}, {"jfif", "3"}, {"jpe", "4"}, {"jpeg", "5"}, {"jpg", "6"}, {"png", "7"}, {"tif", "8"}, {"tiff", "9"}, {"ico", "10"}}; for (int i = 0; i < imgeArray.length; i++) { if (!StringUtils.isBlank(pImgeFlag) && imgeArray[i][0].equals(tmpName.toLowerCase()) && imgeArray[i][1].equals(pImgeFlag)) { return true; } if (StringUtils.isBlank(pImgeFlag) && imgeArray[i][0].equals(tmpName.toLowerCase())) { return true; } } return false; }
/** * 等比例縮放 會裁切部分內容 * * @param src * @param target * @param width * @param height */ @SuppressWarnings("static-access") public final static void scale(String src, String target, int width, int height) { File out = new File(target); // 目的圖片 FileOutputStream outStream = null; File in = new File(src); // 原圖片 FileInputStream inStream = null; try { inStream = new FileInputStream(in); ImageWrapper imageWrapper = ImageReadHelper.read(inStream);
int w = imageWrapper.getWidth(); int h = imageWrapper.getHeight(); float w1= 0f, h1 = 0f; float sp = (float) w / h; float rp = (float) width / height; if (sp > rp) { w1 = (width * h) / (float)w; h1 = width;
} else if(sp<rp){ h1 = (height * w) /(float) h; w1 = width; }else{ w1=width; h1=height; } // 1.縮放 ScaleParameter scaleParam = new ScaleParameter((int)w1, (int)h1, Algorithm.LANCZOS); // 縮放參數 PlanarImage planrImage = ImageScaleHelper.scale(imageWrapper.getAsPlanarImage(), scaleParam); imageWrapper = new ImageWrapper(planrImage); // 4.輸出 outStream = new FileOutputStream(out); String prefix = out.getName().substring(out.getName().lastIndexOf(".") + 1); ImageWriteHelper.write(imageWrapper, outStream, outputFormat.getImageFormat(prefix), new WriteParameter()); } catch (IOException e) { e.printStackTrace(); } catch (SimpleImageException e) { } finally { IOUtils.closeQuietly(inStream); // 圖片檔案輸入輸出流必須記得關閉 IOUtils.closeQuietly(outStream);
} }
/** * 壓縮圖片到 指定尺寸,圖片比目標圖片小則不會變形(有水印) * * @param src * @param target * @param width * @param height */ public final static void scaleWithWaterMark(String src, String target, int width, int height) { File out = new File(target); // 目的圖片 FileOutputStream outStream = null; File in = new File(src); // 原圖片 FileInputStream inStream = null; try { inStream = new FileInputStream(in); ImageWrapper imageWrapper = ImageReadHelper.read(inStream); int w = imageWrapper.getWidth(); int h = imageWrapper.getHeight(); int cw=w, ch=h,x=0,y=0; boolean isDeal=true; if(height>h||width>w){ isDeal=false; }else if((w - width)>(h-height)){ ch=h; cw=(h*width)/height; x=(w-cw)/2; if(cw>h){ cw=w; ch=(w*height)/width; y=(h-ch)/2; x=0; } }else if((w - width)<=(h-height)){ cw=w; ch=(w*height)/width; y=(h-ch)/2; if(ch>h){ ch=h; cw=(h*width)/height; x=(w-cw)/2; y=0; } } System.out.println("x: "+x+" y" +y+"cw: "+cw+" ch"+ch+""); if(isDeal){ CropParameter cropParam = new CropParameter(x, y, cw, ch);// 裁切引數 PlanarImage planrImage = ImageCropHelper.crop(imageWrapper.getAsPlanarImage(), cropParam); ScaleParameter scaleParam = new ScaleParameter(width, height, Algorithm.LANCZOS); // 縮放參數 planrImage = ImageScaleHelper.scale(planrImage, scaleParam); imageWrapper = new ImageWrapper(planrImage); } // 3.打水印 // BufferedImage waterImage = ImageIO.read(new File(WATER_IMAGE_URL)); BufferedImage waterImage = ImageIO.read(new File("D:\\img\\watermark.png")); ImageWrapper waterWrapper = new ImageWrapper(waterImage); Point p =calculate(imageWrapper.getWidth(),imageWrapper.getHeight(), waterWrapper.getWidth(), waterWrapper.getHeight()); WatermarkParameter param = new WatermarkParameter(waterWrapper, 1f,(int) p.getX(),(int) p.getY()); BufferedImage bufferedImage = ImageDrawHelper.drawWatermark(imageWrapper.getAsBufferedImage(), param); imageWrapper = new ImageWrapper(bufferedImage); // 4.輸出 outStream = new FileOutputStream(out); String prefix = out.getName().substring(out.getName().lastIndexOf(".") + 1); ImageWriteHelper.write(imageWrapper, outStream, outputFormat.getImageFormat(prefix), new WriteParameter()); } catch (IOException e) { e.printStackTrace(); } catch (SimpleImageException e) { } finally { IOUtils.closeQuietly(inStream); // 圖片檔案輸入輸出流必須記得關閉 IOUtils.closeQuietly(outStream);
}
} /** * 縮放到指定寬度 高度自適應 * * @param src * @param target * @param width */ @SuppressWarnings("static-access") public final static void scaleWithWidth(String src, String target, Integer width) { File out = new File(target); // 目的圖片 FileOutputStream outStream = null; File in = new File(src); // 原圖片 FileInputStream inStream = null; try { inStream = new FileInputStream(in); ImageWrapper imageWrapper = ImageReadHelper.read(inStream);
int w = imageWrapper.getWidth(); int h = imageWrapper.getHeight(); // 1.縮放 ScaleParameter scaleParam = new ScaleParameter(w, h, Algorithm.LANCZOS); // 縮放參數 if (w < width) {// 如果圖片寬和高都小於目標圖片則不做縮放處理 scaleParam = new ScaleParameter(w, h, Algorithm.LANCZOS); } else { int newHeight = getHeight(w, h, width); scaleParam = new ScaleParameter(width, newHeight + 1, Algorithm.LANCZOS); } PlanarImage planrImage = ImageScaleHelper.scale(imageWrapper.getAsPlanarImage(), scaleParam); imageWrapper = new ImageWrapper(planrImage); // 4.輸出 outStream = new FileOutputStream(out); String prefix = out.getName().substring(out.getName().lastIndexOf(".") + 1); ImageWriteHelper.write(imageWrapper, outStream, outputFormat.getImageFormat(prefix), new WriteParameter()); } catch (IOException e) { e.printStackTrace(); } catch (SimpleImageException e) { } finally { IOUtils.closeQuietly(inStream); // 圖片檔案輸入輸出流必須記得關閉 IOUtils.closeQuietly(outStream);
}
} /** * 縮放到指定高度,寬度自適應 * * @param src * @param target * @param height */ public final static void scaleWithHeight(String src, String target, Integer height) { File out = new File(target); // 目的圖片 FileOutputStream outStream = null; File in = new File(src); // 原圖片 FileInputStream inStream = null; try { inStream = new FileInputStream(in); ImageWrapper imageWrapper = ImageReadHelper.read(inStream);
int w = imageWrapper.getWidth(); int h = imageWrapper.getHeight(); // 1.縮放 ScaleParameter scaleParam = new ScaleParameter(w, h, Algorithm.LANCZOS); // 縮放參數 if (w < height) {// 如果圖片寬和高都小於目標圖片則不做縮放處理 scaleParam = new ScaleParameter(w, h, Algorithm.LANCZOS);
} else { int newWidth = getWidth(w, h, height); scaleParam = new ScaleParameter(newWidth + 1, height, Algorithm.LANCZOS);
} PlanarImage planrImage = ImageScaleHelper.scale(imageWrapper.getAsPlanarImage(), scaleParam); imageWrapper = new ImageWrapper(planrImage); // 4.輸出 outStream = new FileOutputStream(out); String prefix = out.getName().substring(out.getName().lastIndexOf(".") + 1); ImageWriteHelper.write(imageWrapper, outStream, outputFormat.getImageFormat(prefix), new WriteParameter()); } catch (IOException e) { e.printStackTrace(); } catch (SimpleImageException e) { } finally { IOUtils.closeQuietly(inStream); // 圖片檔案輸入輸出流必須記得關閉 IOUtils.closeQuietly(outStream);
}
} /** * 根據寬、高和目標寬度 等比例求高度 * * @param w * @param h * @param width * @return */ public static Integer getHeight(Integer w, Integer h, Integer width) {
return h * width / w; } /** * 根據寬、高和目標高度 等比例求寬度 * * @param w * @param h * @param height * @return */ public static Integer getWidth(Integer w, Integer h, Integer height) { return w * height / h; } /** * 從中間裁切需要的大小 * * @param src * @param target * @param width * @param height */ @SuppressWarnings("static-access") public final static void CutCenter(String src, String target, Integer width, Integer height) { File out = new File(target); // 目的圖片 FileOutputStream outStream = null; File in = new File(src); // 原圖片 FileInputStream inStream = null; try { inStream = new FileInputStream(in); ImageWrapper imageWrapper = ImageReadHelper.read(inStream);
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); // 4.輸出 outStream = new FileOutputStream(out); String prefix = out.getName().substring(out.getName().lastIndexOf(".") + 1); ImageWriteHelper.write(imageWrapper, outStream, outputFormat.getImageFormat(prefix), new WriteParameter()); } catch (IOException e) { e.printStackTrace(); } catch (SimpleImageException e) { } finally { IOUtils.closeQuietly(inStream); // 圖片檔案輸入輸出流必須記得關閉 IOUtils.closeQuietly(outStream); } } /** * 裁切 為正文形 * * @param src * @param target */ public final static void Cut(String src, String target) { File out = new File(target); // 目的圖片 FileOutputStream outStream = null; File in = new File(src); // 原圖片 FileInputStream inStream = null; try { inStream = new FileInputStream(in); ImageWrapper imageWrapper = ImageReadHelper.read(inStream);
int w = imageWrapper.getWidth(); int h = imageWrapper.getHeight(); int width = 0; int height = 0;
if (w >= h) { width = h; height = h; } else { width = w; height = w; } CropParameter cropParam = new CropParameter(0, 0, width, height);// 裁切引數 PlanarImage planrImage = ImageCropHelper.crop(imageWrapper.getAsPlanarImage(), cropParam); imageWrapper = new ImageWrapper(planrImage); // 4.輸出 outStream = new FileOutputStream(out); String prefix = out.getName().substring(out.getName().lastIndexOf(".") + 1); ImageWriteHelper.write(imageWrapper, outStream, outputFormat.getImageFormat(prefix), new WriteParameter()); } catch (IOException e) { e.printStackTrace(); } catch (SimpleImageException e) { } finally { IOUtils.closeQuietly(inStream); // 圖片檔案輸入輸出流必須記得關閉 IOUtils.closeQuietly(outStream); } } public static Point calculate(int enclosingWidth, int enclosingHeight, int width, int height) { int x = (enclosingWidth / 2) - (width / 2); int y = (enclosingHeight / 2) - (height / 2); return new Point(x, y); } //--------------------------------------以下是調整原圖豎拍旋轉問題 ---------------------------------------- /** * 上傳圖片旋轉問題 * * 1.首先獲取圖片正確顯示需要旋轉的角度(順時針) * @return */ public static int getRotateAngleForPhoto(String filePath){ File file = new File(filePath); int angle = 0; Metadata metadata; try { metadata = JpegMetadataReader.readMetadata(file); Directory directory = metadata.getDirectory(ExifDirectory.class); if(directory.containsTag(ExifDirectory.TAG_ORIENTATION)){ // Exif資訊中方向 int orientation = directory.getInt(ExifDirectory.TAG_ORIENTATION); // 原圖片的方向資訊 if(6 == orientation ){ //6旋轉90 angle = 90; }else if( 3 == orientation){ //3旋轉180 angle = 180; }else if( 8 == orientation){ //8旋轉90 angle = 270; } } } catch (JpegProcessingException e) { e.printStackTrace(); } catch (MetadataException e) { e.printStackTrace(); } return angle; } /** * 2.呼叫 旋轉的手機照片 * @param fullPath //原圖路徑 * @param angel //傳入1. * @return */ public static String rotatePhonePhoto(String filePath, int angel){ if(angel == 0){ return filePath; } BufferedImage src; try { src = ImageIO.read(new File(filePath)); int src_width = src.getWidth(null); int src_height = src.getHeight(null); Rectangle rect_des = CalcRotatedSize(new Rectangle(new Dimension(src_width, src_height)), angel);
BufferedImage res = new BufferedImage(rect_des.width, rect_des.height,BufferedImage.TYPE_INT_RGB); Graphics2D g2 = res.createGraphics();
g2.translate((rect_des.width - src_width) / 2, (rect_des.height - src_height) / 2); g2.rotate(Math.toRadians(angel), src_width / 2, src_height / 2);
g2.drawImage(src, null, null); ImageIO.write(res, "jpg", new File(filePath)); } catch (IOException e) { e.printStackTrace(); } return filePath; } public static Rectangle CalcRotatedSize(Rectangle src, int angel) { // if angel is greater than 90 degree, we need to do some conversion if (angel >= 90) { if(angel / 90 % 2 == 1){ int temp = src.height; src.height = src.width; src.width = temp; } angel = angel % 90; }
double r = Math.sqrt(src.height * src.height + src.width * src.width) / 2; double len = 2 * Math.sin(Math.toRadians(angel) / 2) * r; double angel_alpha = (Math.PI - Math.toRadians(angel)) / 2; double angel_dalta_width = Math.atan((double) src.height / src.width); double angel_dalta_height = Math.atan((double) src.width / src.height);
int len_dalta_width = (int) (len * Math.cos(Math.PI - angel_alpha - angel_dalta_width)); int len_dalta_height = (int) (len * Math.cos(Math.PI - angel_alpha - angel_dalta_height)); int des_width = src.width + len_dalta_width * 2; int des_height = src.height + len_dalta_height * 2; return new java.awt.Rectangle(new Dimension(des_width, des_height)); }
}