2012-01-04 11 views
7

前回と同じ質問ですが、もっと詳しく説明します。 私は現在使用して画像を回転させています:Java Image Cut Off

int rotateNum //in main class 

double rotationRequired = Math.toRadians(rotateNum); 

    double locationX = img.getWidth(this)/2; 
    double locationY = img.getHeight(this)/2; 
    AffineTransform tx = AffineTransform.getRotateInstance(rotationRequired, locationX, locationY); 
    AffineTransformOp op = new AffineTransformOp(tx, AffineTransformOp.TYPE_BILINEAR); 


    g2d.drawImage(op.filter((BufferedImage)img, null), imgX, imgY, null); 

をそして私が実際に使用して画像を回転しています:

double deltaX = (double)(imgY - otherImg.imgY); 
double deltaY = (double)(imgX - otherImg.imgX); 
rotateNum = (int)(180 * Math.atan2(deltaY, deltaX)/Math.PI); 

私のイメージは、サイズが異なります。小さな画像は切り取られず(白いスペースで切り取られたことを意味します)、大きな画像は左右にあります。画像のサイズ変更がうまくいかず、 GIMPを使用して画像の周りに白い矩形を切り出しました。

例画像: (左の灰色の領域を無視する)前に

後:私はそれが画像の大きさではないことを想像 側

答えて

2

でカットオフを参照してください。問題はなくむしろその偏心:より正方形のような画像は、より太っているか薄い画像のどちらかに問題がありません。

あなたの問題は回転中心が[幅/ 2、高さ/ 2]であってはならないと思います。それほど単純ではありません。代わりに、大きな正方形の左上部分にある画像を考えると、正方形の辺の長さは画像の幅または高さのいずれか大きい方になります。画像を回転させるたびに回転します。

たとえば、ここに私の返事を参照してください。これは、javaは残念ながらありません何かがhttps://stackoverflow.com/a/8720123/522444

1

です。これを解決する1つの方法は、シェイプを正方形にすることです。回転するとクリッピングが発生しません。

この問題は、あなたが(それは少し古い場合であっても)任意のJavaゲームプログラミングをしたい場合は素晴らしい本であるDavidの「Javaでキラーゲームプログラミング」の本、books_google_killer+game+programming+clipping+rotatingで覆われています。

編集::この画像を正方形に変換することは、画像編集ソフトウェアを使用して生画像に行うことも、Java自体を通して行うこともできます。おそらく、そのような衝突をチェックすることができる独自の回転方法をロールバックします。

1

画像を回転すると画像のサイズに影響する場合があります。私は古いサンフォーラムで長年前に見つけたコードです(私は元のポスターを忘れています)。与えられた回転角度でイメージを表示するのに必要なサイズを再計算します。

import java.awt.*; 
import java.awt.geom.*; 
import java.awt.image.*; 
import java.io.*; 
import java.net.*; 
import javax.imageio.*; 
import javax.swing.*; 

public class RotateImage { 
    public static void main(String[] args) throws IOException { 
     URL url = new URL("https://blogs.oracle.com/jag/resource/JagHeadshot-small.jpg"); 
     BufferedImage original = ImageIO.read(url); 
     GraphicsConfiguration gc = getDefaultConfiguration(); 
     BufferedImage rotated1 = tilt(original, -Math.PI/2, gc); 
     BufferedImage rotated2 = tilt(original, +Math.PI/4, gc); 
     BufferedImage rotated3 = tilt(original, Math.PI, gc); 
     display(original, rotated1, rotated2, rotated3); 
    } 

    public static BufferedImage tilt(BufferedImage image, double angle, GraphicsConfiguration gc) { 
     double sin = Math.abs(Math.sin(angle)), cos = Math.abs(Math.cos(angle)); 
     int w = image.getWidth(), h = image.getHeight(); 
     int neww = (int)Math.floor(w*cos+h*sin), newh = (int)Math.floor(h*cos+w*sin); 
     int transparency = image.getColorModel().getTransparency(); 
     System.out.println(transparency); 
//  BufferedImage result = gc.createCompatibleImage(neww, newh, transparency); 
     BufferedImage result = gc.createCompatibleImage(neww, newh, Transparency.TRANSLUCENT); 
     Graphics2D g = result.createGraphics(); 
     g.translate((neww-w)/2, (newh-h)/2); 
     g.rotate(angle, w/2, h/2); 
     g.drawRenderedImage(image, null); 
     return result; 
    } 

