Developing Java* Components for Netbooks

Related Downloads

A How-To Guide to Developing Java* Class Libraries that Target Netbook Application Developers Introduction

Netbooks have become very popular in a short time. These devices often lack the processing power, memory, drive size, display size, and DVD players of the typical laptop in exchange for small size, longer battery life and are targeted mostly for web browsing, e-mail activities and "cloud computing" where the storage and manipulation of the user's files are on a remote "cloud" of servers.

Java* is an obvious choice for developing small, targeted applications that provide useful functions to the netbook user. Java* is a perfect platform for netbook targeted development: Java* is a mature, popular, and well documented development platform. Also, Java* development is a virtually cost free. Java* programs run in a Java* Virtual Machine (JVM) using a common library so the application is a small set of binary code that uses a standardized platform. This makes a Java* application fast to download and easy to run. Also, Java is installed and running on every machine, everywhere.

This article discusses the using of Java* to develop netbook applications and the concept of developing component libraries of Java* classes that provide a specific set of tools that can be used by other developers to create netbook applications.

The Intel AppUp® center is designed for developers interested in contributing to the growing market of applications for Netbooks based on Intel® Atom™ processors. The Component Catalog is a repository of building blocks you can embed in your application to accelerate development. You can even develop and publish your own components for others to use.

A tutorial style case study is presented that will guide the reader through the creation of a Java* component library, how it is used in an application, and creating the supporting documentation and other metadata.

The component library developed for this example is called VideoLibrary. It is a set of Java* classes that are used for finding a video device, creating a player to show the video stream, showing the video stream, and capturing a frame image from the video and saving it as a JPEG file. The example then goes on to show the use of the library in an application and the creation of the supporting metadata.

Intel AppUp® Developers

The Intel AppUp® developer section of the Intel® Developer Zone includes:

  • Web content designed specifically for the Netbook application developer community.
  • A validation process for validating and approving your applications to be deployed through the system.
  • A distribution program to make your applications available to customers.
  • A client running on customers' Netbooks, which connects customers to the distribution program.

Getting Started

Software and Equipment

The VideoSource library was built using Java* Standard Edition (SE) using the Java* SE development Kit (JDK) version 6, Java* Media Framework 2.1.1e, and NetBeans 6.7.1 The tools and libraries that are needed to build the library and application and the Web location:

Java* SE 6 JRE

This is the basic runtime required to run Java* applications
http://java.sun.com/javase/downloads/index.jsp

Java* SE JDK 6

This is the development libraries
http://java.sun.com/javase/downloads/index.jsp

Java* NetBeans IDE for SE

The development environment
http://www.netbeans.org/downloads/index.html

Java* Media Framework 2.1.1e

A framework library supporting audio and video media and devices
http://java.sun.com/javase/technologies/desktop/media/jmf/2.1.1/download.html

Development can be done on any machine but a Windows XP netbook should be used to test the components and applications.

Creating the Project

After the required platform tools and libraries are installed startup the NetBeans IDE. The splash screen will appear.

Select the File - New Project menu item.

Now select Java* for the category and Java* Class Library as the project type and select Next.

Now type in the project's name 'VideoLibrary' and select the Finish button.

In order for you library to be easily incorporated into a application development create a Package and name it VidLib. To do this right click on the Source Package project listing entry and select New and, under that, Java* Package.

Now name the package 'VidLibPkg' and select Finish.

The final setup step is to create a first library class. Right click on the new VidLibPkg package and select New and Java Class.

Name the class VidLib and select Finish.

Now the project is ready to start programming.

Programming the Library

After setting up the library project programming can begin. This is the hard part.

Planning

In order to create a Java* library the first issue is determining what it is supposed to provide. This is best determined by coming up with a concept of what kind of applications would use this library. This tutorial uses the concept of providing an application developer with a set of basic tools to create an application that can show a video stream and capture a frame image from it. This example may seem a bit light for an application library. But remember, this is a targeted towards netbook applications and the lighter the better. Libraries can be combined to create more feature filled applications so your libraries should be designed to provide a single core function.

What would be in demand is another consideration. What would a netbook user want? What is available on a netbook that can be enhanced with software?

Once you know what the library is to provide study the libraries and classes that will provide the basic tools needed.

Looking through the Java* documentation and searching the internet determines that the Java* Media Framework is required to interface with and use video devices. This is contained in the javax.media.* imports.

Coding

All of the code for the library and the application is included at the end of this article here.

The first step is to provide a means to determine if a video camera is attached to the computer running the application. Therefore, the first method to code into the class is one to provide a list of potential video devices to use. The class CaptureDeviceManager is a manager class that has access to a list of capture devices available. It can locate and return CaptureDeviceInfo objects for available devices.

There is almost always only one video device on a netbook (and most other computers). If there are any entries the code can use the first in the list as a default, at least in this example. The first method to code is getVideoDeviceList. Notice that the added code has several red underlined items. This is because these are undefined. To fix this the correct libraries need to be imported. In the NetBeans IDE this can be done automatically by right clicking in the source code panel and selecting Fix Imports.

