Skip to content

Instantly share code, notes, and snippets.

@ViskoB
Last active December 18, 2015 02:09
Show Gist options
  • Save ViskoB/9d03a0cd4967828ac6cc to your computer and use it in GitHub Desktop.
Save ViskoB/9d03a0cd4967828ac6cc to your computer and use it in GitHub Desktop.
An attempt to colour Guild Wars 2 guild emblems using PHP and the GD library
<?php
/* Guild Wars 2 Emblem Creator Script by Moturdrn.2837
Special thanks to:
- Cliff Spradlin and ArenaNet for making available the API and information
- smiley.1438 and Think.8042 with PHP colour conversion
- smiley.1438 for the gw2_api_request function
- Dr Ishmael.9685 for providing information and downloads of the emblem parts and backgrounds, and the idea to split the matrix and colour conversion functions
- Killer Rhino.6794 for the extra advanced information on working out how to decode the API colour information into something useable
- The general Guild Wars 2 development community for being a bunch of guys and gals ready and willing to help one another out
- Apologies if I've left you out, please contact me and I'll add you in here :)
Please feel free to use this code and make modifications. Apologies in advance if the coding seems all over the place.*/
$pathToBackgrounds = './backgrounds/';
$pathToEmblems = './emblems/';
$pathToGenerated = './generated/';
if(isset($_GET['guild_id'])){
$guild_id = $_GET['guild_id'];
$guildInfo = gw2_api_request("guild_details.json?guild_id={$guild_id}");
if(!$guildInfo)
displayUnknown();
}elseif(isset($_GET['guild_name'])){
$guild_name = $_GET['guild_name'];
$guild_name = str_replace(' ', '%20', $guild_name);
$guildInfo = gw2_api_request("guild_details.json?guild_name={$guild_name}");
if(!$guildInfo)
displayUnknown();
}else{
displayUnknown();
}
if(!$guildInfo['emblem'])
displayUnknown();
$background_id = $guildInfo['emblem']['background_id'];
$foreground_id = $guildInfo['emblem']['foreground_id'];
$background_color_id = $guildInfo['emblem']['background_color_id'];
$foreground_primary_color_id = $guildInfo['emblem']['foreground_primary_color_id'];
$foreground_secondary_color_id = $guildInfo['emblem']['foreground_secondary_color_id'];
$flags = $guildInfo['emblem']['flags'];
$hash = array($background_id,$foreground_id,$background_color_id,$foreground_primary_color_id,$foreground_secondary_color_id,serialize($flags));
$hash = hash('sha256', serialize($hash));
$generatedFile = "{$pathToGenerated}{$hash}.png";
if(file_exists($generatedFile)){
try
{
$image = imagecreatefrompng($generatedFile);
header("Content-Type: image/png");
imagealphablending($image, true);
imagesavealpha($image, true);
imagepng($image);
imagedestroy($image);
}
catch(Exception $e)
{
echo $e->getMessage();
}
exit();
}
$colorsArray = gw2_api_request('colors.json');
if(!$colorsArray)
displayUnknown();
$colorsArray = $colorsArray['colors'];
$background = $colorsArray[$background_color_id]['cloth'];
$primary = $colorsArray[$foreground_primary_color_id]['cloth'];
$secondary = $colorsArray[$foreground_secondary_color_id]['cloth'];
$background_path = "{$pathToBackgrounds}{$background_id}.png";
$primary_path = "{$pathToEmblems}{$foreground_id}a.png";
$secondary_path = "{$pathToEmblems}{$foreground_id}b.png";
header('Content-type: image/png');
// Fetch the background image
$imagebk = imagecreatefrompng($background_path);
// Apply transparency information for the background - PHP GD Base image issue
$backgroundCol = imagecolorallocate($imagebk, 255,255,255);
imagecolortransparent($imagebk, $backgroundCol);
imagealphablending($imagebk, true);
imagesavealpha($imagebk, true);
// Re-colour background image
imagehue($imagebk, $background);
imagefilter($imagebk, IMG_FILTER_CONTRAST, $background['contrast']);
imagefilter($imagebk, IMG_FILTER_COLORIZE, $background['rgb'][0], $background['rgb'][1],$background['rgb'][2]);
// Fetch the primary emblem image
$image1 = imagecreatefrompng($primary_path);
// Re-colour primary emblem image
imagehue($image1, $primary);
// Fetch the secondary emblem image
$image2 = imagecreatefrompng($secondary_path);
// Re-colour secondary emblem image
imagehue($image2, $secondary);
// Combine the primary and secondary emblem image
imagecopy($image1, $image2, 0, 0, 0, 0, 256, 256);
foreach($flags as $flag){
switch($flag){
case 'FlipBackgroundHorizontal':
$imagebk = image_flip($imagebk,'horiz');
break;
case 'FlipBackgroundVertical':
$imagebk = image_flip($imagebk,'vert');
break;
case 'FlipForegroundHorizontal':
$image1 = image_flip($image1,'horiz');
break;
case 'FlipForegroundVertical':
$image1 = image_flip($image1,'vert');
break;
}
}
// Combine the emblem and background
imagecopy($imagebk, $image1, 0, 0, 0, 0, 256, 256);
// Output the completed image
imagepng($imagebk,$generatedFile);
imagepng($imagebk);
// Clean-up
imagedestroy($imagebk);
imagedestroy($image1);
imagedestroy($image2);
function imagehue(&$image, $color) {
$width = imagesx($image);
$height = imagesy($image);
$matrix = getColorMatrix($color);
for($x = 0; $x < $width; $x++) {
for($y = 0; $y < $height; $y++) {
$colorIndex = imagecolorat($image, $x, $y);
$colorTran = imagecolorsforindex($image, $colorIndex);
$r = $colorTran['red'];
$g = $colorTran['green'];
$b = $colorTran['blue'];
$alpha = $colorTran['alpha'];
if($alpha<127){
$rgb = array($r,$g,$b);
$rgb = applyColorTransform($matrix, $rgb);
imagesetpixel($image, $x, $y, imagecolorallocatealpha($image, $rgb[0], $rgb[1], $rgb[2], $colorTran['alpha']));
}
}
}
}
function image_flip($img, $type=''){
$width = imagesx($img);
$height = imagesy($img);
$dest = imagecreatetruecolor($width, $height);
imagesavealpha($dest, true);
$trans_colour = imagecolorallocatealpha($dest, 0, 0, 0, 127);
imagefill($dest, 0, 0, $trans_colour);
switch($type){
case 'vert':
for($i=0;$i<$height;$i++){
imagecopy($dest, $img, 0, ($height - $i - 1), 0, $i, $width, 1);
}
break;
case 'horiz':
for($i=0;$i<$width;$i++){
imagecopy($dest, $img, ($width - $i - 1), 0, $i, 0, 1, $height);
}
break;
default:
return $img;
}
return $dest;
}
// Function matrix_multiply by smiley: https://gist.github.com/codemasher/b869faa7603e1934c28d
function matrix_multiply($m1, $m2){
$r = count($m1);
$c = count($m2[0]);
$p = count($m2);
if(count($m1[0]) != $p){
return false; //incompatible matrix
}
$m3 = array();
for($i = 0; $i < $r; $i++){
for($j = 0; $j < $c; $j++){
$m3[$i][$j] = 0;
for($k = 0; $k < $p; $k++){
$m3[$i][$j] += $m1[$i][$k]*$m2[$k][$j];
}
}
}
return ($m3);
}
// Function getColorMatrix adapted from smiley's code: https://gist.github.com/codemasher/b869faa7603e1934c28d
function getColorMatrix($hslbc){
//colors from the response .json -> material
$h = ($hslbc['hue']*pi())/180;
$s = $hslbc['saturation'];
$l = $hslbc['lightness'];
$b = $hslbc['brightness']/128;
$c = $hslbc['contrast'];
// 4x4 identity matrix
$matrix = array(
array(1, 0, 0, 0),
array(0, 1, 0, 0),
array(0, 0, 1, 0),
array(0, 0, 0, 1)
);
if($b != 0 || $c != 1){
// process brightness and contrast
$t = 128*(2*$b+1-$c);
$mult = array(
array($c, 0, 0, $t),
array( 0, $c, 0, $t),
array( 0, 0, $c, $t),
array( 0, 0, 0, 1)
);
$matrix = matrix_multiply($mult, $matrix);
}
if($h != 0 || $s != 1 || $l != 1){
// transform to HSL
$multRgbToHsl = array(
array( 0.707107, 0, -0.707107, 0),
array(-0.408248, 0.816497, -0.408248, 0),
array( 0.577350, 0.577350, 0.577350, 0),
array( 0, 0, 0, 1)
);
$matrix = matrix_multiply($multRgbToHsl, $matrix);
// process adjustments
$cosHue = cos($h);
$sinHue = sin($h);
$mult = array(
array( $cosHue * $s, $sinHue * $s, 0, 0),
array(-$sinHue * $s, $cosHue * $s, 0, 0),
array( 0, 0, $l, 0),
array( 0, 0, 0, 1)
);
$matrix = matrix_multiply($mult, $matrix);
// transform back to RGB
$multHslToRgb = array(
array( 0.707107, -0.408248, 0.577350, 0),
array( 0, 0.816497, 0.577350, 0),
array(-0.707107, -0.408248, 0.577350, 0),
array( 0, 0, 0, 1)
);
$matrix = matrix_multiply($multHslToRgb, $matrix);
}
return $matrix;
}
// Function applyColorTransform adapted from smiley's code: https://gist.github.com/codemasher/b869faa7603e1934c28d
function applyColorTransform($matrix, $base){
// apply the color transformation
$bgrVector = array(
array($base[2]),
array($base[1]),
array($base[0]),
array(1)
);
$bgrVector = matrix_multiply($matrix,$bgrVector);
// clamp the values
$rgb = array(
floor(max(0, min(255, $bgrVector[2][0]))),
floor(max(0, min(255, $bgrVector[1][0]))),
floor(max(0, min(255, $bgrVector[0][0])))
);
return $rgb;
}
// Function gw2_api_request from https://gist.github.com/codemasher/4d30a47df24195ac509f
function gw2_api_request($request){
$url = parse_url('https://api.guildwars2.com/v1/'.$request);
if(!$fp = @fsockopen('ssl://'.$url['host'], 443, $errno, $errstr, 5)){
return 'connection error: '.$errno.', '.$errstr;
}
$nl = "\r\n";
$header = 'GET '.$url['path'].'?'.$url['query'].' HTTP/1.1'.$nl.'Host: '.$url['host'].$nl.'Connection: Close'.$nl.$nl;
fwrite($fp, $header);
stream_set_timeout($fp, 5);
$response = '';
do{
if(strlen($in = fread($fp,1024))==0){
break;
}
$response.= $in;
}
while(true);
$response = explode($nl,$response);
if(isset($response[0]) && $response[0] == 'HTTP/1.1 200 OK'){
$response = json_decode($response[count($response)-1],true);
}
return $response;
}
function displayUnknown(){
global $pathToEmblems;
header('Content-type: image/png');
// Fetch the background image
$image = imagecreatefrompng("{$pathToEmblems}unknown_guild.png");
imagealphablending($image, true);
imagesavealpha($image, true);
imagepng($image);
imagedestroy($image);
exit();
}
?>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment