2015-05-30 11 views
6

Ho provato a ridimensionare l'immagine tamponata con AffineTransform così come Scalr.resizedinamicamente ridimensionare un BufferedImage in Java

Qui sono i miei codici per entrambi.

utilizzando Scalr.resize:

BufferedImage buff = robot.createScreenCapture(new Rectangle(bufx,bufy,bufwidth,bufheight)); // x-coord, y-coord, width, height 

    BufferedImage scrCapt = Scalr.resize(buff, Method.BALANCED, scrwidth, scrheight); 

utilizzando AffineTransform:

BufferedImage buff = robot.createScreenCapture(new Rectangle(bufx,bufy,bufwidth,bufheight)); // x-coord, y-coord, width, height 

BufferedImage scrCapt = new BufferedImage(bufwidth,bufheight,BufferedImage.TYPE_INT_ARGB); 
AffineTransform atscr = new AffineTransform(); 


atscr.scale(aspectRatioWidth,aspectRatioHeight); 
AffineTransformOp scaleOp = new AffineTransformOp(atscr, AffineTransformOp.TYPE_BILINEAR); 
scrCapt = scaleOp.filter(buff, scrCapt); 

le variabili sono stati dichiarati in principio all'interno della classe:

static int bufx = 0; 
static int bufy = 0; 
static int bufwidth = 1; 
static int bufheight = 1; 
static int scrwidth = 0; 
static int scrheight = 0; 
static float aspectRatioWidth = 0; 
static float aspectRatioHeight = 0; 

sto ottenendo i valori per per tutte le variabili dinamicamente all'interno di un metodo diverso:

aspectRatioWidth = bufwidth/scrwidth; 
aspectRatioHeight = bufheight/scrheight; 

Tuttavia quando si esegue questo codice ottengo un errore in entrambe le funzioni AffineTransform nonché Scalr.resize:

Scalr.resize:

Exception in thread "Thread-2" java.lang.IllegalArgumentException: Width (0) and height (0) cannot be <= 0 
at java.awt.image.DirectColorModel.createCompatibleWritableRaster(DirectColorModel.java:1016) 
at java.awt.image.BufferedImage.<init>(BufferedImage.java:331) 
at org.imgscalr.Scalr.createOptimalImage(Scalr.java:2006) 
at org.imgscalr.Scalr.scaleImage(Scalr.java:2133) 
at org.imgscalr.Scalr.resize(Scalr.java:1667) 
at org.imgscalr.Scalr.resize(Scalr.java:1415) 

AffineTransform:

Exception in thread "Thread-2" java.awt.image.ImagingOpException: Unable to invert transform AffineTransform[[0.0, 0.0, 0.0], [0.0, 1.0, 0.0]] 
at java.awt.image.AffineTransformOp.validateTransform(AffineTransformOp.java:558) 
at java.awt.image.AffineTransformOp.<init>(AffineTransformOp.java:151) 

Come faccio a fare questo? Capisco che questo sta accadendo perché sto cambiando la variabile in un metodo diverso e accedendoli in un altro. Ma questi due metodi non possono essere combinati. C'è un modo per farlo funzionare?

EDIT:

ho cambiato il metodo di ridimensionamento Ecco quello che ho fatto oggi

public static BufferedImage resizeImage(BufferedImage image, double scalewidth, double scaleheight){ 

    BufferedImage img = new BufferedImage(image.getWidth(), image.getHeight(),BufferedImage.SCALE_FAST); 
    Graphics2D g = img.createGraphics(); 
    g.scale(scalewidth, scaleheight); 
    g.drawImage(image, null, 0, 0); 
    g.dispose(); 
    return image; 
} 

EDIT (2):

Per un'idea più chiara di ciò che sta accadendo esattamente:

Questo è un metodo che ri gira scrwidth e scrheight

public static void showOnScreen(int screen, JFrame framenew) 
    { 
    GraphicsEnvironment ge = GraphicsEnvironment 
     .getLocalGraphicsEnvironment(); 
    GraphicsDevice[] gs = ge.getScreenDevices(); 

    for (int i = 0; i < gs.length; i++) { 
     screenwidth.add(gs[i].getDisplayMode().getWidth()); 
     screenheight.add(gs[i].getDisplayMode().getHeight()); 
} 

scrwidth = screenwidth.get(screenwidth.size()-1); 
scrheight = screenheight.get(screenheight.size()-1); 




    System.out.print(ge); 
    System.out.print(gs); 
    if(screen > -1 && screen < gs.length) 
    {gs[screen].setFullScreenWindow(framenew);} 
    else if(gs.length > 0) 
    {gs[0].setFullScreenWindow(framenew);} 
    else 
    {throw new RuntimeException("No Screens Found");}} 

