sábado, 5 de julio de 2014

Using webcam in your Java Applications without pain.

When you need to implement webcam access in your Java applications, the first thing to do is perform a google search: http://www.google.com.mx/webhp?q=java%20webcam&gws_rd=ssl#q=java+webcam

With that, a huge amount of results are found by the search engine. However, things can be confusing in the begining because a wide variety of methods to achieve the goal are described.

Luckly, I found a very easy method to achieve the goal in this blog: http://www.sleepingdumpling.com/blog/download/jvideoinput/. The method described by the author was very easy to implement compared with other solutions.

Based in the above description, I was able to wrote a java library in order to get access to webcam in desktop Java apps (swing/JavaFX) avoiding me and others to write a lot of repetitive code simplifying the work. You can download the library from sourceforge.

Swing example usage:
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
    import org.grios.swing.jwebcam.JWebCamSimple;

    public class Test extends javax.swing.JFrame
    {
        public Test()
        {
            String[] devices = null;
            initComponents();
            jwcs = new JWebCamSimple();

            try
            {
                devices = JWebCamSimple.getDeviceNames();
                for (String s : devices)
                    jComboBox1.addItem(s);
            } 
            catch (Exception e)
            {
                e.printStackTrace();
                System.exit(0);
            }
        }
        private void initComponents()
        {
            jLabel1 = new javax.swing.JLabel();
            jComboBox1 = new javax.swing.JComboBox();
            jButton1 = new javax.swing.JButton();
            jDesktopPane1 = new javax.swing.JDesktopPane();
            jInternalFrame1 = new javax.swing.JInternalFrame();
            jLabel2 = new javax.swing.JLabel();
            jButton2 = new javax.swing.JButton();

            setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

            jLabel1.setText("Available Devices:");

            jButton1.setText("Start");
            jButton1.addActionListener(new java.awt.event.ActionListener()
            {
                public void actionPerformed(java.awt.event.ActionEvent evt)
                {
                    jButton1ActionPerformed(evt);
                }
            });

            jDesktopPane1.setBackground(new java.awt.Color(255, 255, 255));

            jInternalFrame1.setMaximizable(true);
            jInternalFrame1.setResizable(true);
            jInternalFrame1.setTitle("No Device");
            jInternalFrame1.setVisible(true);

            jLabel2.setBackground(new java.awt.Color(255, 255, 255));
            jLabel2.setOpaque(true);
            jInternalFrame1.getContentPane().add(jLabel2, java.awt.BorderLayout.CENTER);

            jDesktopPane1.add(jInternalFrame1);
            jInternalFrame1.setBounds(10, 11, 160, 162);

            jButton2.setText("Stop");
            jButton2.addActionListener(new java.awt.event.ActionListener()
            {
                public void actionPerformed(java.awt.event.ActionEvent evt)
                {
                    jButton2ActionPerformed(evt);
                }
            });

            javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
            getContentPane().setLayout(layout);
            layout.setHorizontalGroup(
                layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(layout.createSequentialGroup()
                    .addContainerGap()
                    .addComponent(jLabel1)
                    .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                    .addComponent(jComboBox1, javax.swing.GroupLayout.PREFERRED_SIZE, 188, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                    .addComponent(jButton1)
                    .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                    .addComponent(jButton2)
                    .addContainerGap(67, Short.MAX_VALUE))
                .addComponent(jDesktopPane1)
            );
            layout.setVerticalGroup(
                layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(layout.createSequentialGroup()
                    .addContainerGap()
                    .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                        .addComponent(jLabel1)
                        .addComponent(jComboBox1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addComponent(jButton1)
                        .addComponent(jButton2))
                    .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                    .addComponent(jDesktopPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 260, Short.MAX_VALUE))
            );

            setBounds(0, 0, 496, 339);
        }            

        private void jButton1ActionPerformed(java.awt.event.ActionEvent evt)                                         
        {                                             
            try
            {
                jComboBox1.setEnabled(false);
                jButton1.setEnabled(false);
                jwcs.start(jComboBox1.getSelectedItem().toString(), jLabel2);

            } 
            catch (Exception e)
            {
                e.printStackTrace();
                System.exit(0);
            }
        }                                        

        private void jButton2ActionPerformed(java.awt.event.ActionEvent evt)                                         
        {                                             
            if (jwcs.isRunning())
                jwcs.stop();            

            jButton1.setEnabled(true);
            jComboBox1.setEnabled(true);
        }                                        

        public static void main(String args[])
        {
                    try
                    {
                            javax.swing.UIManager.setLookAndFeel(javax.swing.UIManager.getSystemLookAndFeelClassName());
                    }
                    catch (Exception ex)
                    {
                    }
            java.awt.EventQueue.invokeLater(new Runnable()
            {
                public void run()
                {
                    new Test().setVisible(true);
                }
            });
        }

        private javax.swing.JButton jButton1;
        private javax.swing.JButton jButton2;
        private javax.swing.JComboBox jComboBox1;
        private javax.swing.JDesktopPane jDesktopPane1;
        private javax.swing.JInternalFrame jInternalFrame1;
        private javax.swing.JLabel jLabel1;
        private javax.swing.JLabel jLabel2;    
        JWebCamSimple jwcs;
    }

On the above code, in line 151 we are declaring  a JWebCamSimple object named jwcs. With JWebCamSimple we will able to play our web cam after of create an instance of it (line 9).
Finally, you can start the webcam calling to start() (line 107) method by passing two arguments:
  • The Device Name, specified as a String value.
  • The Swing component (JComponent) where the webcam video will be displayed. The most easy solution is passing a JLabel object.
For the device name, you sould let the user to select the video device. In above example, this is done firstly on lines 13-15, where the program ask for the video devices available (line 13) and after, a JComboBox object is filled with each found device's name (lines 14 and 15).

And a JavaFX example:
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
        import javafx.application.Application;
        import javafx.collections.FXCollections;
        import javafx.geometry.Insets;
        import javafx.scene.Scene;
        import javafx.scene.control.Button;
        import javafx.scene.control.ComboBox;
        import javafx.scene.control.Label;
        import javafx.scene.image.ImageView;
        import javafx.scene.layout.BorderPane;
        import javafx.scene.layout.ColumnConstraints;
        import javafx.scene.layout.GridPane;
        import javafx.scene.layout.Priority;
        import javafx.scene.layout.RowConstraints;
        import javafx.stage.Stage;
        import org.grios.jwebcam.fx.FXWebCamSimple;

        public class Test extends Application
        {   
            Scene scene;
            BorderPane mainPane;
            GridPane topPane;
            ComboBox<String> cmbVideoDevices;
            Label lblVideoDevices;
            ImageView imgvDisplay;
            Button btnStartDevice;
            Button btnStopDevice;

            FXWebCamSimple fxWebCam;   

           Override
            public void start(Stage primaryStage) throws Exception
            {
                initComponents();

                scene = new Scene(mainPane);
                primaryStage.setWidth(480);
                primaryStage.setHeight(240);
                primaryStage.setTitle("JWebCamFX Demo");
                primaryStage.setScene(scene);
                primaryStage.setOnCloseRequest((evt) -&gt;
                {
                    System.exit(0);
                });
                primaryStage.show();

                fxWebCam = new FXWebCamSimple();

            }

            private void initComponents()
            {
                lblVideoDevices = new Label("Available Video Devices:");
                cmbVideoDevices = new ComboBox<String>(FXCollections.observableArrayList());
                btnStartDevice = new Button("Start");
                btnStopDevice = new Button("Stop");
                imgvDisplay = new ImageView();        

                lblVideoDevices.setPrefSize(135, 21);
                cmbVideoDevices.setPrefSize(140, 21);
                btnStartDevice.setPrefSize(50, 21);
                btnStopDevice.setPrefSize(50, 21);

                btnStartDevice.setOnAction((evt) -&gt; 
                {

                    try
                    {
                        btnStartDevice.setDisable(true);
                        lblVideoDevices.setDisable(true);
                        cmbVideoDevices.setDisable(true);

                        fxWebCam.start(cmbVideoDevices.getSelectionModel().getSelectedItem(), imgvDisplay);
                    } 
                    catch (Exception e)
                    {
                        e.printStackTrace();
                        System.exit(0);
                    }
                });

                btnStopDevice.setOnAction((evt) -&gt;
                {
                    try
                    {
                        fxWebCam.stop();                
                        btnStartDevice.setDisable(false);
                        lblVideoDevices.setDisable(false);
                        cmbVideoDevices.setDisable(false);
                    } 
                    catch (Exception e)
                    {
                        e.printStackTrace();
                        System.exit(0);
                    }
                });


                fillComboBox();

                topPane = new GridPane();
                topPane.setPadding(new Insets(5));
                topPane.setHgap(10);
                topPane.setVgap(10);
                topPane.add(lblVideoDevices, 0, 0);
                topPane.add(cmbVideoDevices, 1, 0);
                topPane.add(btnStartDevice, 2, 0);
                topPane.add(btnStopDevice, 3, 0);

                mainPane = new BorderPane();
                imgvDisplay.fitWidthProperty().bind(mainPane.widthProperty());
                imgvDisplay.fitHeightProperty().bind(mainPane.heightProperty());
                imgvDisplay.setSmooth(true);
                imgvDisplay.setCache(true);
                mainPane.setCenter(imgvDisplay);
                mainPane.setTop(topPane);
            }

            private void fillComboBox()
            {
                try
                {
                    cmbVideoDevices.getItems().clear();
                    for (String str : FXWebCamSimple.getDeviceNames())
                        cmbVideoDevices.getItems().add(str);
                    if (cmbVideoDevices.getItems().size() &gt; 0)
                        cmbVideoDevices.getSelectionModel().selectFirst();
                } 
                catch (Exception e)
                {
                    e.printStackTrace();
                    System.exit(0);
                }
            }

            public static void main(String[] args)
            {
                launch(args);
            }
        }

Good luck!

+ Grios

No hay comentarios: