For the first time this year, WordCamp San Francisco conference badges will include your gravatar. Adding photos to conference badges is nothing new, however bringing your online gravatar into the offline world is a fairly exciting move.

I’d like to share how I created the PHP script to generate the badges. I hope people can re-use the script for future WordCamps, or even any other conferences. If you want to skip the tutorial and just download the script, here it is. I’ve released it under the GNU/GPL 2 license.

Step 1: The FPDF library

The FPDF library is a free to download and use, open source library that will generate PDF files without the need for any specific PHP libraries. The nice thing about it is the documentation is easy to read and has good examples.

Head on over and download the library. You’ll want to create a new directory to store everything in. I called mine “badge-gen” but you can call it whatever you like. Extract the FPDF library into a folder called “fpdf” in the root of your main directory.

Step 2: Create the generation script and include everything we need

Create two new PHP files in the root of your main directory and call one “generate.php” and the other “functions.php”. In the generate.php file we need to require everything we need to set up the environment:

<?php
require('fpdf/fpdf.php'); // require the FPDF library
require('functions.php'); // require the functions we are going to use
?>

Step 3: Add image manipulation and download functions

In the functions.php file, we need to add two image manipulation functions and a function to fetch and download gravatars. The first image function will detect the file extension for an image, and the second will convert PNG files to JPG files. Identicons are PNG files with alpha transparency, unfortunately FPDF does not support alpha enabled PNG images, so we need to convert them to JPG images on the fly. You will need the GD image library installed with PHP on your server.

Add these functions to functions.php:

<?php
function get_file_by_curl( $file, $newfilename ) { 
    $out = fopen( $newfilename, 'wb' );   
    $ch = curl_init(); 
            
    curl_setopt( $ch, CURLOPT_FILE, $out ); 
    curl_setopt( $ch, CURLOPT_HEADER, 0 ); 
    curl_setopt( $ch, CURLOPT_URL, $file ); 
                
    curl_exec( $ch );    
    curl_close( $ch ); 
}

function get_image_extension($filename) {
	$type_mapping =  array( '1' => 'image/gif', '2' => 'image/jpeg', '3' => 'image/png' );
	@$size = GetImageSize( $filename );

	if ( $size[2] && $type_mapping[$size[2]] ) {
		if ( $type_mapping[$size[2]] == 'image/gif' )
		        return '.gif';

		if ( $type_mapping[$size[2]] == 'image/jpeg' )
			return '.jpg';

		if ( $type_mapping[$size[2]] == 'image/png' )
			return '.png';
	}
	return '.jpg';
}

function pngtojpg( $file ) {
	if ( get_image_extension( $file ) == '.png' ) {
		$image = imagecreatefrompng( $file );
		imagejpeg( $image, $file . '.jpg', 80 );
		return $file . '.jpg';
	} else {
		return false;
	}
}
?>

Step 4: Add image download and template directories

We’ll need to make use of a few images for the badges. The entire background on the WordCamp badges is an image. Try and make your images 300dpi, and then scale them down to the size you need in the code. This will ensure that each badge prints in good quality, and doesn’t come out as a pixelated mess.

Store all your images in an “/images” directory in the root of your main folder. This example only includes one static image, the background we just mentioned. You can download the file here.

Due to the way that gravatar image URLs work (they don’t have any sort of file extension and are just a URL with GET variables and an MD5 of your email) we will need to download them before we can add them to badges. This is a limitation of the way images are used in the FPDF library.

Create another directory within your “/images” directory and call it “temp”. You will need to make this directory writable by the server, so either “chmod 777 temp” or use your FTP app to set the permissions. This is where gravatars will be downloaded and stored. If you forget to set the permissions on this folder, you will see a bunch of garbage text on the screen when you try and generate the badges (just a warning).

Finally, create a “/templates” directory in the root of your main folder. In this folder you can store badge page layout templates. For this example we will use a template for Avery Pin Style Name Badges 74549. If you need to use a different template, duplicate this file and make the modifications to the co-ordinates. I’d be happy to create a place to share layout templates if people let me know where to find them.

FPDF treats each PDF page as a canvas, where you set every item’s position using co-ordinates. The co-ordinate values represent millimeters allowing you to measure a normal sheet of paper to get badges positioning perfectly.

In your templates directory, create a new file called “avery74549.php” and add the following code:

<?php
// Add a page, but only on a multiple of 9 (as there are 8 badges per page)
if ( $counter == 1 || ( $counter % 9 == 1 ) ) {
	$pdf->AddPage('P', 'Letter');
	$counter = 1;
}

