黑区使用java 2D图形旋转?

时间:2013-11-18 11:18:15

标签: java swing lwjgl bufferedimage graphics2d

我将首先展示出错的例子,然后我将解释如何,最后我会问我的问题。

这是我想要旋转的图片。

Just and example picture for stackoverflow

我将它旋转90度和270度,然后将它们组合成一个大的缓冲图像。

我用来旋转单个bufferedImage的代码是这样的:

public static BufferedImage rotate(BufferedImage img, int angle) {  
    int w = img.getWidth();  
    int h = img.getHeight();  

    BufferedImage dimg = new BufferedImage(w, h, img.getType());

    Graphics2D g = dimg.createGraphics();
    g.rotate(Math.toRadians(angle), w/2, h/2);  
    g.drawImage(img, null, 0, 0);  
    return dimg;  
}

旋转的出现看起来像这样。

Rotation with native width and height

这些黑条的原因是因为在代码中您可以清楚地看到我创建了一个单独的缓冲图像,它将成为最终图像。

它使用原始宽度和高度,因为图像旋转了with和height开关所以我通过将BufferedImage dimg = new BufferedImage(w, h, img.getType());更改为BufferedImage dimg = new BufferedImage(h, w, img.getType());来补偿这一点。

我认为这可以解决我的问题,这是合乎逻辑的 但我现在错了,旋转结果是这样的。

rotation with with and height switch 所以从这一点开始,我不知道为什么会这样做。
我可能只是俯视一个小东西,或者这是一个常见的错误,即使我找不到任何这种情况发生的事实。

所以这是我的问题,为什么这样做?我该如何解决这个问题。

3 个答案:

答案 0 :(得分:2)

图像不是正方形。如果将其旋转90°,则会产生需要填充的间隙。

解决方案:

  • 确保图像为方形
  • “旋转”大小:旋转90°或270°时,需要创建一个交换宽度和高度的目标图像(即200x100 - > 100x200)
  • 裁剪图像。在你的情况下很好,因为缩放将使箭头看起来很糟糕,但它可能不在中心
  • 缩放图像。如果它是609x579,则将其缩小到579x579(缩小比例看起来会更好一些)。
  • 找到边框颜色并在旋转后用边框颜色填充间隙

答案 1 :(得分:1)

我明白了。

我在开始时做的事情是旋转主图像(dimg),
然后将原始图像绘制到它 我也可以尝试在一个圆圈中放置一个正方形我的早期旋转实际上根本没有任何意义。

所以我需要做的是先创建主机,将图像绘制到主机,旋转主机并将其作为最终图像返回。

public static BufferedImage rotate(BufferedImage img, int angle) {  
    int w = img.getWidth();  
    int h = img.getHeight();  

    BufferedImage dimg = new BufferedImage(w, h, img.getType());

    Graphics2D g = dimg.createGraphics();
    g.drawImage(img, null, 0, 0); //Draw before rotating
    g.rotate(Math.toRadians(angle), w/2, h/2); //Rotating after drawing
    return dimg;  
}

我希望这也有助于其他人

答案 2 :(得分:1)

如果你想使用类似的代码作为第一个代码 这可能会有所帮助(如果删除注释和调试行(例如绘制背景),它只有translate((W-w)/ 2,(H-h)/ 2)行)

// do not forget to import static java.lang.Math.*
public static BufferedImage rotate(BufferedImage img, int angle) {  
    int w = img.getWidth(null);  
    int h = img.getHeight(null);  
    double rad = toRadians(angle);
    double eps = 1e-3;
    int W=(int)(abs(cos(rad))*w+abs(sin(rad))*h-eps)+1;//W after rotation(calculated by using a little geometry ) 
    int H=(int)(abs(sin(rad))*w+abs(cos(rad))*h-eps)+1;//H after rotation
    //you may use max value ( diameter of the rectangle ) instead of dynamic value but in that case you must be careful of the black edges ( in this case red edges ) 
    // if 90 is not a divisor of angle then you can't fit a rectangle with that angle in another one so the red edges are inevitable 
    // but with calculated W and H this edges are minimum 

    BufferedImage dimg = new BufferedImage(W,H, BufferedImage.TYPE_INT_RGB);// you can change it to any type you want it's just a sample 
    Graphics2D g = dimg.createGraphics();
    g.setColor(Color.RED); // background color of red for displaying the red edges when image is not completely fit 
    g.fillRect(0, 0, W, H);
    int x=(W-w)/2;   
    int y=(H-h)/2;  
    g.translate(x, y); // moving dimg center to img center ( this was what first code lack in  ) 
    g.rotate(-rad, w/2, h/2);  // now rotating dimg around the center of img ( which is now same as center of dimg )
    // we rotate dimg by -rad and draw img normally , it's like rotating img by rad instead of dimg by -rad
    g.drawImage(img,null,0,0);  // and drawing
    return dimg;  
}