2012-01-04 13 views
7

Son kez aynı soruyla ama daha fazla ayrıntı vereceğim. Şu anda kullanarak görüntüleri dönen am: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); 

Sonra aslında kullanarak görüntüyü dönen am:

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

My görüntüleri boyutu değişebilir. Küçük görüntüler kesilmiyor (yani beyaz boşlukla kesiliyor) ama daha büyük olanları solda veya sağda. Resimlerin yeniden boyutlandırılması işe yaramıyor ve GIMP'yi kullanarak resmin etrafındaki beyaz dikdörtgenleri kırptım.

Örnek Görüntüler: sonra

(sola gri alanı görmezden) önce: Ben görüntünün boyutu değil hayal

cevap

2

tarafında cutoff bakın o meseleler değil, daha çok onun eksantrikliği: daha kareye benzeyen görüntüler, daha az problem ya da daha yağlı ya da daha zayıf olan görüntülere sahiptir.

Sorununuzun, döndürme merkezinizin [genişlik/2, yükseklik/2] olmaması gerektiği - bu kadar basit değil. Bunun yerine, büyük bir karenin sol üst kısmında yer alan görüntüyü düşünün, karenin uzunluğunun görüntüsü, resmin genişliği veya yüksekliğidir (hangisi daha büyükse). Görüntünüzü döndürdüğünüzde bu şekilde döndürülen şey budur.

Örneğin, burada benim cevap bakın: Bu java maalesef yaptığı bir şey https://stackoverflow.com/a/8720123/522444

1

olduğunu. Bunu çözmenin bir yolu şekli kare yapmaktır, böylece hiçbir kırpma gerçekleşmez.

Bu sorun (biraz eski olsa bile) herhangi bir java oyun programlama yapmak istiyorsanız bir harika kitap David'in "Java Katil oyun programlama" kitabında, books_google_killer+game+programming+clipping+rotating kaplıdır.

Düzenleme: Bir görüntünün bir kareye dönüştürülmesi, görüntü düzenleme yazılımı aracılığıyla veya java'nın kendisiyle ham görüntüye yapılabilir. Belki de bu tür çarpışmaları kontrol edebilen kendi döner yönteminizi kullanın.

1

Görüntüyü döndürmek, resmin boyutunu da etkileyebilir. İşte eski Sun forumlarında uzun zaman önce bulduğum bir kod (orijinal posteri unuttum).

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

Sorun kaynak resim tam olarak kuadratik değil mi: Bu dönme verilen açıda görüntüyü göstermek için gerekli boyutu yeniden hesaplar. son satır çalıştırmak zaman

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

, yani, bu şöyle açıklanabilir: Eğer at.rotate ile AffineTransform dönme uygulamak (genişlik -rad,/2, yükseklik/2) ;, o aynıdır Menşei. Ve eğer genişlik y'den büyükse (veya tersi), dönüşümün kaynağından daha büyük uzunluktan daha küçük bir mesafeye çevrilecektir.

Örneğin, genişliğiniz 30 ve boyunuz 60 ise, başlangıç ​​noktasından, dönüşümün orijinal ayarlandığı yerden (-15, -30) olarak ayarlanacaktır.Yani, çevirdiğinizde, 90 derece, görüntü "genişlik" 60 ve "yükseklik" 30 ile sona erecektir, ancak başlangıç ​​noktasına göre, görüntü orijinal alt (-30,0) 'de çizilecektir, Böylece, AffinTransformu -15'te X ekseninde taşar. Sonra görüntünün bu kısmı kesilecek.

Bunu düzeltmek için, bunun yerine aşağıdaki kodu kullanabilirsiniz:

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); 

faydası Umut.