Package com.googlecode.javacv

Source Code of com.googlecode.javacv.MovedListener

/*
* Copyright (C) 2009,2010,2011 Samuel Audet
*
* This file is part of JavaCV.
*
* JavaCV is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version (subject to the "Classpath" exception
* as provided in the LICENSE.txt file that accompanied this code).
*
* JavaCV is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with JavaCV.  If not, see <http://www.gnu.org/licenses/>.
*/

package com.googlecode.javacv;

import java.awt.Canvas;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.DisplayMode;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Image;
import java.awt.KeyEventDispatcher;
import java.awt.KeyboardFocusManager;
import java.awt.color.ColorSpace;
import java.awt.color.ICC_ColorSpace;
import java.awt.color.ICC_ProfileRGB;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.KeyEvent;
import java.awt.image.BufferStrategy;
import java.awt.image.BufferedImage;
import javax.swing.JFrame;
import javax.swing.JRootPane;

import static com.googlecode.javacv.cpp.opencv_core.*;

/**
*
* @author Samuel Audet
*
* Make sure OpenGL is enabled to get low latency, something like
*      export _JAVA_OPTIONS=-Dsun.java2d.opengl=True
*
*/
public class CanvasFrame extends JFrame {
    public static String[] getScreenDescriptions() {
        GraphicsDevice[] screens = getScreenDevices();
        String[] descriptions = new String[screens.length];
        for (int i = 0; i < screens.length; i++) {
            descriptions[i] = screens[i].getIDstring();
        }
        return descriptions;
    }
    public static DisplayMode getDisplayMode(int screenNumber) {
        GraphicsDevice[] screens = getScreenDevices();
        if (screenNumber >= 0 && screenNumber < screens.length) {
            return screens[screenNumber].getDisplayMode();
        } else {
            return null;
        }
    }
    public static double getGamma(int screenNumber) {
        GraphicsDevice[] screens = getScreenDevices();
        if (screenNumber >= 0 && screenNumber < screens.length) {
            return getGamma(screens[screenNumber]);
        } else {
            return 0.0;
        }
    }

    public static double getGamma(GraphicsDevice screen) {
        ColorSpace cs = screen.getDefaultConfiguration().getColorModel().getColorSpace();
        if (cs.isCS_sRGB()) {
            return 2.2;
        } else {
            try {
                return ((ICC_ProfileRGB)((ICC_ColorSpace)cs).getProfile()).getGamma(0);
            } catch (Exception e) { }
        }
        return 0.0;
    }
    public static GraphicsDevice getScreenDevice(int screenNumber) throws Exception {
        GraphicsDevice[] screens = getScreenDevices();
        if (screenNumber >= screens.length) {
            throw new Exception("CanvasFrame Error: Screen number " + screenNumber + " not found. " +
                                "There are only " + screens.length + " screens.");
        }
        return screens[screenNumber];//.getDefaultConfiguration();
    }
    public static GraphicsDevice[] getScreenDevices() {
        return GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices();
    }

    public CanvasFrame(String title) {
        this(title, 0.0);
    }
    public CanvasFrame(String title, double gamma) {
        super(title);
        init(false, null, gamma);
    }

    public CanvasFrame(String title, GraphicsConfiguration gc) {
        this(title, gc, 0.0);
    }
    public CanvasFrame(String title, GraphicsConfiguration gc, double gamma) {
        super(title, gc);
        init(false, null, gamma);
    }

    public CanvasFrame(String title, int screenNumber, DisplayMode displayMode) throws Exception {
        this(title, screenNumber, displayMode, 0.0);
    }
    public CanvasFrame(String title, int screenNumber, DisplayMode displayMode, double gamma) throws Exception {
        super(title, getScreenDevice(screenNumber).getDefaultConfiguration());
        init(true, displayMode, gamma);
    }

