Java实现图片内容无损任意角度旋转

转自:http://blog.csdn.net/heliang7/article/details/7309394

主要问题是如何在图片做旋转后计算出新图片的长宽。

在java 2d和基本math库的帮助下,其实利用简单的计算就可以知道。

以下算法只是计算出旋转小于90度时的公式。当旋转大于90时,可以先把问题域换算到锐角的情况,再进行计算即可。

如下图所示,需要计算出来的是len_delta的长度,就是有双竖线的位置,它是新图片要增加的宽。(要增加的高度同理可得。)

其实只要知道len的长度,还有len和len_delta的夹角,就可以算出len_delta的长度了。

1. len的长度。注意到它是等腰三角形的底边,顶角为angel, 容易得到len=2*R*sin(angel/2)

2. len和len_delta的夹角。先可以计算出angel_alpha,也就是等腰三角形的底角 angel_alpha = (PI - angel) / 2

然后是R和原图像的底边的夹角angel_delta,显然其tan值是原图片的高宽比(注意计算增加的高度时是宽高比)。用arctan求出其角度。

len和len_delta的夹角 = PI - angel_alpha - angel_delta

3. len_delta = len * cos(len和len_delta的夹角)

java代码示例如下

[java] view plaincopy

    1. <pre name="code" class="java">import java.awt.Dimension;
    2. import java.awt.Graphics2D;
    3. import java.awt.Image;
    4. import java.awt.Rectangle;
    5. import java.awt.image.BufferedImage;
    6. public class RotateImage {
    7. public static BufferedImage Rotate(Image src, int angel) {
    8. int src_width = src.getWidth(null);
    9. int src_height = src.getHeight(null);
    10. // calculate the new image size
    11. Rectangle rect_des = CalcRotatedSize(new Rectangle(new Dimension(
    12. src_width, src_height)), angel);
    13. BufferedImage res = null;
    14. res = new BufferedImage(rect_des.width, rect_des.height,
    15. BufferedImage.TYPE_INT_RGB);
    16. Graphics2D g2 = res.createGraphics();
    17. // transform
    18. g2.translate((rect_des.width - src_width) / 2,
    19. (rect_des.height - src_height) / 2);
    20. g2.rotate(Math.toRadians(angel), src_width / 2, src_height / 2);
    21. g2.drawImage(src, null, null);
    22. return res;
    23. }
    24. public static Rectangle CalcRotatedSize(Rectangle src, int angel) {
    25. // if angel is greater than 90 degree, we need to do some conversion
    26. if (angel >= 90) {
    27. if(angel / 90 % 2 == 1){
    28. int temp = src.height;
    29. src.height = src.width;
    30. src.width = temp;
    31. }
    32. angel = angel % 90;
    33. }
    34. double r = Math.sqrt(src.height * src.height + src.width * src.width) / 2;
    35. double len = 2 * Math.sin(Math.toRadians(angel) / 2) * r;
    36. double angel_alpha = (Math.PI - Math.toRadians(angel)) / 2;
    37. double angel_dalta_width = Math.atan((double) src.height / src.width);
    38. double angel_dalta_height = Math.atan((double) src.width / src.height);
    39. int len_dalta_width = (int) (len * Math.cos(Math.PI - angel_alpha
    40. - angel_dalta_width));
    41. int len_dalta_height = (int) (len * Math.cos(Math.PI - angel_alpha
    42. - angel_dalta_height));
    43. int des_width = src.width + len_dalta_width * 2;
    44. int des_height = src.height + len_dalta_height * 2;
    45. return new java.awt.Rectangle(new Dimension(des_width, des_height));
    46. }
    47. }</pre><br>
    48. <pre></pre>
    49. <p>JUnit测试代码如下,将图片路径改为你自己准备测试用的图片路径即可。</p>
    50. <p></p>
    51. <pre name="code" class="java"><pre name="code" class="java">import java.awt.image.BufferedImage;
    52. import java.io.File;
    53. import java.io.IOException;
    54. import javax.imageio.ImageIO;
    55. import junit.framework.Assert;
    56. import org.junit.Test;
    57. import Jugnoo.RotateImage;
    58. public class RotateImageTest {
    59. @Test
    60. public void testRotate() throws IOException {
    61. BufferedImage src = ImageIO.read(new File("d:/dog.jpg"));
    62. BufferedImage des = RotateImage.Rotate(src, 30);
    63. Assert.assertNotNull(des);
    64. Assert.assertTrue(ImageIO.write(des, "jpg", new File("d:/dog2.jpg")));
    65. // bigger angel
    66. des = RotateImage.Rotate(src, 150);
    67. Assert.assertNotNull(des);
    68. Assert.assertTrue(ImageIO.write(des, "jpg", new File("d:/dog3.jpg")));
    69. // bigger angel
    70. des = RotateImage.Rotate(src, 270);
    71. Assert.assertNotNull(des);
    72. Assert.assertTrue(ImageIO.write(des, "jpg", new File("d:/dog4.jpg")));
    73. }
    74. }</pre><br>
    75. <br>
    76. <pre></pre>
    77. <p></p>
    78. <pre></pre>
    79. <pre></pre>
