2012-01-04 15 views
7

La stessa domanda dell'ultima volta, ma fornirò maggiori dettagli. Attualmente sto usando la rotazione delle immagini:Immagine Java interrotta

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

E poi io sono in realtà ruotare l'immagine utilizzando:

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

Le mie immagini sono di dimensioni variabili. Le immagini più piccole non vengono tagliate (cioè tagliate con lo spazio bianco), ma quelle più grandi, sul lato sinistro o destro. Il ridimensionamento delle immagini non funziona e ho ritagliato il rettangolo bianco attorno all'immagine utilizzando il GIMP .

Esempio Immagini: Prima (ignorare la zona grigia a sinistra)

Dopo: Vedere il cut-off sul lato

risposta

2

immagino che non è la dimensione dell'immagine che conta, ma piuttosto la sua eccentricità: le immagini più squadrate hanno meno problemi, quindi immagini più grasse o più sottili.

Penso che il tuo problema sia che il tuo centro di rotazione non dovrebbe essere [larghezza/2, altezza/2] - non è così semplice. Pensa invece all'immagine che risiede nella parte superiore sinistra di un grande quadrato la cui lunghezza sarà pari alla larghezza o altezza dell'immagine, a seconda di quale sia il più grande. Questo è ciò che viene ruotato ogni volta che si ruota l'immagine.

Per esempio, vedere la mia risposta qui: https://stackoverflow.com/a/8720123/522444

1

Questo è qualcosa che Java fa purtroppo. Un modo per risolverlo è quello di rendere la forma un quadrato, in modo che quando si ruota non si verifichi alcun taglio.

Questo problema è coperto in "Killer programmazione del gioco in Java" di David libro, books_google_killer+game+programming+clipping+rotating che è un grande librose si vuole fare alcuna programmazione java game (Anche se è un po 'vecchio).

Modifica :: Questa conversione di un'immagine in un quadrato può essere eseguita sull'immagine grezza tramite il software di modifica delle immagini o tramite java stesso. Forse rotolare il proprio metodo di rotazione che può verificare tali collisioni ..

1

La rotazione dell'immagine può anche influenzare la dimensione dell'immagine. Ecco un codice che ho trovato sui vecchi forum Sun molto tempo fa (ho dimenticato il poster originale). Si ricalcola la dimensione richiesta per visualizzare l'immagine al suo determinato angolo di rotazione:

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

Il problema è l'immagine fonte non è esattamente quadratica. Quando si implementa la rotazione AffineTransform con at.rotate (-RAD, larghezza/2, altezza/2) ;, è lo stesso di:

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

Così, quando si esegue l'ultima riga, si traduce alla origine. E se la larghezza è maggiore di y (o viceversa), l'origine della trasformazione sarà tradotta in una distanza minore rispetto al lato di maggiore lunghezza.

Ad esempio, se la larghezza è 30 e l'altezza è 60, il punto di origine verrà impostato come (-15, -30) da dove è stata impostata la trasformazione originale.Quindi, quando lo traduci, diciamo, a 90 gradi, l'immagine finirà con "larghezza" 60 e "altezza" 30, ma in base al punto di origine, l'immagine originale in basso verrà disegnata a (-30,0), quindi trabocca AffineTransform in -15 nell'asse X. Quindi questa parte dell'immagine verrà tagliata.

Per correggere questo, è possibile utilizzare il seguente codice invece:

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

Speranza che aiuta.

Problemi correlati