Как эффективно рендерить видео в Java (AWT ??) - PullRequest
2 голосов
/ 11 октября 2010

В моем проекте у меня есть класс FrameProducer событий срабатывания каждый раз, когда создается видеокадр.Каждый кадр - это изображение, возвращаемое как java.awt.Image.BufferedImage объект.

У меня есть 2 FrameProducer объектов, и я хотел бы визуализировать BufferedImage's, созданный ими одновременно на экране.Мне бы хотелось, чтобы изображение, отображаемое на экране, было масштабируемым (то есть, когда я перетаскиваю угол окна приложения, визуализированное видео становится меньше или больше).

Как вы думаете, этолучше всего достичь?

Я подумал об использовании java.awt.Graphics2D, встроенном в java.awt.Frame, но я не знаю, как это можно сделать, или это лучший выбор.Мне просто нужно это для визуализации алгоритма, это не должно быть красиво и блестяще, просто быстро и легко.Какие предложения или готовый код я бы мог использовать?


Редактировать: ОК, я реализовал решение так, как предлагал Рекин, и оно работает.Но так как я не эксперт по Java и определенно не эксперт по Swing , я хотел бы попросить вас сделать добрые замечания по моему коду - я уверен, что многие выиграют от этого в будущем.

Как я уже сказал, есть FrameProducer (не говоря уже о реализации):

public abstract class FrameProducer extends Observable {
    public abstract BufferedImage getFrame();

    public void fireEvent() {
        setChanged();
        notifyObservers();
    }
}

Затем также FrameRenderer ожидает события от FrameProducer (простойреализация шаблона наблюдателя с использованием java.util):

public class FrameRenderer extends JPanel implements Observer {
    private BufferedImage frame;
    @Override
    protected void paintComponent(Graphics g) {
        Graphics2D g2d = (Graphics2D) g;
        g2d.drawImage(frame, null, 0, 0);
        g2d.dispose();
    }
    @Override
    public void update(Observable observable, Object arg) {
        System.out.println("Cought an event from " + observable.getClass());
        if (observable instanceof FrameProducer) {
            frame = ((FrameProducer) observable).getFrame();
            paint(getGraphics());
        }
    }
}

И еще есть вещь, требующая доработки: MainFrame.

public class MainFrame extends JFrame {

    FrameProducer[] producers;

    public MainFrame(FrameProducer[] producers) {
        this.setTitle("Playing what you feed.");
        this.producers = producers;
        initContents();
        setVisible(true);
    }

    private void initContents() {
        FrameRenderer renderer = new FrameRenderer();
        renderer.setLocation(0, 0);
        this.add(renderer);
        producers[0].addObserver(renderer);
    }
}

Все это инициализируется вОсновной метод:

public class FrameAccessTest {
    public static void main(String[] args) {
        final FrameProducer frameGrabber = new CameraFrameGrabber("vfw://0");

        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    MainFrame mainFrame =
                        new MainFrame(new FrameProducer[] {frameGrabber});
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }
}

Как мне реализовать initContents () таким образом, чтобы все видеопотоки, представленные в конструкторе MainFrame's как FrameProducer[], отображались подряд и чтобы онимасштабируемы?

Ответы [ 2 ]

2 голосов
/ 11 октября 2010

Я бы пошел с JPanel и переопределил paintComponent метод.В нем я бы использовал Graphics2D.drawImage(), дающий ширину и высоту контейнера в качестве параметров для него.

Подход AWT кажется ближе к голому металлу, но, поскольку JDK 6 принес много улучшений в рендеринг Swing,Я бы пошел подход Swing & Java2D.Он ускоряется доступным оборудованием (используя DirectDraw в Windows или OpenGL, где это возможно) и скрывает множество низкоуровневых деталей за красивым API.Например, Вы получаете двойную буферизацию бесплатно.

0 голосов
/ 11 октября 2010

Переопределите метод paintComponent и используйте Graphics2D для рисования буферизованного изображения, используя drawImage.Этот метод перегружен и может быть использован для масштабирования изображения.

...