    @Override public void dispose() {
        bufferStrategy.dispose();
        super.dispose();
    }
    private void init(final boolean fullScreen, final DisplayMode displayMode, final double gamma) {
        Runnable r = new Runnable() { public void run() {
            GraphicsDevice gd = getGraphicsConfiguration().getDevice();
            DisplayMode d = gd.getDisplayMode(), d2 = null;
            if (displayMode != null && d != null) {
                int w = displayMode.getWidth();
                int h = displayMode.getHeight();
                int b = displayMode.getBitDepth();
                int r = displayMode.getRefreshRate();
                d2 = new DisplayMode(w > 0 ? w : d.getWidth(),    h > 0 ? h : d.getHeight(),
                                     b > 0 ? b : d.getBitDepth(), r > 0 ? r : d.getRefreshRate());
            }
            if (fullScreen) {
                setUndecorated(true);
                getRootPane().setWindowDecorationStyle(JRootPane.NONE);
                setResizable(false);
                gd.setFullScreenWindow(CanvasFrame.this);
            }
            if (d2 != null && !d2.equals(d)) {
                gd.setDisplayMode(d2);
            }
            double g = gamma == 0.0 ? getGamma(gd) : gamma;
            invgamma = g == 0.0 ? 1.0 : 1.0/g;

            // must be called after the fullscreen stuff, but before
            // getting our BufferStrategy
            setVisible(true);

            canvas = new Canvas() {
                @Override public void paint(Graphics g) {
                    // Try to redraw the front buffer when the OS says it has stomped
                    // on it, using the back buffer. Calling bufferStrategy.show() here
                    // sometimes throws NullPointerException or IllegalStateException,
                    // but otherwise seems to work fine.
                    try {
                        bufferStrategy.show();
                    } catch (NullPointerException e) {
                    } catch (IllegalStateException e) { }
                }
            };
            if (fullScreen) {
                canvas.setSize(getSize());
                needInitialResize = false;
            } else {
                needInitialResize = true;
            }
            getContentPane().add(canvas);
            canvas.setVisible(true);
            canvas.createBufferStrategy(2);
            //canvas.setIgnoreRepaint(true);
            bufferStrategy = canvas.getBufferStrategy();

            KeyboardFocusManager.getCurrentKeyboardFocusManager().
                    addKeyEventDispatcher(new KeyEventDispatcher() {
                public boolean dispatchKeyEvent(KeyEvent e) {
                    if (e.getID() == KeyEvent.KEY_PRESSED) {
                        synchronized (CanvasFrame.this) {
                            keyEvent = e;
                            CanvasFrame.this.notify();
                        }
                    }
                    return false;
                }
            });
        }};

        if (EventQueue.isDispatchThread()) {
            r.run();
        } else {
            try {
                EventQueue.invokeAndWait(r);
            } catch (Exception ex) { }
        }
    }

    public DisplayMode getDisplayMode() {
        return getGraphicsConfiguration().getDevice().getDisplayMode();
    }

    // used for example as debugging console...
    public static CanvasFrame global = null;

    // maximum is 60 ms on Metacity and Windows XP, and 90 ms on Compiz Fusion,
    // but set the default to twice as much for safety...
    public static final long DEFAULT_LATENCY = 120;
    private long latency = DEFAULT_LATENCY;

    private KeyEvent keyEvent = null;

    private Canvas canvas = null;
    private boolean needInitialResize = false;
    private BufferStrategy bufferStrategy = null;
    private double invgamma;

    public long getLatency() {
        // if there exists some way to estimate the latency in real time,
        // add it here
        return latency;
    }
    public void setLatency(long latency) {
        this.latency = latency;
    }
    public void waitLatency() {
        try {
            Thread.sleep(getLatency());
        } catch (InterruptedException ex) { }
    }

    public KeyEvent waitKey() {
        return waitKey(0);
    }
    public synchronized KeyEvent waitKey(int delay) {
        try {
            keyEvent = null;
            wait(delay);
        } catch (InterruptedException ex) { }
        KeyEvent e = keyEvent;
        keyEvent = null;
        return e;
    }

    public Canvas getCanvas() {
        return canvas;
    }
    @Override public BufferStrategy getBufferStrategy() {
        return bufferStrategy;
    }

    public Graphics2D createGraphics() {
        return (Graphics2D)bufferStrategy.getDrawGraphics();
    }
    public void releaseGraphics(Graphics2D g) {
        g.dispose();
        bufferStrategy.show();
    }

    public Dimension getCanvasSize() {
        return canvas.getSize();
    }
    public void setCanvasSize(int width, int height) {
        // there is apparently a bug in Java code for Linux, and what happens goes like this:
        // 1. Canvas gets resized, checks the visible area (has not changed) and updates
        // BufferStrategy with the same size. 2. pack() resizes the frame and changes
        // the visible area 3. We call Canvas.setSize() with different dimensions, to make
        // it check the visible area and reallocate the BufferStrategy almost correctly
        // 4. We resize the Canvas to the desired size... pff..
        setExtendedState(NORMAL); // force unmaximization..
        canvas.setSize(width, height);
        pack();
        canvas.setSize(width+1, height+1);
        canvas.setSize(width, height);
        needInitialResize = false;
    }