After this the correct import entries are made and the source code is now correct.

The correct imports have now been added to the source code.

Notice that the getVideoDeviceList method is public meaning that the application that uses this class has access to the function. Notice also that it is defined as static. This means that this method can be accessed without instantiating (using new to create an instance) by using the class name like this: VidLib. getVideoDeviceList(). Also, no matter how many instances of the VidLib class are created, there will be only one instance of this method.

The next step is to provide the application developer with a means to use the selected device and display the video output. The Component is the visual component of the player used to display the video stream. A method to create the player and return a Component is needed. The Player object is used to start and stop the video. Each VidLib class must have its own Player so one is added as a class element.

A MediaLocator object is created from the CaptureDeviceInfo object provided as a parameter to the method call. The javax.Media.Manager class is the access point for obtaining system dependent resources. Here it creates a video player and from the player a visual component is obtained. The returned component can be used directly as a video screen in a JPanel object by using the add method.

Now that the methods to find and display a video are created, a way to capture an image from the video player and save the image to a file is needed. The getVideoFrameImage method returns an image from the player that can be then saved to a file.

The FrameGrabbingControl is an interface used to grab a still video frame from the video stream and place it into the javax.media.Buffer. This control is exported by the Player using the getControl method. The frame returned is in a raw decoded format. The BufferToImage class is used to convert it into an AWT Image object. Image is an abstract class and is the superclass of all classes that represent graphical images and must be obtained in a platform-specific way.

See:
The final method needed by the application developer is one that takes an captured image and saves the image to a file. The saveVidioFrameImage_to_JPEG_File method uses image and file path arguments to create a JPEG format saved image.

The BufferedImage is an Image subclass used to create a Graphics2D object that renders the image using the drawImage method. The FileOutputStream class is simply an output file used by the JPEGImageEncoder to save the image after it encodes the image buffer data into a JPEG data stream. The JPEGEncodeParam encapsulates tables and options necessary to control encoding of JPEG data streams and sets the quality of the image saved.

Testing the Class Library

Testing the class library does not require that a separate application be created to test the library class. By creating a public static void main(String[] args) method allows you to run the library as an application and test the code. When the class library is being distributed (see below) it may be prudent to remove this code so that the library is smaller in size and does not use any extra UI libraries (like swing in this case) that are not used in the applications using the library.

Here is a screen shot of the application showing the video output of the application of the application window:

Using the Class Library in an Application

Create an application project called VideoSave using the File - New Project menu selections.

Right click the project and select properties.

Now select the Libraries category, the Compile tab, and the Add JAR/Folder button.

Now look for the distribution folder (dist) of the VideoLibrary project.

Now select the VideoLibrary.jar file with the Open button. This is the class library.

Select the OK button and return to the editing IDE. The import entry that allows you to use the class library import VidLibPkg.VidLib; has been added.

The same code in the main method of the VidLib class library can be used here to test the library.

Documenting the Class Library

One of the best things about Java* is the self documentation using Javadoc. Right click on a project and select the Javadoc item.

Documentation by the developer can and should be added to better document the code. More on this can be found here: How to Write Doc Comments for the Javadoc Tool.

The Javadoc tool creates HTML files that are placed in the distribution directory dist.

Library Distribution

The dist project subdirectory contains all of the files needed to use the library.

For more information look at the JAR File Specification, and Packaging Programs in JAR Files.

Resources


Source Code

VidLibPkg VidLib Class Library

package VidLibPkg;

