获取图片Exif信息

 

获取图片Exif信息

问题:手机照片上传时,会发现ios手机上传竖拍照片会逆时针旋转90度,横拍照片无此问题;而Android不会出现这种现象。

原因:ios系统默认Orientation属性为1,与常规机器拍摄图片的Orientation属性不一致。

方案:读取文件Exif信息,获取Orientation属性,修改Orientation属性为0。

Orientation属性属性说明如下:

旋转角度参数
1
顺时针90°6
逆时针90°8
180°3

读取Exif信息:

(依赖:metadata-extractor-2.10.1.jar,xmpcore-5.1.2.jar)

package com.minivision.gmepartner.test;

import com.drew.imaging.ImageMetadataReader;
import com.drew.imaging.ImageProcessingException;
import com.drew.metadata.Directory;
import com.drew.metadata.Metadata;
import com.drew.metadata.Tag;

import java.io.File;
import java.io.IOException;

/**
 * Description:  <br/>
 * <p>
 * Author:liuyinfei
 * ===============================
 * Created with IntelliJ IDEA.
 * Date: 2019/1/24
 * ================================
 */
public class RotateAngleUtil {
    /**
     * 图片数据元提取
     */
    public static void metadataExtractor(){
        File jpegFile = new File("C:\\Users\\80613\\Desktop\\svn\\download-wps图片.jpg");
        try {
            Metadata metadata = ImageMetadataReader.readMetadata(jpegFile);
            for (Directory directory : metadata.getDirectories()) {
                for (Tag tag : directory.getTags()) {
                    System.out.println(tag);
                }
            }
        } catch (ImageProcessingException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        metadataExtractor();

    }
}
package img;
 
import java.awt.Color;
import java.awt.Graphics2D;
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.OutputStream;
import java.util.Iterator;
import javax.imageio.ImageIO;
import javax.media.jai.PlanarImage;
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.WriteParameter;
import com.alibaba.simpleimage.util.ImageCropHelper;
import com.alibaba.simpleimage.util.ImageWriteHelper;
import com.drew.imaging.ImageMetadataReader;
import com.drew.imaging.ImageProcessingException;
import com.drew.metadata.Directory;
import com.drew.metadata.Metadata;
import com.drew.metadata.exif.ExifImageDirectory;
 
/**
 * 测试  获取图片旋转信息并处理
 * 图片旋转和剪切
 * @date 2018年1月30日 下午6:48:30
 */
public class CatchEXIF2 {
     
    public static void main(String[] args) throws Exception {
        // 输入输出文件路径/文件
        String src = "D:\\test\\微信图片_20180130193655.jpg";
        String dest = "D:\\test\\teswwwwt.jpg";
        File srcFile = new File(src);
        File destFile = new File(dest);
        // 将输入文件转换为字节数组
        byte[] bytes = getByte(srcFile);
        // 构造输入输出字节流
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        ByteArrayInputStream is = new ByteArrayInputStream(bytes);
         
        /*处理图片*/
        // 判断是否旋转并纠正
        BufferedImage bufferedImage = getExifAndTurn(bytes);
        // 缩放和剪切
        zoomAndCut(bufferedImage, os, 400, 400);
         
        // 将字节输出流写到输出文件路径下
        writeFile(os, destFile);
        os.close();
        is.close();
    }
     