时间: 2025-01-08 07:54:55

Java实现图片内容无损任意角度旋转的相关文章

基于VB的hough变换和任意角度旋转

Public Sub DoRotate(Optional ByVal RotaryAngle As Long = 0) '任意角度旋转 Dim sDIB As New cDIB Dim sBits() As RGBQUAD Dim dBits() As RGBQUAD Dim stSA As SAFEARRAY2D Dim dtSA As SAFEARRAY2D Dim Lev As Long Dim Wgt As Long Dim x As Long Dim y As Long Dim new

Winform以任意角度旋转PictureBox中的图片的方法

方法1: private void RotateFormCenter(PictureBox pb, float angle) { Image img = pb.Image; int newWidth = Math.Max(img.Height, img.Width); Bitmap bmp = new Bitmap(newWidth, newWidth); Graphics g = Graphics.FromImage(bmp); Matrix x = new Matrix(); PointF

unity 鼠标拖拽物体实现任意角度自旋转

主要涉及函数 Input.GetAxis(“Mouse x”) 可取得鼠标横向(x轴)移动增量 Input.GetAxis(“Mouse y”) 可取得鼠标竖向(y轴)移动增量 通过勾股定理获取拖拽长度,长度越长旋转越快 在project setting--Input 可以设置 直接上代码,看了就明白了 1 using UnityEngine; 2 using System.Collections; 3 4 public class startRoate : MonoBehaviour 5 {

JQuery插件让图片旋转任意角度且代码极其简单

引入下方的jquery.rotate.js文件,然后通过$("选择器").rotate(角度);可以旋转任意角度, 例如$("#rotate-image").rotate(45);把这句放在$(document).ready(function(){ });中 就是将id为rotate-image的图片旋转45度. 不过,貌似在Chrome中总是不显示. 唉,找了两个小时,才发现Chrome太坑爹了,没法获取图片的长宽. 解决办法是,把$("#rotate-

矩阵变换:沿任意轴旋转及其推导

http://blog.csdn.net/zsq306650083/article/details/8773996 1. 2D中绕原点旋转 设基向量p,q和r分别是朝向+x,+y和+z方向的单位向量. 旋转角度为θ,基向量p,q绕原点旋转,得到新的基向量p`和q` 即旋转矩阵R(θ)为 2. 3d中绕坐标轴旋转 01. 绕x轴旋转,基向量q和r旋转θ,得到新的基向量q`和r` 即旋转矩阵Rx(θ)为: 02. 绕y轴旋转,基向量p和r旋转θ,得到新的基向量p`和r` 即旋转矩阵Ry(θ)为: 0

任意角度的场景文本检测论文简单总结

任意角度的场景文本检测 论文思路总结特点:重新添加分支的创新更突出场景文本检测 基于分割的检测方法 spcnet(mask_rcnn+tcm+rescore) psenet(渐进扩展) mask text spottor(新加分割分支) craft incepText 基于回归的检测方法: r2cnn(类别分支,水平分支,倾斜分支) rrpn(旋转rpn) textbox(ssd) textbox++ sstd(tcm改进前身) rtn ctpn(微分) 基于分割和回归的混合方法: spcnet

Java使用JDBC连接任意类型数据库(mysql oracle。。)

package cn.liz.test; import java.io.InputStream; import java.sql.Connection; import java.sql.Driver; import java.sql.SQLException; import java.util.Properties; import org.junit.Test; public class JBDCtest { /** * 编写一个通用的方法, 在不修改源程序的情况下, 可以获取任何数据库的连接

绕任意轴旋转的矩阵推导总结

前言 常用的几何变换中旋转是较为复杂的一种,最近看<Physically Based Rendering, Second Edition: From Theory To Implementation>一书涉及绕任意轴旋转的实现,也给出了大体思路,但具体的推导过程及最后的旋转矩阵并未直接地给出,故根据参考Animated CGEM: Rotation About an Arbitrary Axis总结(欢迎指正). (一)基础 1.点乘与叉乘 点乘(dot)亦称作内积或数量积,如图,a·b =

java中并不是任意多个接口都可以实现多实现

interface A{ public abstract void show(); } interface B{ public abstract int show(); } public class Test implements A, B{ public void show(){ System.out.println("A show!"); } /* 只写 void show()出现的问题: Test不是抽象的, 并且未覆盖B中的抽象方法show(); */ public int s