    public void showImage(Image image, final int w, final int h) {
        if (image == null) {
            return;
        } else if(isResizable() && needInitialResize) {
            if (EventQueue.isDispatchThread()) {
                setCanvasSize(w, h);
            } else {
                try {
                    EventQueue.invokeAndWait(new Runnable() {
                        public void run() {
                            setCanvasSize(w, h);
                        }
                    });
                } catch (Exception ex) { }
            }
        }
        Graphics2D g = createGraphics();
        g.drawImage(image, 0, 0, canvas.getWidth(), canvas.getHeight(), null);
        releaseGraphics(g);
    }
    public void showImage(Image image, double scale) {
        if (image == null)
            return;
        int w = (int)Math.round(image.getWidth (null)*scale);
        int h = (int)Math.round(image.getHeight(null)*scale);
        showImage(image, w, h);
    }
    public void showImage(Image image) {
        showImage(image, 1.0);
    }

    // Java2D will do gamma correction for TYPE_CUSTOM BufferedImage, but
    // not for the standard types, so we need to do it manually...
    public void showImage(IplImage image, int w, int h) {
        showImage(image.getBufferedImage(image.getBufferedImageType() ==
                BufferedImage.TYPE_CUSTOM ? 1.0 : invgamma), w, h);
    }
    public void showImage(IplImage image, double scale) {
        showImage(image.getBufferedImage(image.getBufferedImageType() ==
                BufferedImage.TYPE_CUSTOM ? 1.0 : invgamma), scale);
    }
    public void showImage(IplImage image) {
        showImage(image.getBufferedImage(image.getBufferedImageType() ==
                BufferedImage.TYPE_CUSTOM ? 1.0 : invgamma));
    }

    public void showColor(Color color) {
        Graphics2D g = createGraphics();
        g.setColor(color);
        g.fillRect(0, 0, canvas.getWidth(), canvas.getHeight());
        releaseGraphics(g);
    }
    public void showColor(CvScalar color) {
        showColor(new Color((int)color.red(), (int)color.green(), (int)color.blue()));
    }

    // this should not be called from the event dispatch thread, but if it is,
    // it should still work... it should simply be slower as it will timeout
    // waiting for the moved event
    public static void tile(final CanvasFrame[] frames) {

        class MovedListener extends ComponentAdapter {
            boolean moved = false;
            @Override public void componentMoved(ComponentEvent e) {
                moved = true;
                Component c = e.getComponent();
                synchronized (c) {
                    c.notify();
                }
            }
        }
        final MovedListener movedListener = new MovedListener();

        // layout the canvas frames for the cameras in tiles
        int canvasCols = (int)Math.round(Math.sqrt(frames.length));
        if (canvasCols*canvasCols < frames.length) {
            // if we don't get a square, favor horizontal layouts
            // since screens are usually wider than cameras...
            // and we also have title bars, tasks bar, menus, etc that
            // takes up vertical space
            canvasCols++;
        }
        int canvasX = 0, canvasY = 0;
        int canvasMaxY = 0;
        for (int i = 0; i < frames.length; i++) {
            final int n = i;
            final int x = canvasX;
            final int y = canvasY;
            try {
                movedListener.moved = false;
                EventQueue.invokeAndWait(new Runnable() {
                    public void run() {
                        frames[n].addComponentListener(movedListener);
                        frames[n].setLocation(x, y);
                    }
                });
                int count = 0;
                while (!movedListener.moved && count < 5) {
                    // wait until the window manager actually places our window...
                    // wait a maximum of 500 ms since this does not work if
                    // we are on the event dispatch thread. also some window
                    // managers like Windows do not always send us the event...
                    synchronized (frames[n]) {
                        frames[n].wait(100);
                    }
                    count++;
                }
                EventQueue.invokeAndWait(new Runnable() {
                    public void run() {
                        frames[n].removeComponentListener(movedListener);
                    }
                });
            } catch (Exception ex) { }
            canvasX = frames[i].getX()+frames[i].getWidth();
            canvasMaxY = Math.max(canvasMaxY, frames[i].getY()+frames[i].getHeight());
            if ((i+1)%canvasCols == 0) {
                canvasX = 0;
                canvasY = canvasMaxY;
            }
        }
    }

}
TOP

Related Classes of com.googlecode.javacv.MovedListener

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.