<?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 = 8 ; // 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') ? 2 : 0 ;
// 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_sz, 0, $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_wd, 0, $cap_wd, 0, $btn_wd-($cap_wd*2), $btn_ht, 5, $btn_ht) ; // copy left & right sides "caps" imageCopy($btn_out, $btn_shadow, 0, 0, 0, 0, $cap_wd, $btn_ht) ; imageCopy($btn_out, $btn_shadow, $btn_wd - $cap_wd, 0, $cap_wd, 0, $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_wd, 0, $btn_wd-($cap_wd*2), $btn_ht, 5, $btn_ht) ; // copy left & right sides "caps" imageCopy($btn_out, $btn_body, $offset, $offset, 0, 0, $cap_wd, $btn_ht) ; imageCopy($btn_out, $btn_body, ($btn_wd - $cap_wd + $offset), $offset, $cap_wd, 0, $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_sz, 0, ($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_wd, 0, $btn_wd-($cap_wd*2), $btn_ht, 5, $btn_ht) ; // copy left & right sides "caps" imageCopy($btn_out, $btn_highlight, $offset, $offset, 0, 0, $cap_wd, $btn_ht) ; imageCopy($btn_out, $btn_highlight, ($btn_wd - $cap_wd + $offset), $offset, $cap_wd, 0, $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_sz, 0, ($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($hex, 0, 2)), // 1st pair of digits 'g' => hexdec(substr($hex, 2, 2)), // 2nd pair 'b' => hexdec(substr($hex, 4, 2)) // 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'; }
?>
|