    public static GraphicsConfiguration getDefaultConfiguration() { 
     GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); 
     GraphicsDevice gd = ge.getDefaultScreenDevice(); 
     return gd.getDefaultConfiguration(); 
    } 

    public static void display(BufferedImage im1, BufferedImage im2, BufferedImage im3, BufferedImage im4) { 
     JPanel cp = new JPanel(new GridLayout(2,2)); 
     addImage(cp, im1, "original"); 
     addImage(cp, im2, "rotate -PI/2"); 
     addImage(cp, im3, "rotate +PI/4"); 
     addImage(cp, im4, "rotate PI"); 

     JFrame f = new JFrame("RotateImage"); 
     f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     f.setContentPane(cp); 
     f.pack(); 
     f.setLocationRelativeTo(null); 
     f.setVisible(true); 
    } 

    static void addImage(Container cp, BufferedImage im, String title) { 
     JLabel lbl = new JLabel(new ImageIcon(im)); 
     lbl.setBorder(BorderFactory.createTitledBorder(title)); 
     cp.add(lbl); 
    } 
} 
3

ソースイメージが正確に2次ではありません。あなたはat.rotateでのAffineTransform回転を実装する場合(-rad、幅/ 2、高さ/ 2);,それは同じである:それは最後の行を実行したときにそう

at.translate(width/2,height/2); 
at.rotate(rads); 
at.translate(-width/2,-height/2); 

、それはに変換します原点。また、幅がyより大きい場合(またはその逆の場合)は、変換の原点が長さが長い側よりも小さい距離に変換されます。

たとえば、幅が30で高さが60の場合、原点は変換が元の位置から(-15、-30)に設定されます。つまり、90度のように平行移動すると、画像は「幅」60と「高さ」30になりますが、原点に応じて、画像の元の下端が(-30,0)に描画されますしたがって、X軸で-15のAffineTransformをオーバーフローさせます。その後、この部分の画像がカットされます。

これを修正するには、代わりに次のコードを使用することができます。

double degreesToRotate = 90; 
double locationX =bufferedImage.getWidth()/2; 
double locationY = bufferedImage.getHeight()/2; 

double diff = Math.abs(bufferedImage.getWidth() - bufferedImage.getHeight()); 

//To correct the set of origin point and the overflow 
double rotationRequired = Math.toRadians(degreesToRotate); 
double unitX = Math.abs(Math.cos(rotationRequired)); 
double unitY = Math.abs(Math.sin(rotationRequired)); 

double correctUx = unitX; 
double correctUy = unitY; 

//if the height is greater than the width, so you have to 'change' the axis to correct the overflow 
if(bufferedImage.getWidth() < bufferedImage.getHeight()){ 
    correctUx = unitY; 
    correctUy = unitX; 
} 

int posAffineTransformOpX = posX-(int)(locationX)-(int)(correctUx*diff); 
int posAffineTransformOpY = posY-(int)(locationY)-(int)(correctUy*diff); 

//translate the image center to same diff that dislocates the origin, to correct its point set 
AffineTransform objTrans = new AffineTransform(); 
objTrans.translate(correctUx*diff, correctUy*diff); 
objTrans.rotate(rotationRequired, locationX, locationY); 

AffineTransformOp op = new AffineTransformOp(objTrans, AffineTransformOp.TYPE_BILINEAR); 

// Drawing the rotated image at the required drawing locations 
graphic2dObj.drawImage(op.filter(bufferedImage, null), posAffineTransformOpX, posAffineTransformOpY, null); 

はそれが役立つ願っています。