Advertisement
  1. Code
  2. Interface Design
Code

Build an Online Photobooth and Stunning 3D Photowall

by
Difficulty:AdvancedLength:LongLanguages:

During this Premium tutorial we will build a online photobooth and a 3d photowall. This application will let you take a photo using your webcam, after which it will be sent to a server where it will be stored in a database. Finally, your photo will be viewable in a 3d photo carousel. We'll cover a wide range of techniques like flash remoting, AMFPHP, mySQL databases, PHP and the Away3D lite engine.


Step 1: Aim

The goal of this tutorial is to give you a few examples of specific techniques and more importantly, how to combine them to great effect.


Step 2: Preparation I

Since this is a client server application we will need a server. This server needs to run an http server, a mysql database server and needs to be equipped with PHP (at least version 5). It sounds like a lot, but most basic web hosting packages will provide you with this. If you don't have a server at your disposal, you could turn your own computer into one, using software packages like xampp. I wont go into the details of setting up such an environment since that's not what this tutorial is about. There are a lot of good tutorials and articles about setting up such a server.

I'll presume you have some basic knowledge about the whole concept of client server, FTP and webhosting.


Step 3: Preparation II

Next, we will need some developing tools. The good ol' days of developing everything in notepad are over... So we need:

  • Flash IDE (CS4)
  • A php/html editor (Aptana)
  • An FTP client (Cyberduck)
  • A decent webbrowser (Firefox)
  • A remoting sniffer for debugging (Charles)

The above-mentioned programs are a personal choice, it's certainly not required to use those specific applications.


Step 4: Setting up the Directory Structure.

For a project like this it's really important to have a solid directory structure. In the end we will have quite a number of files so it's important to have them all in the right place.

We'll use an arrangement based on the structure that is used in 'traditional' software development. This means that we'll have a clear distinction between source files, compiled files, libraries and documents.

In the zip file attached to this tutorial, you'll find 4 folders in the root, doc, bin, lib and src. In the two most important ones, src & bin, you'll find all the files we will be working on. The lib & doc folders contain files we'll need, but don't have to work on. More information about the role of these folders will come along the way.


Step 5: Download AMFPHP

For this application we will need a number of libraries. I'll discuss them one by one, where you can find them and why we need 'em.

First, we'll need AMFPHP. Although the development of AMFPHP has been been a bit slow recently, it's still a very useful package if you want to use flash remoting with PHP. You'll find it at amfphp.org. After downloading it, you should unzip it and copy it to the lib directory.


Step 6: Download AS3CoreLib

At some point we will need to store the image taken by the webcam in the database. Since we don't want to store raw bitmap images, we'll need a JPEG encoder. We could do this using a PHP script but this has 2 disadvantages. First, it will create a lot of network traffic and secondly it's an extra burden for the server if it has to do all these calculations. So we're doing the JPEG encoding on the client side.

Since AS3 doesn't have standard JPEG encoding functionality we'll use an external library called AS3CoreLib. You can find it here. After downloading it, you should copy it to the lib directory.


Step 7: Download Away3d Lite and TweenMax

Finally we'll need two other libraries for the flash applications, namely the Away3d lite library and the TweenMax library. You'll find them here and here. After downloading them, unzip 'em and copy them to the lib directory.

We'll use Away3dLite here because it supports the new 3d functionality of Flash Player 10, resulting in much better performance then Papervision3D.


Step 8: Setup SQL

Now that we have everything we need in the right place, it's time to start doing some work. We will work bottom-up in this project, which means we will first build the backend and then the front end. We'll do this so we have a testing environment for our two flash applications.

First things first; in the zip file you'll find a file called tables.sql.txt in the folder /src/sql. This file contains the sql code you need to set up the database for this project. We'll discuss the sql file in the next step.

Login to your database server, create an account if you don't already have one, and make a note of it. This sounds a lot simpler then it actually is but since this isn't really part of the tutorial I won't discuss it in much detail. If you're clueless about this, I would recommend reading up about this subject.


Step 9: Tables.sql.txt

