java處理圖片壓縮、裁剪


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();
            }
        }
    }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM