分享之前写的剪切图片工具

分享之前写的剪切图片工具

Scroll Down

package cn.farboy.common.utils;

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.ExifIFD0Directory;
import lombok.Getter;
import net.coobird.thumbnailator.Thumbnails;
import net.coobird.thumbnailator.geometry.Positions;
import org.apache.commons.lang3.StringUtils;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Arrays;
import java.util.Objects;

@Getter
public enum CutImageUtil {

    FORMAT_750_500(750, 500),
    FORMAT_600_600(600, 600);

    CutImageUtil(int width, int height) {
        this.width = width;
        this.height = height;
    }

    private static final String prefix = "CutImageUtil";
    private boolean sourceFromUrl = false;
    private int width;
    private int height;
    private File source;
    private File target;
    private String format;

    public CutImageUtil ofSource(File source) throws IOException {
        if (notImage(source))
            throw new IOException("This source file is NOT image");
        this.source = source;
        return this;
    }

    public CutImageUtil ofSource(String imageUrl) throws IOException {
        if (StringUtils.isBlank(imageUrl))
            throw new IOException("Please input image url");
        this.source = getFileByUrl(imageUrl);
        this.sourceFromUrl = true;
        return this;
    }

    public CutImageUtil ofTarget(String suffix) throws IOException {
        String realSuffix = suffix;
        if (StringUtils.isBlank(realSuffix) || notSupportFormat(suffix)) {
            realSuffix = ".jpeg";
        }
        if (!StringUtils.startsWith(realSuffix, "."))
            realSuffix = "." + realSuffix;
        this.format = StringUtils.substring(realSuffix, 1).toLowerCase();
        this.target = File.createTempFile(prefix, realSuffix);
        return this;
    }

    public File process() throws IOException {
        Objects.requireNonNull(this.source, "please use ofSource() to set source image file");
        if (Objects.isNull(target))
            this.ofTarget(null);
        Thumbnails.of(source)
                  .scale(this.getScale())
                  .outputQuality(1L)
                  .toFile(target);
        Thumbnails.of(target)
                  .sourceRegion(Positions.CENTER, this.width, this.height)
                  .size(this.width, this.height)
                  //.outputFormatType(format)
                  .keepAspectRatio(false)
                  .outputQuality(1L)
                  .toFile(target);
        if (this.sourceFromUrl)
            this.source.deleteOnExit();
        return target;
    }

    private boolean notImage(File source) {
        try {
            return Objects.isNull(ImageIO.read(source));
        } catch (IOException ex) {
            return true;
        }
    }

    private boolean notSupportFormat(String suffix) {
        if (StringUtils.isBlank(suffix)) return true;
        return Arrays.stream(ImageIO.getWriterFormatNames()).noneMatch(f -> f.equalsIgnoreCase(suffix));
    }

    /*
     * 计算图片的压缩比
     */
    private double getScale() {
        double scale = 1.000d;
        int width;
        int height;
        try {
            BufferedImage buffer = ImageIO.read(this.source);
            try {
                // 判断实际图片是否经过旋转
                Metadata metadata = JpegMetadataReader.readMetadata(this.source);
                Directory directory = metadata.getFirstDirectoryOfType(ExifIFD0Directory.class);
                int orientation = directory.getInt(ExifIFD0Directory.TAG_ORIENTATION);
                /**
                 * 3 旋转180度,长宽不变,图像倒置
                 * 6 旋转90度
                 * 8 旋转270度
                 */
                if (3 == orientation || 6 == orientation) {
                    width = buffer.getHeight();
                    height = buffer.getWidth();
                } else {
                    width = buffer.getWidth();
                    height = buffer.getHeight();
                }
            } catch (JpegProcessingException | MetadataException e) {
                width = buffer.getWidth();
                height = buffer.getHeight();
            }

            if (width >= this.width && height >= this.height) {
                if (width >= height) {
                    scale = (this.height * 1.00) / height;
                } else {
                    scale = (this.width * 1.00) / width;
                }
            }
            if (width >= this.width && height < this.height) {
                scale = (this.height * 1.00) / height;
            }
            if (width < this.width && height >= this.height) {
                scale = (this.width * 1.00) / width;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return scale;
    }

    private File getFileByUrl(String imageUrl) {
        ByteArrayOutputStream outStream = new ByteArrayOutputStream();
        BufferedOutputStream stream = null;
        InputStream inputStream = null;
        File file = null;
        try {
            URL url = new URL(imageUrl);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.163 Safari/537.36");
            inputStream = conn.getInputStream();
            byte[] buffer = new byte[1024];
            int len = 0;
            while ((len = inputStream.read(buffer)) != -1) {
                outStream.write(buffer, 0, len);
            }
            String suffix = StringUtils.substring(imageUrl, imageUrl.lastIndexOf("."));
            if (notSupportFormat(suffix)) {
                suffix = ".jpg";
            } else {
                suffix = "." + suffix;
            }
            file = File.createTempFile(prefix, "." + suffix);
            FileOutputStream fileOutputStream = new FileOutputStream(file);
            stream = new BufferedOutputStream(fileOutputStream);
            stream.write(outStream.toByteArray());
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (inputStream != null) inputStream.close();
                if (stream != null) stream.close();
                outStream.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return file;
    }

}