// Set the co-ordinates for all items in each of the badges
switch ( $counter ) {
	case 1:
		$background_x = 12.5;
		$background_y = 22;
		$avatar_x = 81;
		$avatar_y = 28;
		$text_x = 17.5;
		$text_y = 52;
	break;
	case 2:
		$background_x = 108.5;
		$background_y = 22;
		$avatar_x = 177;
		$avatar_y = 28;
		$text_x = 114;
		$text_y = 52;
	break;
	case 3:
		$background_x = 12.5;
		$background_y = 83;
		$avatar_x = 81;
		$avatar_y = 88;
		$text_x = 17.5;
		$text_y = 113;
	break;
	case 4:
		$background_x = 108.5;
		$background_y = 83;
		$avatar_x = 177;
		$avatar_y = 88;
		$text_x = 114;
		$text_y = 113;
	break;
	case 5:
		$background_x = 12.5;
		$background_y = 144;
		$avatar_x = 81;
		$avatar_y = 150;
		$text_x = 17.5;
		$text_y = 174;			
	break;
	case 6:
		$background_x = 108.5;
		$background_y = 144;
		$avatar_x = 177;
		$avatar_y = 150;
		$text_x = 114;
		$text_y = 174;			
	break;
	case 7:
		$background_x = 12.5;
		$background_y = 205;
		$avatar_x = 81;
		$avatar_y = 211;
		$text_x = 17.5;
		$text_y = 235;			
	break;
	case 8:
		$background_x = 108.5;
		$background_y = 205;
		$avatar_x = 177;
		$avatar_y = 211;
		$text_x = 114;
		$text_y = 235;			
	break;
}
?>

Step 5: The Beef

Now we have the environment set up, we can move on to the actual generation of the badges.

Open up your “generate.php” file, as this is the file we are going to edit from now on. The first step is to instantiate the FPDF class and store it in the object variable “$pdf”. Add the following below the existing code:

// Set up the new PDF object
$pdf = new FPDF();

// Set the text color to white.
$pdf->SetTextColor(255,255,255);

// Remove page margins.
$pdf->SetMargins(0, 0);

// Disable auto page breaks.
$pdf->SetAutoPageBreak(0);

Now we need to retrieve attendee information from somewhere, and load that into an array. You could query a database to retrieve this information, or you could hard code it into the file. You will need the attendees’ first name, last name, email address and optionally their blog URL.

For the sake of this how-to, we will hard code a couple of attendees into an array to use.

// Grab the attendee list
$attendees = array(
   array( 'first_name' => 'John', 'last_name' => 'Smith', 'email' => 'john@smith.com', 'blog' => 'http://john.smith.com' ),
   array( 'first_name' => 'Jane', 'last_name' => 'Doe', 'email' => 'jane@doe.com', 'blog' => 'http://jane.doe.com' ),
   array( 'first_name' => 'Kris', 'last_name' => 'Masters', 'email' => 'kris@masters.com', 'blog' => 'http://kris.masters.com' )
);

Now we have the attendee array set up, we can loop through each one and write each value to a badge in the PDF file:

// Loop through each attendee and create a badge for them
for ( $i = 0; $i < count($attendees); $i++ ) {
		// Grab the template file that will be used for the badge page layout
		require('templates/avery74549.php');

		// Download and store the gravatar for use, FPDF does not support gravatar formatted image links
		$grav_file_raw = 'images/temp/' . $attendees&#91;$i&#93;&#91;'first_name'&#93; . '-' . rand();
		$grav_data = get_file_by_curl( 'http://www.gravatar.com/avatar/' . md5($attendees&#91;$i&#93;&#91;'email'&#93;) . '?s=512&default=identicon', $grav_file_raw );
		
		// Check if the image is a png, if it is, convert it, otherwise add a JPG extension to the raw filename
		if ( !$grav_file = pngtojpg($grav_file_raw) ) {
			$grav_file_extension = get_image_extension($grav_file_raw);
			$grav_file = $grav_file_raw . $grav_file_extension;
			rename( $grav_file_raw, $grav_file );
		}

		// Add the background image for the badge to the page
		$pdf->image('images/back.jpg', $background_x, $background_y, 96, 61);
		$pdf->image($grav_file, $avatar_x, $avatar_y, 21, 21);

		// Set the co-ordinates, font, and text for the first name
		$pdf->SetXY($text_x, $text_y);
		$pdf->SetFont('helvetica','b',33);
		$pdf->MultiCell(86, 13,ucwords(stripslashes($attendees[$i]['first_name'])),0,'R');

		// Set the co-ordinates, font, and text for the last name
		$pdf->SetXY($text_x, $text_y + 11);
		$pdf->SetFont('helvetica','',16);
		$pdf->MultiCell(86, 13,stripslashes(ucwords($attendees[$i]['last_name'])),0,'R');

		// Remove http:// from blog URL's and also remove ending slashes
		$attendees[$i]['blog'] = str_replace('http://', '', $attendees[$i]['blog']);
		
		if ( $attendees[$i]['blog'][strlen($attendees[$i]['blog']) - 1] == '/' )
			$attendees[$i]['blog'][strlen($attendees[$i]['blog']) - 1] = '';

		// Set the co-ordinates, font, and text for the blog url
		$pdf->SetXY($text_x, $text_y + 17);
		$pdf->SetFont('helvetica','',10);
		$pdf->MultiCell(86, 13,$attendees[$i]['blog'],0,'L');
		
		$counter++;
} 

Finally once we have looped through all attendees and added a badge for each, we can output the PDF file to the browser so it can be saved or printed:

// Output the PDF file to the browser
$pdf->Output();

That’s it! You can download the final source files here. Good luck creating gravatar enabled badges. Please ask any questions in the comments, or post links to show off your own conference badges.