2015-08-18 3 views
0

Я разрабатываю игру, и вращающиеся изображения в настоящее время занимают большую часть времени в процессе расчета кадра. Для оптимизации я ищу самый быстрый способ повернуть буферизованное изображение. Я уже пробовал два метода, показанных там.java rotating bufferedimages fast

медленный метод:

public static BufferedImage rotate(BufferedImage imgOld, int deg){            //Parameter for this method are the picture to rotate and the rotation in degrees 

    AffineTransform at = AffineTransform.getRotateInstance(Math.toRadians(deg), (int)(imgOld.getWidth()/2), (int)(imgOld.getHeight()/2));  //initialize and configure transformation 
    BufferedImage imgNew = new BufferedImage(imgOld.getWidth(), imgOld.getHeight(), imgOld.getType());           //create new bufferedimage with the properties of the image to rotate 
    Graphics2D g = (Graphics2D) imgNew.getGraphics();                       //create Graphics 
    g.setTransform(at);                               //apply transformation 
    g.drawImage(imgOld, 0, 0, null);                           //draw rotated image      
    g.dispose(); 
    imgOld.flush(); 
    return imgNew; 
} 

немного более быстрый способ:

public static BufferedImage rotate(BufferedImage imgOld, int deg){             //parameter same as method above                 

     BufferedImage imgNew = new BufferedImage(imgOld.getWidth(), imgOld.getHeight(), imgOld.getType());    //create new buffered image     
     Graphics2D g = (Graphics2D) imgNew.getGraphics();                //create new graphics 
     g.rotate(QaDMath.toRadians(deg), imgOld.getWidth()/2, imgOld.getHeight()/2);         //configure rotation 
     g.drawImage(imgOld, 0, 0, null);                    //draw rotated image 
     return imgNew;                         //return rotated image     
    }  

}

я нашел много тем, связанных с вращением изображения, но ни один обсуждать самый быстрый, решение. Надеюсь, я не пропустил ни одной темы, и это не дубликат.

Надеюсь, есть кто-то более опытный, чем я там зная Готовили раствор

+0

Вам нужно повернуть их во время выполнения? Не могли бы вы вместо этого сгенерировать повернутые изображения, которые вам нужны раньше времени, а затем просто использовать версию, которая повернула нужную сумму? –

+0

Я тоже думал об этом варианте, но боюсь, что несколько тысяч изображений слишком много для барана, используемого java –

ответ

1

Я бы предположил, что часть проблемы заключается в том, что вы постоянно создают новые BufferedImages сделать поворот. Это приводит к тому, что вы делаете живопись дважды, один раз, когда вы рисуете на BufferedImage, и во второй раз, когда вы рисуете BufferedImage в кадре.

Вы можете попытаться просто нарисовать существующий BufferedImage, повернутый. Например, вы могли бы использовать Rotated Icon, а затем просто нарисовать иконку с помощью

rotated.paintIcon(...); 

Всякий раз, когда вам нужно повернуть изображение, которое вы просто использовать:

rotated.setDegrees(...); 

Простой пример:

import java.awt.*; 
import java.awt.geom.AffineTransform; 
import java.awt.image.BufferedImage; 
import java.io.IOException; 
import javax.imageio.ImageIO; 
import javax.swing.*; 
import javax.swing.event.*; 

public class Rotation3 extends JPanel 
{ 
    private Icon icon; 
    private RotatedIcon rotated; 
    private int degrees; 

    public Rotation3(Image image) 
    { 
     icon = new ImageIcon(image); 
     rotated = new RotatedIcon(icon, 0); 
     rotated.setCircularIcon(true); 
     setDegrees(0); 
     setPreferredSize(new Dimension(600, 600)); 
    } 

    @Override 
    protected void paintComponent(Graphics g) 
    { 
     super.paintComponent(g); 

     double radians = Math.toRadians(degrees); 

     // translate x/y so Icon rotated around a specific point (300, 300) 

     int x = 300 - (rotated.getIconWidth()/2); 
     int y = 300 - (rotated.getIconHeight()/2); 
     rotated.paintIcon(this, g, x, y); 

     g.setColor(Color.RED); 
     g.fillOval(295, 295, 10, 10); 
    } 

    public void setDegrees(int degrees) 
    { 
     this.degrees = degrees; 
     rotated.setDegrees(degrees); 
     repaint(); 
    } 

    public static void main(String[] args) 
    { 
     EventQueue.invokeLater(new Runnable() 
     { 
      public void run() 
      { 
       try 
       { 
        String path = "dukewavered.gif"; 
        ClassLoader cl = Rotation3.class.getClassLoader(); 
        BufferedImage bi = ImageIO.read(cl.getResourceAsStream(path)); 
        final Rotation3 r = new Rotation3(bi); 

        final JSlider slider = new JSlider(JSlider.HORIZONTAL, 0, 360, 0); 
        slider.addChangeListener(new ChangeListener() 
        { 
         public void stateChanged(ChangeEvent e) 
         { 
          int value = slider.getValue(); 
          r.setDegrees(value); 
         } 
        }); 

        JFrame f = new JFrame(); 
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
        f.add(new JScrollPane(r)); 
        f.add(slider, BorderLayout.SOUTH); 
        f.pack(); 
        f.setLocationRelativeTo(null); 
        f.setVisible(true); 
       } 
       catch(IOException e) 
       { 
        System.out.println(e); 
       } 
      } 
     }); 
    } 
} 

Just перетащите ползунок, чтобы увидеть поворот.

+0

, кажется хорошей идеей, но у моего компилятора есть проблема с RotatedIcon. Вы тоже пишете этот класс или мне не хватает библиотеки? –

+0

@ManuelPrinz Я действительно не думаю, что вам нужно использовать 'RotatedIcon'. Увеличение производительности с использованием этого подхода происходит только от рисования изображения, повернутого на экран, вместо создания повернутой версии изображения (включая выделение памяти и т. Д.), А затем рисование повернутого изображения. – haraldK

+0

Я обязательно попробую это предложение, но для реализации его в течение всей игры потребуется несколько дней и тестирование частоты кадров, но я еще раз отвечу, как хорошо это работает. Спасибо за ваши советы. –