iBond
As the end of our London-themed mobile application tour rolls around, we turn to the world famous Mr. Bond, James Bond. One of the features not provided for by mobile browsers yet is the ability to take a picture using the device camera. This of course makes it hard for James to use a web standards-based application to take spy photos when he’s off saving the world. Luckily, as we reach into Q’s bag of tricks we can tap into the device APIs offered by Mr. Gap, PhoneGap.
From the point of conceiving all four demonstration ideas, through development, and to the point of delivery, which included a trip from the United States to London, England, was four days. Four applications in four days was an ambitious goal to be sure, but PhoneGap and web standards made it happen.
PhoneGap and web standards didn’t however, give me the boost in creative energy I need to finish off the second half of this application. I never really could land on a look I liked for the buttons. I tried caffeine, beer, cigars, and even walking around picturesque London for a few hours, but my creative juices were tapped.
I really wanted to fill the buttons with the texture of the handle from James Bond’s preferred weapon, the Walther PPK. Unfortunately, I couldn’t find large enough pictures to accomplish that easily, and my Photoshop skills were letting me down in a big way after coming over the Pacific Ocean. Point being that while I like how most of the application looks, I can’t stand the buttons.
Device Camera Capture
The application presents two button for James to use. The first button presents 007 with the opportunity to take a picture using the device camera. When tapped, a call to “navigator.camera.getPicture()” will present the device UI for taking a picture. The call takes a success function, a failure function, and options as arguments.
$( this ).attr( ‘src’, ‘assets/camera.down.png’ );
navigator.camera.getPicture( function( data ) {
$( ‘#photo’ )
.attr( ‘src’, ‘data:image/jpeg;base64,’ + data )
.css( ‘visibility’, ‘visible’ );
$( ‘#camera’ ).attr( ‘src’, ‘assets/camera.up.png’ );
}, function( error ) {
console.log( ‘Error’ );
}, {
destinationType: Camera.DestinationType.DATA_URL,
sourceType: Camera.PictureSourceType.CAMERA,
allowEdit: false,
targetWidth: 260,
targetHeight: 435
} );
} );
There are a number of options that you can provide, which can make using this part of the PhoneGap API a little tricky. In my case, I wanted to get the image data itself back after the picture was taken. Depending on the device, and the resolution of the camera, this might be more data than can easily be passed back from the device into the PhoneGap application. I didn’t have a problem, but it is something to be aware of during development.
The alternative option then is to get a reference to a file on disk where the image is stored. From there it is up to you to manage if that file gets a life longer than that of the application, where it lives, etc. Once you’ve taken care of the details, you can change the “src” attribute of an IMG tag to show the image from disk, set the image as background to a DOM element using CSS, or even simply process the image bytes further for whatever additional data it is that you might be mining (e.g. Exif).
From there, I specified that the source was to be “Camera.PictureSourceType.CAMERA”, which is the notation for the device camera. The other option would be “Camera.PictureSourceType.PHOTOLIBRARY”, which we will cover in a moment. Along the way, you can tell the device to allow the user to edit the picture they’ve taken, should the device support image editing.
One of the nice things that PhoneGap does for you is image sizing. This would otherwise be horribly pixelated if the full image was smashed down into a smaller version by force, or conversely take forever to process making a thumbnail directly with JavaScript. PhoneGap allows you to specify the dimensions you’d like the returned file to fit in, and will even respect the aspect ratio (e.g. it won’t stretch or distort the image to fit the specified sizing).
When the picture has been taken, the success function you passed along will be called, and will contain the raw image data, Base-64 encoded. This is actually pretty ideal because from there you can pop it right into a canvas element for further manipulation, or feed it into an IMG tag as the source.
Device Photo Album
The other button on the user interface allows Mr. Bond the opportunity to select a picture he has already taken. The code is almost identical with the exception of the aforementioned change in source type, and the addition of a media type. The media type option allows you to make sure that, in the heat of a fight with Oddjob or Jaws, James doesn’t accidentally select a video from his photo album.
$( this ).attr( ‘src’, ‘assets/roll.down.png’ );
navigator.camera.getPicture( function( data ) {
$( ‘#photo’ )
.attr( ‘src’, ‘data:image/jpeg;base64,’ + data )
.css( ‘visibility’, ‘visible’ );
$( ‘#roll’ ).attr( ‘src’, ‘assets/roll.up.png’ );
}, function( error ) {
console.log( ‘Error’ );
}, {
destinationType: Camera.DestinationType.DATA_URL,
sourceType: Camera.PictureSourceType.PHOTOLIBRARY,
allowEdit: false,
targetWidth: 260,
targetHeight: 435,
mediaType: Camera.MediaType.PICTURE
} );
} );
Conclusion
Being able to take a picture of something from within an mobile application, is all but considered a given these days. I went to play a new tower defense game on my iPad the other day, and even it wouldn’t let me install without a front-facing camera. While web standards move forward to make that a possibility in the future, PhoneGap is here to help you today. Even if James is otherwise preoccupied chatting with Miss Moneypenny, or getting his groove on with the ever-so-lovely Bond Girls.


I am a father, husband, photography enthusiast and pilot most of the time. I work for Adobe managing the world's best evangelism team the rest of the time. I also enjoy hacking hardware, cigars, travel, and movies.