java graphics2d 旋转图片

Wesley13
• 阅读 650

由于iphone拍出来的照片存在旋转的问题,当然在iphone上查看是没有问题的,但是如果是在安卓手机上或者使用windows 图片查看器就会发现图片是旋转90度的。有一些安卓手机拍出来的照片也是旋转的,比如三星的那个曲屏手机。所以需要程序去把图片旋转过来,变成正的,保证体验一致。

原理是通过metadata-extractor去检测图片的EXIF信息,获取图片的ORIENTATION信息

 <dependency>
       <groupId>com.drewnoakes</groupId>
       <artifactId>metadata-extractor</artifactId>
       <version>2.9.0</version>
 </dependency>

读取代码如下:

     public static int readImgExifOrientation(InputStream in){

        try {
            if (in.markSupported()) {
                Metadata metadata = ImageMetadataReader.readMetadata(in);
                in.reset();//重置流
                ExifIFD0Directory directory = metadata.getFirstDirectoryOfType(ExifIFD0Directory.class);
                if (directory != null) {

                    int tag = directory.getInt(ExifIFD0Directory.TAG_ORIENTATION);
                    logger.debug("方向: " + tag);
                    ExifIFD0Descriptor descriptor = new ExifIFD0Descriptor(directory);
                    logger.debug(descriptor.getOrientationDescription());

                    return tag;
                }
            }else {
                throw new RuntimeException("必须使用支持mark 的input stream");
            }
        } catch (Exception e) {
            logger.error("读取图片方向失败",e);
        }
        return 0;
    }

返回的tag值对应了一个旋转的角度。通过自己写的一个方法去对应。具体对应的是多少度可以去查看这个库的文档。这里只列举了这几个。

    private static float getRotate(int tag){
        switch (tag){
            case 3:
                return 180;
            case 5:
                return 270;
            case 6:
                return 90;
            case 7:
                return 270;
            case 8:
                return 90;
            default:return 0;
        }
    }

得到旋转的角度之后,我们就可以调用api去将图片再旋转回来。

     public static InputStream rotate(InputStream in,int tag,String suffix) throws Exception{
        double theta = Math.toRadians(getRotate(tag));
        if (theta == 0) {//不需要旋转
            return in;
        }
        if(suffix!=null){
            suffix = suffix.replaceAll("\\.", "");
        }else {
            suffix = ".jpg";
        }
        BufferedImage oldImg = ImageIO.read(in);
        int w = oldImg.getWidth();
        int h = oldImg.getHeight();
        BufferedImage newImg = new BufferedImage(h,w,oldImg.getColorModel().getTransparency());
        Graphics2D g2d =newImg.createGraphics();
        g2d.setRenderingHint(
                RenderingHints.KEY_INTERPOLATION,
                RenderingHints.VALUE_INTERPOLATION_BILINEAR);
        g2d.rotate(theta, w/2, h/2); //旋转
        g2d.drawImage(oldImg,  h,0, null);
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        ImageIO.write(newImg, suffix, out);
        g2d.dispose();
        return new ByteArrayInputStream(out.toByteArray());
    }

使用java2d中的旋转之后发现左下角会出现黑边,图片被截取。另外网上很多人写的代码都是创建一张跟原图相同宽高的图片,然后再旋转,但是这样操作之后黑边会出现在国内人边,并且图片也会被截取。

找了一些原因,由于对图形部分研究不深,无法解决。一直觉得做图形的都是牛比人物。最后采用另外一个库thumbnailator。

        <dependency>
            <groupId>net.coobird</groupId>
            <artifactId>thumbnailator</artifactId>
            <version>0.4.8</version>
        </dependency>

这个库操作很简单,两句话就可以进行旋转。

    public static InputStream rotate(InputStream in,int tag,String suffix) throws Exception{
        double theta = getRotate(tag);
        if (theta == 0) {//不需要旋转
            return in;
        }
        if(suffix!=null){
            suffix = suffix.replaceAll("\\.", "");
        }else {
            suffix = ".jpg";
        }
        BufferedImage oldImg = ImageIO.read(in);
        int w = oldImg.getWidth();
        int h = oldImg.getHeight();
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        Thumbnails.of(oldImg).size(h,w).rotate(theta).outputFormat(suffix).toOutputStream(out);
        return new ByteArrayInputStream(out.toByteArray());
    }
点赞
收藏
评论区
推荐文章
blmius blmius
2年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
凯特林 凯特林
3年前
移动端H5开发常用技巧总结
html篇常用的meta属性设置meta对于移动端的一些特殊属性,可根据需要自行设置<meta name"screenorientation" content"portrait" //Android 禁止屏幕旋转<meta name"fullscreen" content"yes"             //全屏显示
梦
3年前
微信小程序new Date()转换时间异常问题
微信小程序苹果手机页面上显示时间异常,安卓机正常问题image(https://imghelloworld.osscnbeijing.aliyuncs.com/imgs/b691e1230e2f15efbd81fe11ef734d4f.png)错误代码vardate'2021030617:00:00'vardateT
Easter79 Easter79
2年前
Taro小程序自定义顶部导航栏
微信自带的顶部导航栏是无法支持自定义icon和增加元素的,在开发小程序的时候自带的根本满足不了需求,分享一个封装好的组件,支持自定义icon、扩展dom,适配安卓、ios、h5,全面屏。我用的是京东的Taro多端编译框架写的小程序,原生的也可以适用,用到的微信/taro的api做调整就行,实现效果如下。!在这里插入图片描述(https://i
Wesley13 Wesley13
2年前
unity2017 光照与渲染(一)
光照&渲染(基于unity2017.2.0)1.CustomSkybox天空盒最丰富的环境光a.TextureShape改成Cube。b.把图片直接丢给天空,就会自动生成材质。c.参数Exposure曝光度,Rotation旋转天空盒。
Easter79 Easter79
2年前
Twitter的分布式自增ID算法snowflake (Java版)
概述分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的。有些时候我们希望能使用一种简单一些的ID,并且希望ID能够按照时间有序生成。而twitter的snowflake解决了这种需求,最初Twitter把存储系统从MySQL迁移
Wesley13 Wesley13
2年前
Ubuntu 安装 ImageMagick 库
ImageMagick介绍ImageMagick是一个用来创建、编辑、合成图片的软件。它可以读取、转换、写入多种格式的图片。图片切割、颜色替换、各种效果的应用,图片的旋转、组合,文本,直线,多边形,椭圆,曲线,附加到图片伸展旋转。ImageMagick是免费软件:全部源码开放,可以自由使用,复制,修改,发布。支持
Wesley13 Wesley13
2年前
Unity横屏
Android下发现Unity里面的Player设置,并不能完全有效,比如打开了自动旋转,启动的时候还是会横屏,修改XML添加以下代码<applicationandroid:icon"@drawable/ic\_launcher"                    android:label"@string/app\_name"
Wesley13 Wesley13
2年前
video 标签存在的一些坑
最近做的些web页面,内嵌许多小视频,在ios和安卓手机上播放时,遇到不少问题:在微信浏览器内播放时,视频会自动全屏如果每个视频都有一张自定义的图片作为封面,在显示视频的同时,如果没有给这个视频设置高度,视频的容器在安卓手机上会被视频的封面撑大到变形<videoclass"videosource"width"10
Stella981 Stella981
2年前
OpenCV旋转图片
MatrotateImage(constMat&source,doubleangle){    Point2fsrc\_center(source.cols/2.0F,source.rows/2.0F);    Matrot\_matgetRotationMatrix2D(src\_center,angle,1.0