E questo è l'ActionListener che restituisce bufwidth e bufheight:

btnNewButton.addActionListener(new ActionListener() {  
    public void actionPerformed(ActionEvent e) 
    { 
     //Execute when button is pressed 
     System.out.println("You clicked the button"); 

     int ind = c.getSelectedIndex(); 
     bufx = capx.get(ind); 
     bufy = capy.get(ind); 
     bufwidth = capwidth.get(ind); 
     bufheight = capheight.get(ind); 
     frame.setVisible(false); 
     framenew.setVisible(true); 
     showOnScreen(1,framenew); 

     aspectRatioWidth = (double) bufwidth/scrwidth; 
     aspectRatioHeight = (double) bufheight/scrheight; 

      System.out.print("aspectRatioWidth: "); 
      System.out.println(aspectRatioWidth); 

      System.out.print("aspectRatioHeight: "); 
      System.out.println(aspectRatioHeight);   
    } 
    });  

E aspectRatios vengono utilizzati all'interno run:

public void run() { 
System.out.print("aspectRatioWidth: "); 
System.out.println(aspectRatioWidth); 

System.out.print("aspectRatioHeight: "); 
System.out.println(aspectRatioHeight); 

while(true){ 
    BufferedImage buff = robot.createScreenCapture(new Rectangle(bufx,bufy,bufwidth,bufheight)); // x-coord, y-coord, width, height 

    BufferedImage resizedbuff = resizeImage(buff, aspectRatioWidth, aspectRatioHeight);} 
+0

Quindi, ... Hai fatto alcuni cambiamenti (hai fatto la cambiamento che ho raccomandato?) - cosa hanno fatto i tuoi cambiamenti? Il tuo codice ora funziona? Stai ancora vedendo un'eccezione? –

+0

sì Ho convertito i numeri in doppio. Si tratta di dare il giusto valore quando eseguo la divisione metodo all'interno, che sta tornando bufwidth, bufheight e tutte le variabili Tuttavia sta tornando a zero quando stampo fuori aspectRatioWidth e aspectRatioHeight all'interno run() posso capire che questo sta accadendo perché quando viene eseguito run(), i valori di tutte le variabili non sono stati ancora incrementati Come faccio a essere sicuri che run() si verifichi solo dopo che i valori sono stati incrementati? – newbie2015

risposta

4

Stai facendo divisione int che restituisce sempre un int, qui 0 poiché le dimensioni dello schermo saranno probabilmente maggiori delle dimensioni dell'immagine:

aspectRatioWidth = bufwidth/scrwidth; 
aspectRatioHeight = bufheight/scrheight; 

Soluzione: convertire i numeri in doppio e quindi fare doppia divisione.

aspectRatioWidth = (double) bufwidth/scrwidth; 
aspectRatioHeight = (double) bufheight/scrheight; 

Modifica

Non sei sicuro di quello che stai cercando di fare in ultima analisi - inviare l'immagine dello schermo del computer nella vostra interfaccia grafica? Se è così, forse qualcosa di simile ...

import java.awt.AWTException; 
import java.awt.Dimension; 
import java.awt.Graphics; 
import java.awt.Rectangle; 
import java.awt.Robot; 
import java.awt.Toolkit; 
import java.awt.event.WindowAdapter; 
import java.awt.event.WindowEvent; 
import java.awt.geom.AffineTransform; 
import java.awt.image.AffineTransformOp; 
import java.awt.image.BufferedImage; 
import java.util.List; 

import javax.swing.*; 

public class ChangeVars extends JPanel { 
    private static final int PREF_W = 400; 
    private static final int PREF_H = PREF_W; 
    private static final int DELAY = 20; 
    public BufferedImage displayImage; 
    private MyWorker myWorker; 

    public ChangeVars() { 
     try { 
     myWorker = new MyWorker(DELAY); 
     myWorker.execute(); 
     } catch (AWTException e) { 
     e.printStackTrace(); 
     } 
    } 

    @Override 
    // to initialize the panel to something 
    public Dimension getPreferredSize() { 
     if (isPreferredSizeSet()) { 
     return super.getPreferredSize(); 
     } 
     return new Dimension(PREF_W, PREF_H); 
    } 

    @Override 
    protected void paintComponent(Graphics g) { 
     super.paintComponent(g); 
     if (displayImage != null) { 
     g.drawImage(displayImage, 0, 0, null); 
     } 
    } 

    public void stopWorker() { 
     if (myWorker != null && !myWorker.isDone()) { 
     myWorker.setRunning(false); 
     myWorker.cancel(true); 
     } 
    } 

    private class MyWorker extends SwingWorker<Void, BufferedImage> { 

     private volatile boolean running = true; 
     private Robot robot; 
     private int delay; 

     public MyWorker(int delay) throws AWTException { 
     this.delay = delay; 
     robot = new Robot(); 
     } 

     @Override 
     protected Void doInBackground() throws Exception { 
     while (running) { 
      Dimension d = Toolkit.getDefaultToolkit().getScreenSize(); 
      Rectangle screenRect = new Rectangle(0, 0, d.width, d.height); 
      BufferedImage img = robot.createScreenCapture(screenRect); 
      publish(img); 
      Thread.sleep(delay); 
     } 
     return null; 
     } 

     @Override 
     protected void process(List<BufferedImage> chunks) { 
     for (BufferedImage image : chunks) { 
      Dimension sz = getSize(); 
      double scaleX = (double) sz.width/image.getWidth(); 
      double scaleY = (double) sz.height/image.getHeight(); 
      AffineTransform transform = AffineTransform.getScaleInstance(
        scaleX, scaleY); 
      AffineTransformOp transformOp = new AffineTransformOp(transform, 
        AffineTransformOp.TYPE_BILINEAR); 
      displayImage = new BufferedImage(sz.width, sz.height, 
        BufferedImage.TYPE_INT_ARGB); 
      displayImage = transformOp.filter(image, displayImage); 
      repaint(); 
     } 
     } 

     public void setRunning(boolean running) { 
     this.running = running; 
     } 

     public boolean getRunning() { 
     return running; 
     } 

    } 

    private static void createAndShowGui() { 
     final ChangeVars changeVars = new ChangeVars(); 

     JFrame frame = new JFrame("ChangeVars"); 
     frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); 
     frame.addWindowListener(new WindowAdapter() { 

     @Override 
     public void windowClosing(WindowEvent e) { 
      if (changeVars != null) { 
       changeVars.stopWorker(); 
      } 
      System.exit(0); 
     } 

     }); 
     frame.getContentPane().add(changeVars); 
     frame.pack(); 
     frame.setLocationByPlatform(true); 
     frame.setVisible(true); 
    } 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 
     public void run() { 
      createAndShowGui(); 
     } 
     }); 
    } 
} 