The sql part of this project is probably the simplest part. We only need 1 table consisting of 3 fields. We'll call this table 'photos' and the fields in it are called 'id', because we need a unique key, 'data', which contains the actual binary data of the photo and 'ip' to log the IP address of the computer where the photo has been taken. The last field is somewhat arbitrary but for security reasons it could be useful.

The more important issue here is the second field, which holds the binary data of the photos. Why not just store the photo on the harddisk of the server and add a reference of the file in the database? Sure we could do this but part of this tutorial is about storing binary data into a database. Besides, this method is a lot 'cleaner' because now we don't have to worry about checks to see if the file really exists or that the reference in the database is correct. There is a lot of discussion on the net weather or not it is a good idea to store files in a database, I think the advantages outweigh the disadvantages in this application.

Most modern SQL clients provide for a way to 'import' sql files into the database, so just import the tables.sql.txt file into the database and you're done!


Step 10: Setup the Backend

Now that the database part is up and running, it's time to prepare the rest of the server. There's not a lot to do here, basically creating a folder on your web server will do. I'll mention it anyway because this directory will be the online equivalent of the 'bin' folder in our project root.

The bin folder contains the actual result of our build, and since it's a website, this folder will be the one that ends up online. You might want to link this folder in your FTP client, since we're going to use it a lot. If you use a XAMPP like setup, you'll want to add this folder to your webroot.


Step 11: Install AMFPHP Unzip

The first step we need to take is to unzip the package we've downloaded and put it into the bin folder. Next, copy the 'services' folder from the 'AMFPHP' folder to the 'bin' folder. This folder is going to hold the actual php scripts we're about to write.


Step 12: Install AMFPHP Configuration

Since we've modified some things within AMFPHP we need to update AMFPHP's configuration file. So open 'bin/amfphp/gateway.php' and navigate to line 123. Here you find the setting that point to the services folder, modify it to '../services'. Now navigate to line 123 and make sure that production server is set to false. If not, you're likely to get the notorious 'Bad Gateway' error in the Flash IDE when you try to access this webservice.

Do a quick test to see if everything is working correctly; upload the bin folder to your server and open http://yourserver/amfphp/browser/ If you're only seeing a blank flex background, right-click, uncheck 'repeat', right-click again and click play. That should do the trick.


Step 13: Setup the PHP Classes

Now that we've put everything into place, it's time to do some coding. As mentioned before we'll work top down, so we'll start with building the PHP classes. Before we start we'll need to make some design decisions. However, since this is a tutorial, I've already made them and now I will explain them.

We are going to divide the services into two classes. The first class will be a base class, which holds the functions and variables that are needed be the various subclasses. The other class will be a subclass of the base class and will hold the actual functions we're going to call from the flash applications.

Although our backend will consist of only two publicly accessible functions, we will use this rather 'big' setup. Why? Because normal web applications are usually a lot bigger then this one and in such situations this setup will be extremely useful.


Step 14: DB.php

The first class we will build is the database class. It's located in 'bin/services/nl/gerbster/utils'. Why? Well, because I use this class very often I've located it in a special utils folder. This way I can use it in many different projects without having to alter it every time I use it. So open it and let's take a look.

The idea behind this class is very simple; set up a connection with a MySQL database, authenticate and if everything goes well, return the link, otherwise return 'false'.


Step 15: PhotoBooth.php

The base class of our backend will be the PhotoBooth(.php) class. The other class, Photo(.php), will extend this class and hold the two functions we're going to call later on from the flash applications.

This class includes 'db.inc.php', which contain some pre defined variables, and the previously discussed 'Db.php' file. The 'PhotoBooth' class functions are nothing more then a wrapper, which contains a reference to the database object, so we can make calls to the database.

Why do this? Well, in this example it's not really useful, however, if you have more then one subclass, it can be very useful to centralize certain functions because of security reasons or maintainability.


Step 16: Photo.php

This class is the class where all the action happens. It holds the two functions we'll call from the two flash applications, 'getPhotos' and 'storePhoto'. The constructor does what all constructors basically do, set variables and initialize stuff. In this case it sets the AMFPHP encoding format to 'amf3'. We will do this on the flash side as well later on. The reason for this is that version 3 of the AMF protocol supports byte arrays, something we're going to make heavy use of.

