IM-上传图片

图片上传,有时会遇到三星手机传上来的是竖拍的照片,需要单独处理

  1. 增加POM依赖
<!-- 图片旋转处理 https://mvnrepository.com/artifact/com.drewnoakes/metadata-extractor -->
            <dependency>
                <groupId>com.drewnoakes</groupId>
                <artifactId>metadata-extractor</artifactId>
                <version>2.7.0</version>
            </dependency>
  1. 代码实现

import com.drew.imaging.ImageMetadataReader;
import com.drew.metadata.Directory;
import com.drew.metadata.Metadata;
import com.drew.metadata.Tag;
import com.drew.metadata.exif.ExifIFD0Directory;
import lombok.extern.slf4j.Slf4j;

import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.stream.ImageInputStream;
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;

/**
 * 图片旋转处理
 * https://blog.csdn.net/qq_43501821/article/details/132296979
 * @author xxx
 */
@Slf4j
public class ImageRotate {
    public static void main(String[] args) {
        java.util.List<String> list = new ArrayList<String>();
        Arrays.asList("20240914_101154.jpg", "IMG_3926.jpeg", "IMG_5226.jpeg", "IMG_6418.jpeg", "88a93450-231b-4778-bf41-99c6f2e50544.png").forEach(name -> {
            list.add(name);

        });
        String filePath = "/Users/xx/Downloads/";
        for (String fileName : list) {
            // 读取图片文件
            File imageFile = new File(filePath + fileName);
            try {
                String fullName = filePath + fileName;
                int index = fullName.lastIndexOf(".");
                String targetImgPath = fullName.substring(0, fullName.lastIndexOf(".")) + "_rotate." + getFileExtension(fileName);
                String[] filename = fileName.split("\\.");
                File targetFile = File.createTempFile(filename[0], filename[1]);
                boolean bCorrect = correctImg(imageFile, targetFile); // new File(targetImgPath)
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 获取文件扩展名
     * @param fileName 文件名
     * @return 文件扩展名
     */
    public static String getFileExtension(String fileName) {
        if (fileName == null || fileName.isEmpty()) {
            return "";
        }

        int lastIndexOfDot = fileName.lastIndexOf(".");
        if (lastIndexOfDot >= 0 && lastIndexOfDot < fileName.length() - 1) {
            return fileName.substring(lastIndexOfDot + 1);
        } else {
            return "";
        }
    }

    /**
     * 纠正图片旋转
     *
     * @param srcFile 原始图片
     * @param targetImgFile 目标图片地址
     * @return 是否需要纠正成功, true: 需要纠正, false: 无需纠正
     *
     */
    public static boolean correctImg(File srcFile, File targetImgFile) throws Exception {
        FileOutputStream fos = null;
        try {
            // 1.获取纠正
            RectifyDirection rotateAngle = getRectifyDirection(srcFile);
            // 2.无需纠正直接返回
            if (rotateAngle == null) {
                return false;
            }
            // 原始图片缓存
            BufferedImage srcImg = ImageIO.read(srcFile);

            // 原始宽度
            int imgWidth = srcImg.getWidth();
            // 原始高度
            int imgHeight = srcImg.getHeight();

            // 3.如果不是垂直的就代表他们的宽高需要互换
            if (rotateAngle.angel != 180) {
                int temp = imgWidth;
                imgWidth = imgHeight;
                imgHeight = temp;
            }

            // 中心点位置
            double centerWidth = ((double) imgWidth) / 2;
            double centerHeight = ((double) imgHeight) / 2;

            // 图片缓存
            BufferedImage targetImg = new BufferedImage(imgWidth, imgHeight, BufferedImage.TYPE_INT_RGB);

            // 旋转对应角度
            Graphics2D g = targetImg.createGraphics();
            // 4.以中心点位置 向左旋转
            g.rotate(Math.toRadians(rotateAngle.angel), centerWidth, centerHeight);
            // 5.旋转后图片的宽高就又替换了。
            // 6.这里就需要找到替换后原有的宽高与现有的宽高,从这个坐标开始绘制图片
            int x = (imgWidth - srcImg.getWidth()) / 2;
            int y = (imgHeight - srcImg.getHeight()) / 2;
            g.drawImage(srcImg, x, y, null);
            g.dispose();
            // 7.是否需要水平翻转
            if (rotateAngle.isMirror) {
                BufferedImage tempImage = new BufferedImage(targetImg.getWidth(), targetImg.getHeight(), BufferedImage.TYPE_INT_RGB);
                g = tempImage.createGraphics();
                // 使用 AffineTransform 进行水平翻转
                AffineTransform transform = new AffineTransform();
                // 8.平移现在图片的宽度后
                transform.translate(targetImg.getWidth(), 0);
                // 9. 缩放
                // 因为横坐标缩放是-1,所以是水平翻转
                // 翻转过程见水平翻转图片
                transform.scale(-1, 1);
                g.setTransform(transform);

                g.drawImage(targetImg, 0, 0, null);
                g.dispose();
                targetImg = tempImage;
            }

            // 输出图片
            fos = new FileOutputStream(targetImgFile);
            String formatName = getFormatName(srcFile);
            ImageIO.write(targetImg, formatName, fos);
            log.info("图片纠正成功:" + targetImgFile.getAbsolutePath());
        } catch (Exception e) {
            log.warn("图片纠正失败:" + targetImgFile.getName(), e);
            return false;
        } finally {
            if (fos != null) {
                try {
                    fos.flush();
                    fos.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        return true;
    }

    /**
     * 获取纠正方向
     *
     * @param file
     * @return
     * @throws Exception
     */
    public static RectifyDirection getRectifyDirection(File file) throws Exception {
        // 1.获取图片的元数据
        Metadata metadata = ImageMetadataReader.readMetadata(file);
        // 2.图片元数据处理那种方向
        int orientation = 0;

        for (Directory directory : metadata.getDirectories()) {
            // 3.只需要TAG_ORIENTATION的数据即可。
            if (directory.containsTag(ExifIFD0Directory.TAG_ORIENTATION)) {
                orientation = directory.getInt(ExifIFD0Directory.TAG_ORIENTATION);
                for (Tag tag : directory.getTags()) {
                    System.out.println(tag);
                }
            }
        }
        // 4.根据不同的orientation创建不同的处理方式
        switch (orientation) {
            case 2:
                return new RectifyDirection(0, true);
            case 3:
                return new RectifyDirection(180, false);
            case 4:
                return new RectifyDirection(180, true);
            case 5:
                return new RectifyDirection(90, true);
            case 6:
                return new RectifyDirection(90, false);
            case 7:
                return new RectifyDirection(270, true);
            case 8:
                return new RectifyDirection(270, false);
            default:
                return null;
        }
    }

    static class RectifyDirection {
        /**
         * 角度
         */
        public int angel;
        /**
         * 是否镜像
         */
        public boolean isMirror;

        public RectifyDirection(int angel, boolean isMirror) {
            this.angel = angel;
            this.isMirror = isMirror;
        }
    }

    /**
     * 获取图片格式
     *
     * @param file
     * @return
     */
    private static String getFormatName(File file) {
        try {
            ImageInputStream iis = ImageIO.createImageInputStream(file);
            ImageReader reader = ImageIO.getImageReaders(iis).next();
            reader.setInput(iis);

            String format = reader.getFormatName();
            iis.close();
            return format;
        } catch (IOException e) {
            e.printStackTrace();
        }
        String srcImgPath = file.getName();
        return srcImgPath.substring(srcImgPath.lastIndexOf(".") + 1);
    }
}```

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值