001package org.opencv.highgui;
002
003import org.opencv.core.Mat;
004
005import javax.swing.*;
006import java.awt.*;
007import java.awt.event.KeyEvent;
008import java.awt.event.KeyListener;
009import java.awt.image.BufferedImage;
010import java.awt.image.DataBufferByte;
011import java.util.HashMap;
012import java.util.Iterator;
013import java.util.Map;
014import java.util.concurrent.CountDownLatch;
015import java.util.concurrent.TimeUnit;
016
017/**
018 * This class was designed for use in Java applications
019 * to recreate the OpenCV HighGui functionalities.
020 */
021public final class HighGui {
022
023    // Constants for namedWindow
024    public final static int WINDOW_NORMAL = ImageWindow.WINDOW_NORMAL;
025    public final static int WINDOW_AUTOSIZE = ImageWindow.WINDOW_AUTOSIZE;
026
027    // Control Variables
028    public static int n_closed_windows = 0;
029    public static int pressedKey = -1;
030    public static CountDownLatch latch = new CountDownLatch(1);
031
032    // Windows Map
033    public static Map<String, ImageWindow> windows = new HashMap<String, ImageWindow>();
034
035    public static void namedWindow(String winname) {
036        namedWindow(winname, HighGui.WINDOW_AUTOSIZE);
037    }
038
039    public static void namedWindow(String winname, int flag) {
040        ImageWindow newWin = new ImageWindow(winname, flag);
041        if (windows.get(winname) == null) windows.put(winname, newWin);
042    }
043
044    public static void imshow(String winname, Mat img) {
045        if (img.empty()) {
046            System.err.println("Error: Empty image in imshow");
047            System.exit(-1);
048        } else {
049            ImageWindow tmpWindow = windows.get(winname);
050            if (tmpWindow == null) {
051                ImageWindow newWin = new ImageWindow(winname, img);
052                windows.put(winname, newWin);
053            } else {
054                tmpWindow.setMat(img);
055            }
056        }
057    }
058
059    public static Image toBufferedImage(Mat m) {
060        int type = BufferedImage.TYPE_BYTE_GRAY;
061
062        if (m.channels() > 1) {
063            type = BufferedImage.TYPE_3BYTE_BGR;
064        }
065
066        int bufferSize = m.channels() * m.cols() * m.rows();
067        byte[] b = new byte[bufferSize];
068        m.get(0, 0, b); // get all the pixels
069        BufferedImage image = new BufferedImage(m.cols(), m.rows(), type);
070
071        final byte[] targetPixels = ((DataBufferByte) image.getRaster().getDataBuffer()).getData();
072        System.arraycopy(b, 0, targetPixels, 0, b.length);
073
074        return image;
075    }
076
077    public static JFrame createJFrame(String title, int flag) {
078        JFrame frame = new JFrame(title);
079
080        frame.addWindowListener(new java.awt.event.WindowAdapter() {
081            @Override
082            public void windowClosing(java.awt.event.WindowEvent windowEvent) {
083                n_closed_windows++;
084                if (n_closed_windows == windows.size()) latch.countDown();
085            }
086        });
087
088        frame.addKeyListener(new KeyListener() {
089            @Override
090            public void keyTyped(KeyEvent e) {
091            }
092
093            @Override
094            public void keyReleased(KeyEvent e) {
095            }
096
097            @Override
098            public void keyPressed(KeyEvent e) {
099                pressedKey = e.getKeyCode();
100                latch.countDown();
101            }
102        });
103
104        if (flag == WINDOW_AUTOSIZE) frame.setResizable(false);
105
106        return frame;
107    }
108
109    public static void waitKey(){
110        waitKey(0);
111    }
112
113    public static int waitKey(int delay) {
114        // Reset control values
115        latch = new CountDownLatch(1);
116        n_closed_windows = 0;
117        pressedKey = -1;
118
119        // If there are no windows to be shown return
120        if (windows.isEmpty()) {
121            System.err.println("Error: waitKey must be used after an imshow");
122            System.exit(-1);
123        }
124
125        // Remove the unused windows
126        Iterator<Map.Entry<String,
127                ImageWindow>> iter = windows.entrySet().iterator();
128        while (iter.hasNext()) {
129            Map.Entry<String,
130                    ImageWindow> entry = iter.next();
131            ImageWindow win = entry.getValue();
132            if (win.alreadyUsed) {
133                iter.remove();
134                win.frame.dispose();
135            }
136        }
137
138        // (if) Create (else) Update frame
139        for (ImageWindow win : windows.values()) {
140
141            if (win.img != null) {
142
143                ImageIcon icon = new ImageIcon(toBufferedImage(win.img));
144
145                if (win.lbl == null) {
146                    JFrame frame = createJFrame(win.name, win.flag);
147                    JLabel lbl = new JLabel(icon);
148                    win.setFrameLabelVisible(frame, lbl);
149                } else {
150                    win.lbl.setIcon(icon);
151                }
152            } else {
153                System.err.println("Error: no imshow associated with" + " namedWindow: \"" + win.name + "\"");
154                System.exit(-1);
155            }
156        }
157
158        try {
159            if (delay == 0) {
160                latch.await();
161            } else {
162                latch.await(delay, TimeUnit.MILLISECONDS);
163            }
164        } catch (InterruptedException e) {
165            e.printStackTrace();
166        }
167
168        // Set all windows as already used
169        for (ImageWindow win : windows.values())
170            win.alreadyUsed = true;
171
172        return pressedKey;
173    }
174
175    public static void destroyWindow(String winname) {
176        ImageWindow tmpWin = windows.get(winname);
177        if (tmpWin != null) windows.remove(winname);
178    }
179
180    public static void destroyAllWindows() {
181        windows.clear();
182    }
183
184    public static void resizeWindow(String winname, int width, int height) {
185        ImageWindow tmpWin = windows.get(winname);
186        if (tmpWin != null) tmpWin.setNewDimension(width, height);
187    }
188
189    public static void moveWindow(String winname, int x, int y) {
190        ImageWindow tmpWin = windows.get(winname);
191        if (tmpWin != null) tmpWin.setNewPosition(x, y);
192    }
193}