import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGEncodeParam;
import com.sun.image.codec.jpeg.JPEGImageEncoder;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Enumeration;
import java.util.Vector;
import javax.media.CannotRealizeException;
import javax.media.CaptureDeviceInfo;
import javax.media.CaptureDeviceManager;
import javax.media.Manager;
import javax.media.MediaLocator;
import javax.media.Player;
import javax.media.control.FrameGrabbingControl;
import javax.media.format.VideoFormat;
import javax.media.util.BufferToImage;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class VidLib {

    public static void main(String[] args) {
        final VidLib vs = new VidLib();
        Vector<CaptureDeviceInfo> dl = VidLib.getVideoDeviceList();
        final Component comp = vs.getVideoComponent(dl.get(0));
        JButton btnCapture = new JButton("Capture");
        btnCapture.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent ae) {
                // capture an image and save it to a file when the button is pressed
                Image img = vs.getVideoFrameImage();
                vs.saveVidioFrameImage_to_JPEG_File(img, ".\\SavedImage.jpg");
            }
        });
        // Create and add a video display panel
        JPanel vp = new JPanel();
        vp.setLayout(new BorderLayout());
        // add the capture button and the video display componnent to the video panel
        vp.add(btnCapture, BorderLayout.SOUTH);
        vp.add(comp, BorderLayout.NORTH);
        // Create the dialog frame
        JFrame f = new JFrame("Video Capture");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setResizable(true);
        f.add("Center", vp);
        // size the Window to fit the preferred size and layouts of its subcomponents.
        f.pack();
        // Center the frame
        f.setLocationRelativeTo(null);
        // let them see it
        f.setVisible(true);
        return;
    }

    public boolean saveVidioFrameImage_to_JPEG_File(Image img, String FilePath) {
        boolean bSuccess = false;
        if ((null == FilePath) || (FilePath.isEmpty())) {
            return (false);
        }
        BufferedImage bi = new BufferedImage(img.getWidth(null),
                img.getHeight(null), BufferedImage.TYPE_INT_RGB);
        Graphics2D g2 = bi.createGraphics();
        g2.drawImage(img, null, null);
        FileOutputStream jpegFileOut = null;
        JPEGImageEncoder encoder = null;
        try {
            jpegFileOut = new FileOutputStream(FilePath);
        } catch (java.io.FileNotFoundException io) {
            io.printStackTrace();
        }
        try {
            encoder = JPEGCodec.createJPEGEncoder(jpegFileOut);
            JPEGEncodeParam param = encoder.getDefaultJPEGEncodeParam(bi);

            // 0.75 high quality 0.5  medium quality 0.25 low quality
            // forceBaseline - force baseline quantization table
            param.setQuality(1.0f, false);
            encoder.setJPEGEncodeParam(param);
        } catch (Exception e) {
            e.printStackTrace();
        }
        try {
            encoder.encode(bi);
            jpegFileOut.close();
            bSuccess = true;
        } catch (java.io.IOException io) {
            io.printStackTrace();
        }
        return (bSuccess);
    }

    public Image getVideoFrameImage() {
        Image img = null;
        try {
            FrameGrabbingControl fgc =
                    (FrameGrabbingControl) vidplayer.getControl("javax.media.control.FrameGrabbingControl");
            javax.media.Buffer buf = fgc.grabFrame();
            // Convert it to an image
            BufferToImage btoi = new BufferToImage((VideoFormat) buf.getFormat());
            img = btoi.createImage(buf);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return (img);
    }
    Player vidplayer = null;

    public Component getVideoComponent(CaptureDeviceInfo cdi) {
        Component comp = null;
        MediaLocator ml = null;
        if (null != cdi) {
            try {
                ml = cdi.getLocator();
            } catch (Exception e) {
                e.printStackTrace();
            }
            try {
                try {
                    vidplayer = Manager.createRealizedPlayer(ml);
                } catch (IOException e) {
                    e.printStackTrace();
                } catch (CannotRealizeException e) {
                    e.printStackTrace();
                }
            } catch (javax.media.NoPlayerException e) {
                e.printStackTrace();
            }
            try {
                comp = vidplayer.getVisualComponent();
            } catch (Exception e) {
                e.printStackTrace();
            }
            try {
                vidplayer.start();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return (comp);
    }

    public static Vector<CaptureDeviceInfo> getVideoDeviceList() {

        Vector devices;
        Enumeration dev_enum;
        CaptureDeviceInfo cdi;
        // <CaptureDeviceInfo> checks that the type is CaptureDeviceInfo
        Vector<CaptureDeviceInfo> videoDevices = null;
        try {
            devices = (Vector) CaptureDeviceManager.getDeviceList(null).clone();
            dev_enum = devices.elements();

            if (devices != null && devices.size() > 0) {
                // <CaptureDeviceInfo> checks that the type is CaptureDeviceInfo
                videoDevices = new Vector<CaptureDeviceInfo>();
                javax.media.Format[] formats;

                while (dev_enum.hasMoreElements()) {
                    cdi = (CaptureDeviceInfo) dev_enum.nextElement();
                    formats = cdi.getFormats();

                    for (int j = 0; j < formats.length; j++) {
                        if (formats[j] instanceof VideoFormat) {
                            videoDevices.addElement(cdi);
                            break;
                        }
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return (videoDevices);
    }
}

VideoSave Application Main.java

package videosave;

import VidLibPkg.VidLib;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Vector;
import javax.media.CaptureDeviceInfo;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

/**
 *
 * @author me
 */
public class Main {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        final VidLib vs = new VidLib();
        Vector<CaptureDeviceInfo> dl = VidLib.getVideoDeviceList();
        final Component comp = vs.getVideoComponent(dl.get(0));
        JButton btnCapture = new JButton("Capture");
        btnCapture.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent ae) {
                // capture an image and save it to a file when the button is pressed
                Image img = vs.getVideoFrameImage();
                vs.saveVidioFrameImage_to_JPEG_File(img, ".\\SavedImage.jpg");
            }
        });
        // Create and add a video display panel
        JPanel vp = new JPanel();
        vp.setLayout(new BorderLayout());
        // add the capture button and the video display componnent to the video panel
        vp.add(btnCapture, BorderLayout.SOUTH);
        vp.add(comp, BorderLayout.NORTH);
        // Create the dialog frame
        JFrame f = new JFrame("Video Capture");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setResizable(true);
        f.add("Center", vp);
        // size the Window to fit the preferred size and layouts of its subcomponents.
        f.pack();
        // Center the frame
        f.setLocationRelativeTo(null);
        // let them see it
        f.setVisible(true);
        return;
    }

} 
Para obter mais informações sobre otimizações de compiladores, consulte Aviso sobre otimizações.