The two functions in this class are very simple set and get functions. We'll start with the first one, 'getPhotos'. The first thing it does is retrieve the data from the database using a very basic SQL query. Note that we limit the response from the database to 24 records top down, which just means that we only retrieve the 24 last added pictures. Next step is cycling through the records, decoding the information from the database, putting it into a byte array and stacking it into an array. Finally, the array is send to the client.

The other function in this class, 'storePhoto', is basically a reversal of the previous discussed function. It takes a byte array, encodes it, and stores it into the database. If anything goes wrong, it returns an error message, otherwise it just returns true. The only really interesting parts of these functions are the encoding parts. When the data comes in, it is actual binary data, however, MySQL cannot store it in that way, so we'll have to convert it into a form that is accepted by MySQL. And that's where base64 comes in. Base64 is way of encoding binary data to ASCII signs, so it can be stored in a MySQL database. More info about base64 can be found on the net.


Step 17: Testing, Testing

Now that we have concluded the PHP part of this tutorial, it's time to test it. This is very important because we want to make sure that everything works before we start with the front end. So we start with uploading the content to our server and open the service inspector again: http://yourserver/amfphp/browser/ If everything is alright you see something like this:


If you've made a typo or something else went wrong, you will probably get an error report here. Please note that this test only shows if your PHP code is correct. This does certainly not mean that your PHP code is doing exactly what you want it to do! However, this enough for now, once we have the front end up and running we can perform more detailed testing.


Step 18: Setup Frontend

The frontend of this application consist of three parts. First there is the photobooth application, which allows you to take a picture and send it to the server. Next we'll have a photo wall, which retrieves the data from the server and shows it in a 3d carousel. And finally, the third part consists of the html files which holds everything together. We'll deal with these parts in the same order as described above.


Step 19: Building the Photobooth

First, we'll create a new flash file for the photobooth and we'll call it photobooth.fla. Before we can start writing some ActionScript to make it all work, we'll have to adjust some settings and add a instance of the 'record button'. So, first open the Profile settings.


Now click on 'actionscript settings'


We'll define our document class here. It's located in a folder called 'com/photobooth/' and the file is called PhotoBooth.as, so the document class will be 'com.photobooth.PhotoBooth'. Next we need to define the path to the library classes and swc's. We will place them in a different directory, called 'lib', so we will have our project files separate from our library files. Add a directory with the dialog box and navigate to your 'lib' directory.


Now go to the 'Library Path' tab and do the same. After settings the variables it's time to add the 'record button' to the library. Add the record button image to the Library. Now create a new MovieClip, call it RecordBtn and make it available for actionscript. Finally set the size to 300 x 375 px.


Step 20: Class Overview photobooth.as

Since this application isn't really rocket science, the application only has one class. It's called PhotoBooth and, as mentioned earlier, it's located in the directory '/src/flash/com/photobooth'. Copy the code underneath to that file and save it. In the following chapters, we'll discuss the code in more detail.


Step 21: Imports and Class Definition

Beginning at the top, we'll start with the imports. Since this is a more advanced tutorial I'll presume you know a thing or two about ActionScript, so it won't be surprise we import the first 3 items. The next three, concerning 'network' functionality, are used for the remoting part. The three 'text' classes are used for the counter and the two camera classes are imported since we're going to use the webcam. The last of the native flash classes we're importing here are some utility classes, namely the 'ByteArray' and the 'Timer' classes, more on them later.

The 2 external library's we're about to import are the JPEG encoder class and the TweenMax classes. We need them to transform the webcam photo to a JPEG image and to animate some elements.

Finally we'll define the class, it's called PhotoBooth and it extends the MovieClip class. Nothing special there.


Step 22: Setting the Variables

Most programs will have some variables, so will this one. Basically, the variables declared here relate to the classes imported above. There are some variables for the remoting part, the webcam and the visual elements.

The first three concern the remoting part of this program. The first one is especially important, since it holds the location of our amfphp gateway script. Adjust it so it points to your server! The other 2 are dealt with later.

The next two variables are used for the webcam and video object we're going to use later on.

