Button Example

 

   
 
 
 
    
btn_shadow.png btn_body.png btn_highlight.png
<?PHP

error_reporting
(E_ALL E_NOTICE);

/*
btn.php
Outputs a glossy button PNG based on text & color inputs & button state
*/

// set some global parameters where they are easy to change
$font_sz 12;
$font 'luxisr.ttf' // local ttfs were trouble, so use an X11 font 
$text_top // Distance in pixels from top the text should start
$min_cap 32 // The minimum width of text area

// validate the user input
$bg hex2int(validHexColor($_REQUEST['bg'],'ffffff'));
$fg hex2int(validHexColor($_REQUEST['fg'],'000000'));
$string safeString($_REQUEST['string']) ;
// if button is in "down" state, move 2 pixels down & right
$offset = ($_REQUEST['state'] === 'down') ?  :  ;

// open button body image & calculate height & initial width
$btn_body imageCreateFromPNG('btn_body.png');
$btn_ht imagesy($btn_body);
$start_wd imagesx($btn_body);
$cap_wd $start_wd/2;

// Recolor button body based upon user input
// from the number of colors, calculate distance between each color step
$colorSteps imageColorsTotal($btn_body) - 2  // don't count transparency
$step['r'] = ($fg['r'] - $bg['r']) / $colorSteps ;
$step['g'] = ($fg['g'] - $bg['g']) / $colorSteps ;
$step['b'] = ($fg['b'] - $bg['b']) / $colorSteps ;

// for each index in the palette starting with white,
// set color to new calculated value
for ($n=$colorSteps;$n>=0;--$n
    
imageColorSet($btn_body,$n
                    
round(($n $step['r']) + $bg['r']),
                    
round(($n $step['g']) + $bg['g']),
                    
round(($n $step['b']) + $bg['b'])
                    ) ;

// calculate the width of the text block
$tbb imageFTBBox ($font_sz0$font$string, array());
$text_wd $tbb[4] - $tbb[0]; // image width

// use text width to calculate final button width & x,y
$btn_wd $start_wd max(0,$text_wd $min_cap) ;
$x = (($btn_wd $text_wd) / 2) ;
$y $font_sz $text_top ;

// Create final button image & allocate foreground & background
$btn_out imageCreateTrueColor($btn_wd,34);
$bgColor imageColorAllocate($btn_out,$bg['r'],$bg['g'],$bg['b']);
$fgColor imageColorAllocate($btn_out,$fg['r'],$fg['g'],$fg['b']);
imageFill($btn_out,0,0,$bgColor); // this isn't automatic w/ imageCreateTrueColor

// if the button is not in a down state, first draw the shadow beneath all else
if ($offset == 0) {
    
$btn_shadow imageCreateFromPNG('btn_shadow.png');
    
// draw middle of image stretching to accomodate longer text
    
imageCopyResampled ($btn_out$btn_shadow$cap_wd0$cap_wd0$btn_wd-($cap_wd*2), $btn_ht5$btn_ht) ;
    
// copy left & right sides "caps"
    
imageCopy($btn_out$btn_shadow0000$cap_wd$btn_ht) ;
    
imageCopy($btn_out$btn_shadow$btn_wd $cap_wd0$cap_wd0$cap_wd$btn_ht) ;
    
// done with shadow, so destroy it
    
imageDestroy($btn_shadow);
}

// Then add the main body of the recolored button
// draw middle of image stretching to accomodate longer text
imageCopyResampled ($btn_out$btn_body, ($cap_wd $offset), $offset$cap_wd0$btn_wd-($cap_wd*2), $btn_ht5$btn_ht) ;
// copy left & right sides "caps"
imageCopy($btn_out$btn_body$offset$offset00$cap_wd$btn_ht) ;
imageCopy($btn_out$btn_body, ($btn_wd $cap_wd $offset), $offset$cap_wd0$cap_wd$btn_ht) ;
// done with shadow, so destroy it
imageDestroy($btn_body);

// Add the text offset by a pixel colored in the foreground to act as highlight
$tbb imageFTText ($btn_out$font_sz0, ($x+$offset-1), ($y+$offset+1), $fgColor$font"$string", array());

// Next add the highlight layer, whitening anything beneath it
$btn_highlight imageCreateFromPNG('btn_highlight.png');
// draw middle of image stretching to accomodate longer text
imageCopyResampled ($btn_out$btn_highlight, ($cap_wd $offset), $offset$cap_wd0$btn_wd-($cap_wd*2), $btn_ht5$btn_ht) ;
// copy left & right sides "caps"
imageCopy($btn_out$btn_highlight$offset$offset00$cap_wd$btn_ht) ;
imageCopy($btn_out$btn_highlight, ($btn_wd $cap_wd $offset), $offset$cap_wd0$cap_wd$btn_ht) ;
// done with highlight, so destroy it
imageDestroy($btn_highlight);

// Finally add the text again, not offset, in the background color
$tbb imageFTText ($btn_out$font_sz0, ($x+$offset), ($y+$offset), $bgColor$font"$string", array());

// send headers, output & destroy
header("Content-type: image/png");
imagePNG($btn_out);
imageDestroy($btn_out);

/**
 * @param    $hex string        6-digit hexadecimal color
 * @return    array            3 elements 'r', 'g', & 'b' = int color values
 * @desc Converts a 6 digit hexadecimal number into an array of
 *       3 integer values ('r'  => red value, 'g'  => green, 'b'  => blue)
 */
function hex2int($hex) {
        return array(
                    
'r' => hexdec(substr($hex02)), // 1st pair of digits
                    
'g' => hexdec(substr($hex22)), // 2nd pair
                    
'b' => hexdec(substr($hex42))  // 3rd pair
                
);
}

/**
 * @param $input string     6-digit hexadecimal string to be validated
 * @param $default string   default color to be returned if $input isn't valid
 * @return string           the validated 6-digit hexadecimal color
 * @desc returns $input if it is a valid hexadecimal color, 
 *       otherwise returns $default (which defaults to black)
 */
function validHexColor($input '000000'$default '000000') {
    
// A valid Hexadecimal color is exactly 6 characters long
    // and eigher a digit or letter from a to f
    
return (eregi('^[0-9a-f]{6}$'$input)) ? $input $default ;
}

function 
safeString($input) {
    return (isset(
$input))?stripslashes($input):'Button';
}


?>