Simple Java Wrapper Class for raspistill on the Raspberry Pi 2

Like many self-proclaimed geeks, I can't resist a change to play with new technology. So when the Raspberry Pi 2 was released a short time ago, I didn't hesitate buying one. My first impressions was: for $35, that's a lot of computer power in a very small package. And because I really am a geek, I will admit that the first thing I tried to do with it was to install DOSBOX and run Microsoft Flight Simulator 4.

Once I got that out of my system, I started experimenting with some simple Java programming and the Raspberry Pi camera module. (It's great that Java is built-into Raspian Wheezy; in the past you had to install it.)

That being said, there isn't any direct I/O control of the camera via Java, although that's pretty much expected. When considering ways to control the camera I came across the Pi4J library, which provides Java-based APIs to control the Raspberry Pi's I/O. This looks like it will be great for me eventually, but for the moment the best idea that I could come up with was to write a simple Java-based wrapper class for the raspistill command line executable.

With that in mind, here's a sample class that you can use to take photos from Java on a Raspberry Pi. I added lots of code comments to explain how everything works, and I'll provide a little more detail after the code sample.

// This class is a very simple Java wrapper for the raspistill executable,
// which makes it easier to take photos from a Java application. Note that
// there are considerably more parameters available for raspistill which
// could be added to this class. (e.g. Shutter Speed, ISO, AWB, etc.) 

public class RaspiStill
{
   // Define the path to the raspistill executable.
   private final String _raspistillPath = "/opt/vc/bin/raspistill";
   // Define the amount of time that the camera will use to take a photo.
   private final int _picTimeout = 5000;
   // Define the image quality.
   private final int _picQuality = 100;

   // Specify a default image width.
   private int _picWidth = 1024;
   // Specify a default image height.
   private int _picHeight = 768;
   // Specify a default image name.
   private String _picName = "example.jpg";
   // Specify a default image encoding.
   private String _picType = "jpg";

   // Default class constructor.
   public void RaspiStill()
   {
      // Do anything else here. For example, you could create another
      // constructor which accepts an alternate path to raspistill,
      // or defines global parameters like the image quality.
   }

   // Default method to take a photo using the private values for name/width/height.
   // Note: See the overloaded methods to override the private values.
   public void TakePicture()
   {
      try
      {
         // Determine the image type based on the file extension (or use the default).
         if (_picName.indexOf('.')!=-1) _picType = _picName.substring(_picName.lastIndexOf('.')+1);

         // Create a new string builder with the path to raspistill.
         StringBuilder sb = new StringBuilder(_raspistillPath);

         // Add parameters for no preview and burst mode.
         sb.append(" -n -bm");
         // Configure the camera timeout.
         sb.append(" -t " + _picTimeout);
         // Configure the picture width.
         sb.append(" -w " + _picWidth);
         // Configure the picture height.
         sb.append(" -h " + _picHeight);
         // Configure the picture quality.
         sb.append(" -q " + _picQuality);
         // Specify the image type.
         sb.append(" -e " + _picType);
         // Specify the name of the image.
         sb.append(" -o " + _picName);

         // Invoke raspistill to take the photo.
         Runtime.getRuntime().exec(sb.toString());
         // Pause to allow the camera time to take the photo.
         Thread.sleep(_picTimeout);
      }
      catch (Exception e)
      {
         // Exit the application with the exception's hash code.
         System.exit(e.hashCode());
      }
   }

   // Overloaded method to take a photo using specific values for the name/width/height.
   public void TakePicture(String name, int width, int height)
   {
      _picName = name;
      _picWidth = width;
      _picHeight = height;
      TakePicture();
   }

   // Overloaded method to take a photo using a specific value for the image name.
   public void TakePicture(String name)
   {
      TakePicture(name, _picWidth, _picHeight);
   }

   // Overloaded method to take a photo using specific values for width/height.
   public void TakePicture(int width, int height)
   {
      TakePicture(_picName, width, height);
   }
}

The wrapper class should be pretty self-explanatory: calling the TakePicture() method with no parameters will use the application defaults, and calling the overloaded methods will allow you to specify the output filename and the width/height for the image. You specify the image type based on the file extension; (e.g. ".jpg", ".png", ".gif"). There are a bunch of additional raspistill options which you can easily add to the application; see the Raspberry Pi camera module page for more information.

Here's a simple application to test it out:

public class CameraTest
{
  // Define the number of photos to take.
  private static final long _numberOfImages = 5;
  // Define the interval between photos.
  private static final int _delayInterval = 5000;

  public static void main(String[] args)
  {
    try
    {
      // Create a new RaspiStill object.
      RaspiStill camera = new RaspiStill();
      // Loop through the number of images to take.
      for (long i = 0; i < _numberOfImages; ++i)
      {
        // Capture the image.
        camera.TakePicture("image" + i + ".jpg",800,600);
        // Pause after each photo.
        Thread.sleep(_delayInterval);
      }
    }
    catch (Exception e)
    {
      // Exit the application with the exception's hash code.
      System.exit(e.hashCode());
    }
  }
}

Now that I've shared this odd little sample, I'll wander back to my dungeon so I can keep playing with my Raspberry Pi.


Note: This blog was originally posted at http://blogs.msdn.com/robert_mcmurray/

Comments are closed