Since this program has some visual elements, we'll need to define them as well. They're not very interesting, and will be mentioned later. Please note the 'btnMC' variable, this is a reference to the MovieClip we created earlier on.

Finally we'll declare the 'bmpd' variable. It's a bitmapData object we're going to use to store the webcam image data when a picture is taken.


Step 23: Constructor and initwebcam

The first function that will be executed is the constructor. Normally a constructor consists of a few simple checks that make sure that all requirements are met, some essential variables are set and finally various 'init' functions are called, which, in turn, will get the program running.

Well, we won't derive from the dogma here, so first we'll check if there's a camera on the system. If not, the program is stalled. Otherwise, the two init functions are called. Of course, this isn't proper usability design; the user should receive a warning if there's no camera. Consider this an extra assignment :)

The initWebcam function will initialize the webcam (no surprises there) and put the image on the screen. Step 1 is to define the size and frame rate of the camera. Next a new Video object is created, the image is flipped to create a mirror effect using the 'flipVideo' function and the webcam object is attached to the Video object. As a final step we'll add it to the stage so everybody can see it.

The 'flipVideo' is a simple matrix based function that 'flips' the video stream. More information about matrix calculations can be found on the net of course.


Step 24: initAssets

Now that we have a webcam image on the screen, it's time to add the rest of the visual elements to the screen. We'll start by drawing the 'flash' box. This is a transparent white rectangle, which will turn white and quickly fade away when a picture is taken. This creates a nice 'flash' effect. We also create a small half transparent rectangle, which will be the background of the 'record' button.

Next, we'll add the 'record' button. As mentioned before this object is linked to the 'RecordBtn' we've added to the library of the .fla file. Since this is still a MovieClip, first thing will do is turn its 'buttonMode' on. This will make it behave like a button. Next, we'll place it on screen correctly and finally add a event listener to it. This event is fired when the object is clicked and it will show the timer.

The third segment of this function will add a textfield to the screen. This textfield is used to show the countdown after the record button is clicked.

The last step of this function will be adding everything to the stage. Remember, in flash, nothing will be visible unless it's added to the stage. First, we add the background, the button and the textfield to a 'container' called 'buttonLayer' and then we add it to stage. We do this because it will be easier later on to hide it all together.

As a last step we'll add the 'buttonLayer' and the flashSprite to the stage.


Step 25: Taking a Photo Mechanism

The flow of the photo mechanism is very easy. After the users clicks on the 'record' button, a timer is shown and the record button is made invisible. When the countdown hits zero a frame from the webcam stream is taken, resized and encoded as a JPEG image.

To add a visual feedback of this process, the flashSprite box animates in .5 seconds from alpha 1 to alpha 0, creating the previously mentioned flash effect. Meanwhile, the JPEG image is sent to the server using the remoting object. Once this process is complete, the 'record' button is made visible again.

The 'showTimer' embodies the first step of the process. It makes the 'record' button invisible, then shows and initializes the timer. The timer is set to 1 second, 1000 milliseconds, and it has to repeat itself 3 times. We also add two event listeners. One that fires if a 'cycle' is ready, on which it will lower the count using the 'doCountDown' function. The other one fires when the Timer is done completely and it will call the 'makeSnapShot' function.

The 'makeSnapShot' function will make the 'record' button visible again; make the countdown text field invisible and show the 'photo flash' effect. More importantly, it takes a frame from the webcam video stream, scales it down, encodes it to a JPEG image after which it is handed over to the 'sendByteArrayToServer' function.


Step 26: Remoting Call

Although this is a key part of the whole tutorial, the code handling the remoting call only consists of 5 lines. The call is done by the 'sendByteArrayToServer' function. Firstly, a 'Responder' object is created. This object handles the response we get back after a call is made to our AMFPHP gateway.

Next, we'll create the 'NetConnection' object. This object makes the actual connection to our AMFPHP gateway. We define the format of the data we're sending and finally we connect to the gateway using the 'gateway' variable, which we declared earlier on.

Now that we're connected, it's time to make the call. We'll call the function 'com.photobooth.Photo.storePhoto' and send the byte array holding our picture. The second argument of the call functions holds a reference to the responder object, so the connection object knows who to call when the response comes back.