Anche se più semplice sarebbe quella di lasciare che paintComponent fare la scala:

@Override 
protected void paintComponent(Graphics g) { 
    super.paintComponent(g); 
    if (displayImage != null) { 
    int width = getWidth(); 
    int height = getHeight(); 
    g.drawImage(displayImage, 0, 0, width, height, null); 
    } 
} 

// .... 

    @Override 
    protected void process(List<BufferedImage> chunks) { 
    for (BufferedImage image : chunks) { 
     displayImage = image; 
     repaint(); 
    } 
    } 
+0

Sto usando un metodo diverso per implementare il ridimensionamento dell'immagine Funziona benissimo tranne che ora ho capito che c'è un altro problema Le due variabili vengono cambiate in una diversa funzione mentre le sto accedendo all'interno di run() Quindi quando aspectRatioWidth e aspectRatioHeight ritornano sempre uno zero perché bufwidth e bufheight sono stati inizializzati a zero C'è un modo in cui posso assicurarmi che le altre funzioni siano implementate prima di eseguire() – newbie2015

+0

@ newbie2015: così ora stai cambiando i requisiti su di noi. In futuro, per favore cerca di evitare questo, perché questo può essere frustrante per noi e può invalidare le risposte esistenti. Per quanto riguarda il tuo problema, se ora stai riscontrando un nuovo problema, modifica la tua domanda e chiarisci il problema il più possibile. Non sono sicuro di poter comprendere appieno ciò che è sbagliato in base al blurb che hai postato sopra. Ad esempio, non ho modo di sapere come sono correlate le variabili. –

+0

@ newbie2015: prendere in considerazione la creazione e la pubblicazione di un [programma di esempio minimo, completo e verificabile] (http://stackoverflow.com/help/mcve) dove si condensa il codice nel bit più piccolo che ancora compila e viene eseguito, non ha all'esterno le dipendenze (come la necessità di collegarsi a un database o immagini), non hanno codice aggiuntivo che non è rilevante per il tuo problema, ma dimostra ancora il tuo problema. Come problema collaterale, il tuo codice attuale sembra essere sovrautilizzo di campi statici, qualcosa che in generale dovrebbe essere evitato. –

Problemi correlati