    /**
     * 获取图片信息,并判断是否要做旋转操作
     * (ios图片可能会发生旋转现象)
     * @param is
     */
    public static BufferedImage getExifAndTurn(byte[] bytes){
        ByteArrayInputStream is = null;
        ByteArrayInputStream its = null;
        BufferedImage result = null;
        try {
            is = new ByteArrayInputStream(bytes);
            Metadata metadata = ImageMetadataReader.readMetadata(is);
            Iterable<Directory> directories = metadata.getDirectories();
            Iterator<Directory> iterator = directories.iterator();
            int orientation = 0;
            int angel = 360;
            while (iterator.hasNext()) {
                Directory exif = iterator.next();
                // 获取图片旋转信息
                if (exif.containsTag(ExifImageDirectory.TAG_ORIENTATION)) {
                    String description = exif.getDescription(ExifImageDirectory.TAG_ORIENTATION);
                    orientation = getOrientation(description);
                }
            }
             
            if(orientation == 0 || orientation == 1) { 
                angel = 360; 
            } 
            else if(orientation == 3) { 
                angel = 180; 
            } 
            else if(orientation == 6) { 
                angel = 90; 
            } 
            else if(orientation == 8) { 
                angel = 270; 
            } 
             
            its = new ByteArrayInputStream(bytes);
            result = ImageIO.read(its);
            // 旋转
            if(angel != 360){
                result = turn(result, angel);
            }
        } catch (ImageProcessingException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                its.close();
                is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return result;
    }
     
    /**
     * 获取图片旋转标志
     * @param description 图片旋转描述信息
     * @return
     */
    public static int getOrientation(String description) { 
        int orientation = 0; 
        if ("Top, left side (Horizontal / normal)".equalsIgnoreCase(description)) { 
            orientation = 1; 
        } else if ("Top, right side (Mirror horizontal)".equalsIgnoreCase(description)) { 
            orientation = 2; 
        } else if ("Bottom, right side (Rotate 180)".equalsIgnoreCase(description)) { 
            orientation = 3; 
        } else if ("Bottom, left side (Mirror vertical)".equalsIgnoreCase(description)) { 
            orientation = 4; 
        } else if ("Left side, top (Mirror horizontal and rotate 270 CW)".equalsIgnoreCase(description)) { 
            orientation = 5; 
        } else if ("Right side, top (Rotate 90 CW)".equalsIgnoreCase(description)) { 
            orientation = 6; 
        } else if ("Right side, bottom (Mirror horizontal and rotate 90 CW)".equalsIgnoreCase(description)) { 
            orientation = 7; 
        } else if ("Left side, bottom (Rotate 270 CW)".equalsIgnoreCase(description)) { 
            orientation = 8; 
        } 
        return  orientation; 
    } 
     
    /**
     * 图片旋转
     * @param degree 旋转角度
     */
    public static BufferedImage turn(BufferedImage bi, int degree) {
        BufferedImage result = null;
        try {
            int swidth = 0; // 旋转后的宽度
            int sheight = 0; // 旋转后的高度
            int x; // 原点横坐标
            int y; // 原点纵坐标
 
            // 处理角度--确定旋转弧度
            degree = degree % 360;
            if (degree < 0) {
                degree = 360 + degree;// 将角度转换到0-360度之间
            }
            double theta = Math.toRadians(degree);// 将角度转为弧度
 
            // 确定旋转后的宽和高
            if (degree == 180 || degree == 0 || degree == 360) {
                swidth = bi.getWidth();
                sheight = bi.getHeight();
            } else if (degree == 90 || degree == 270) {
                sheight = bi.getWidth();
                swidth = bi.getHeight();
            } else {
                swidth = (int) (Math.sqrt(bi.getWidth() * bi.getWidth() + bi.getHeight() * bi.getHeight()));
                sheight = (int) (Math.sqrt(bi.getWidth() * bi.getWidth() + bi.getHeight() * bi.getHeight()));
            }
            // 确定原点坐标
            x = (swidth / 2) - (bi.getWidth() / 2);
            y = (sheight / 2) - (bi.getHeight() / 2);
 
            result = new BufferedImage(swidth, sheight, bi.getType());
            // 设置图片背景颜色
            Graphics2D gs = (Graphics2D) result.getGraphics();
            gs.setColor(Color.white);
            gs.fillRect(0, 0, swidth, sheight);// 以给定颜色绘制旋转后图片的背景
 
            AffineTransform at = new AffineTransform();
            at.rotate(theta, swidth / 2, sheight / 2);// 旋转图象
            at.translate(x, y);
            AffineTransformOp op = new AffineTransformOp(at, AffineTransformOp.TYPE_BICUBIC);
            result = op.filter(bi, result);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }
     
     
    /**
     * 将file文件转为字节数组
     * @param file
     */
    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();
            }
        }
    }
 
    /**
     * 先等比例缩放,小边缩放至指定长度后, 大边直接裁剪指指定长度
     * @param bufferedImage
     * @param os
     * @param width
     * @param height
     */
    public static void zoomAndCut(BufferedImage bufferedImage, OutputStream os, Integer width, Integer height) {
        try {
            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);
            // 写文件
            ImageWriteHelper.write(imageWrapper, os, ImageFormat.getImageFormat("jpg"), new WriteParameter());
            os.close();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (SimpleImageException e) {
            e.printStackTrace();
        }
    }
}

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值