Since we've defined the responder object we'll need two functions called 'onResult' and 'onFault'. These functions will be called when the response comes back from the server. However, we're not using them here. If you want, you could build in some functionality that provides some feedback to the user about the status of the call.


Step 27: Compile and Test

Now that everything is in place it's time to compile and test this part of the application. Since we've already built the backend of this application we can check if the photos are stored correctly as well. So hit the command-enter combination and see if it works. If everything is in the right order, you'll see something like this:



Step 28: PhotoWall Intro

The initial steps of building the photo wall are basically the same as the ones taken for the photo booth. We'll go over them briefly. First, create a new .fla file and call it 'PhotoWall.fla'. Next, add the library paths and define the document class to 'com.photobooth.PhotoWall'. Finally set the size to 800 X 600 px.

The photobooth application was small enough to fit all the code into a single class, however, the photo wall isn't. We'll divide the functionality into two classes this time. The first class will deal with retrieving the data from our server, the other one will deal with the visual representation of the data. This concept, dividing your code in a data handling part and a visual representation part, is proven to be very useful and is also the basis of the MVC design principle.

The PhotoWall class does nothing more then call the AMFPHP gateway, retrieve the photos and pass them over to the Wall3d class.


Step 29: PhotoWall Imports and Variables

The imports of this class are roughly the same as the imports of the PhotoBooth class. However, we only need the imports concerned with networking, the byte array and the wall3d class, which we're going to build later on.

The variables used in this class are all used for the remoting call, with the exception of wall3d, which is used for holding an instance of the 3d wall we're about to build.


Step 30: PhotoWall Constructor and Remoting Call

As mentioned before, constructors are mainly used to set variables and initialize stuff. Well, nothing new here. After setting some variables concerning scaling and alignment, the function 'getPhotosFromServer' is called. This function is responsible for calling the AMFPHP gateway and retrieving the array with photos. We won't discuss this in much detail since we've already done this with the PhotoBooth class.


Step 31: Data Handling

The more interesting part of this class is the data handling part. When the result comes back from the server it is passed on to the 'onResult' function. The first thing this function does is set the totalResults variable to the total length of the array with photos. Next, it will cycle through the array and convert every byte array into a bitmap data object using the 'Loader' class.

This 'Loader' class needs an event listener so that's why there is a 'bytesComplete' function. This function creates a BitmapData object and pushes it into the 'photos' array. If the length of the 'photos' array is equal to the value of the 'totalResults' variable, a new instance of Wall3d is created and added to the stage.


Step 32: Wall3D intro

This will be the last ActionScript class we're building for this tutorial and it is a somewhat special one. As mentioned before, this class will show a three dimensional carousel of all the pictures. The reason we're doing this in 3d is to show why it is a good idea to separate the data handling part of an application from the presentation part. It is also a good case to demonstrate the Away 3d lite library.

So, how does this work? Well, in short, we're going to create a 3d environment, place the photos in such a way that they appear to be a carousel. For this we're going to use some basic mathematics. We're also adding some mouse listeners to add some interactivity.


Step 33: Imports and Variables

The imports for this class are a bit different then the other classes. Since we only need some basic flash functionality like display and event utilities we'll import the following classes:

The following imports are all away3dlite related. As you will notice they all relate to some part of the 3d environment we're about to build. We need a camera, a scene, a viewport and primitives with their materials.

The variables we're using in this class are all related to the 3d environment we're about to build. The first three are basic objects we need to build the 3d environment; namely a camera, a scene and a viewport.

The next 7 variables are all related to the movement and interactivity of the carousel. We'll discuss them in more detail later on.

Before we can animate or click anything at all, we'll need to build the carousel. We're going to do that using some basic mathematics and the following 3 variables are used for that reason.

The final variable is a holder for the array with photos.


Step 34: Constructor, Background

Nothing new here, first we'll store the photo array in a local variable, after which some initialization functions are called. The init functions are divided into one for building the background, one to build the 3d engine and one to add event listeners. Finally a function is called to build the photo carousel.

We'll discuss all these functions, with the exception of the background function, in more detail later on.

