Java实现图片任意角度旋转

2019-05-08 17:56:04

Java普通方法实现图片旋转:

import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
 
import javax.imageio.ImageIO;
 
public class Test1 {
    public static void main(String[] args) throws IOException{
        Image image = ImageIO.read(new File("D:\\play\\2.bmp"));
        BufferedImage bi = Rotate(image,180);
        ImageIO.write(bi, "bmp", new File("D:\\play\\123.bmp"));
    }
    /**
     * 图像旋转
     * @param src
     * @param angel
     * @return
     */
    public static BufferedImage Rotate(Image src, double angel) {
        int src_width = src.getWidth(null);
        int src_height = src.getHeight(null);
        // calculate the new image size
        Rectangle rect_des = CalcRotatedSize(new Rectangle(new Dimension(
                src_width, src_height)), angel);
 
        BufferedImage res = null;
        res = new BufferedImage(rect_des.width, rect_des.height,
                BufferedImage.TYPE_3BYTE_BGR);
        Graphics2D g2 = res.createGraphics();
        // transform
        g2.translate((rect_des.width - src_width) / 2,
                (rect_des.height - src_height) / 2);
        g2.rotate(Math.toRadians(angel), src_width / 2, src_height / 2);
 
        g2.drawImage(src, null, null);
        g2.dispose();
        return res;
    }
 
    public static Rectangle CalcRotatedSize(Rectangle src, double angel) {
        // if angel is greater than 90 degree, we need to do some conversion
        if (angel >= 90) {
            if(angel / 90 % 2 == 1){
                int temp = src.height;
                src.height = src.width;
                src.width = temp;
            }
            angel = angel % 90;
        }
 
        double r = Math.sqrt(src.height * src.height + src.width * src.width) / 2;
        double len = 2 * Math.sin(Math.toRadians(angel) / 2) * r;
        double angel_alpha = (Math.PI - Math.toRadians(angel)) / 2;
        double angel_dalta_width = Math.atan((double) src.height / src.width);
        double angel_dalta_height = Math.atan((double) src.width / src.height);
 
        int len_dalta_width = (int) (len * Math.cos(Math.PI - angel_alpha
                - angel_dalta_width));
        len_dalta_width=len_dalta_width>0?len_dalta_width:-len_dalta_width;
 
        int len_dalta_height = (int) (len * Math.cos(Math.PI - angel_alpha
                - angel_dalta_height));
        len_dalta_height=len_dalta_height>0?len_dalta_height:-len_dalta_height;
 
        int des_width = src.width + len_dalta_width * 2;
        int des_height = src.height + len_dalta_height * 2;
        des_width=des_width>0?des_width:-des_width;
        des_height=des_height>0?des_height:-des_height;
        return new java.awt.Rectangle(new Dimension(des_width, des_height));
    }
}


opencv实现图片旋转:


  /**
     * opencv实现图片旋转
     * @param splitImage
     * @param angle
     * @return
     */
    public static Mat rotate3(Mat splitImage, double angle)
    {
        double thera = angle * Math.PI / 180;
        double a = Math.sin(thera);
        double b = Math.cos(thera);
 
        int wsrc = splitImage.width();
        int hsrc = splitImage.height();
 
        int wdst = (int) (hsrc * Math.abs(a) + wsrc * Math.abs(b));
        int hdst = (int) (wsrc * Math.abs(a) + hsrc * Math.abs(b));
        Mat imgDst = new Mat(hdst, wdst, splitImage.type());
 
        Point pt = new Point(splitImage.cols() / 2, splitImage.rows() / 2);
        // 获取仿射变换矩阵
        Mat affineTrans = Imgproc.getRotationMatrix2D(pt, angle, 1.0);
 
        System.out.println(affineTrans.dump());
        // 改变变换矩阵第三列的值
        affineTrans.put(0, 2, affineTrans.get(0, 2)[0] + (wdst - wsrc) / 2);
        affineTrans.put(1, 2, affineTrans.get(1, 2)[0] + (hdst - hsrc) / 2);
 
        Imgproc.warpAffine(splitImage, imgDst, affineTrans, imgDst.size(),
                Imgproc.INTER_CUBIC | Imgproc.WARP_FILL_OUTLIERS);
        return imgDst;
    }
  • 2019-08-28 08:49:47

    Nginx + fastcgi + php 的原理与关系

    CGI对每个请求会parse一遍对应脚本的配置文件(如php.ini), 加载配置和扩展,初始化执行环境,性能非常差,所有有了下面的流程:

  • 2019-08-28 09:23:15

    php单例模式

    单例模式,是一种常见的软件设计模式。在应用这个模式时,单例对象的类必须保证只有一个实例存在。

  • 2019-08-28 22:45:02

    彻底搞懂Gradle、Gradle Wrapper与Android Plugin for Gradle的区别和联系

    Gradle是个构建系统,能够简化你的编译、打包、测试过程。熟悉Java的同学,可以把Gradle类比成Maven。Gradle Wrapper的作用是简化Gradle本身的安装、部署。不同版本的项目可能需要不同版本的Gradle,手工部署的话比较麻烦,而且可能产生冲突,所以需要Gradle Wrapper帮你搞定这些事情。Gradle Wrapper是Gradle项目的一部分。

  • 2019-08-30 21:53:51

    OpenSSL实践-Android下的编译和使用

    openssl可以编译成ARM下面的二进制代码(动态库或者静态库),方便APP使用,APP在使用的时候,需要使用JNI来进行调用。

  • 2019-08-31 14:05:00

    JNI Crash:异常定位与捕获处理

    在Android JNI开发中,经常会遇到JNI崩溃的问题,尤其带代码量大,或者嵌入了第三方代码的情况下,很难进行问题定位和处理。本文将介绍两种常见的JNI崩溃处理方法,包括: 每个JNI调用后进行异常检测处理(适用于JNI代码量很小的情况) 捕获系统崩溃的Signal,并进行异常处理(适用于JNI代码量大,难以每句话后面都进行异常检测的情况)