We could have used the paint bucket from the flash IDE to create a gradient background, but instead we're doing it with a few lines of code. It's a straightforward piece of code you can re-use in all kinds projects; it uses a matrix to create a gradient pattern which is then used by the graphics library to draw the correct gradient.


Step 35: Setup 3d Environment

Setting up the away 3d lite engine is not very different then setting up other 3d engines. The three major components, the scene, camera and viewport are initialized and added to the stage.

We'll be using the hover camera for this setting since we'll be moving the camera around later on. Also notice the little 'hack' to improve the frame rate. Normally these kinds of tricks are to be incorporated into the 3d library, but since that hasn't been done yet, we'll leave it here.


Step 36: Building the Photo Carousel

The carousel we're about to build consists of a number of double sided planes. A plane is a 3d primitive in the form of a rectangle. The function is rather simple, it cycles through the photos array, creates a plane for every photo and adds them to the 3d scene. Every plane is placed 20 pixels further away, this is necessary to create a spiral effect. Otherwise the photos would overlap each other.


Step 37: Movement and Event Listeners

Now that the photos are placed into the 3d scene we add some movement and interactivity. What we want is the spiral to rotate continuously, if the user clicks the movement should stop and the user should be able to drag the carousel around with a small easing effect.

So, first thing we're going to do is add some event listeners. The first one is the good old 'onEnterFrame' event, which calls the 'onEnterFrame' function. This function handles all movement and will be the first we'll discuss.

The rotation of the planes is realized by moving the planes in the 3d environment; the dragging is realized by moving the camera around. We use a Boolean variable called 'drag' to determine if the mouse button is down. If so, we'll use the mouse coordinates to calculate the new position of the camera. We also store the last known position of the camera and use that value to create an easing effect.

Next, we'll use the Pythagorean theorem to place all the planes in a spiral form. We use the 'angle', 'angleOffset' and the 'diameter' variables to do this. Every time this function is called, the angle is incremented so the next time the planes are positioned they appear to be rotated a bit. This creates a circular motion.

Finally, we'll tell the camera to move, if necessary, and the viewport to render the scene.


Step 38: Round up and Test

The last thing left now is to test the application. If you want, you can adjust the variables like 'angleOffset' and 'diameter' to change to looks of the carousel, but ultimately it should look like this:



Step 39: HTML Setup

Now that we have everything in place, compiled and tested, it's time to build the HTML files we're going to place on the server. We're going to build 3 html files, one index file, a booth.html file, which holds the photo booth application and a third html file, which holds the photo wall called wall.html. All files will make use of CSS and JavaScript.


Step 40: booth.html

We're using the javascript utility 'swfobject' here to embed the flash application into the booth.html. There are various scripts and methods around to embed flash into an html file and there is no specific reason for using 'swfobject' here. However, it is a good script that can be used on various projects.

Since this tutorial is about flash and PHP we won't discuss this subject into to much detail. However, if you're interested in swfobject and the combination flash/html, please check the web.


Step 41: wall.html

The wall.html is basically the same as the booth.html file. It uses 'swfobject' to embed the flash application into the page.


Step 42: Upload

The final step we have to take before we can test this project is to upload all files to your server. We've discussed the setup of our project folder in one of the first steps of this tutorial, and now you'll see why this 'bin' directory is useful. The only thing you need to upload is the contents of the 'bin' folder, no need for searching files or excluding source files. Again, in a project of this size it may not be absolutely necessary, but believe me, if your projects are getting bigger and bigger, you'll appreciate this setup.

Although this is no rocket science, there are a few things you need to keep in mind. First of all, make sure the all html and php files are world readable. Next, check if all paths are correct, in the html as well as in the flash applications.


Step 43: Final Test

Now that everything is done and at its place it's time for the all-important final tests. Of course we've done some testing along the way but a simple error in the html or PHP can still cripple the whole application. So make sure that you can take a picture in the photo booth and that it shows up in the photo wall. A very useful application to test and debug remoting calls is 'Charles'. It allows you to view and debug all traffic between the client and server to find out if there are any 'hidden' problems.



Step 44: Result

If everything is done correctly it should like this:



Thanks for following along!

Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.