Skip to content

Instantly share code, notes, and snippets.

@yunnysunny
Created January 31, 2018 07:27
Show Gist options
  • Select an option

  • Save yunnysunny/2422b7369f7653b5a3a6edc4877414d8 to your computer and use it in GitHub Desktop.

Select an option

Save yunnysunny/2422b7369f7653b5a3a6edc4877414d8 to your computer and use it in GitHub Desktop.

Revisions

  1. yunnysunny created this gist Jan 31, 2018.
    274 changes: 274 additions & 0 deletions rand_avatar.php
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,274 @@
    <?php
    /**
    * 随机头像生成
    * 生成算法来自Github,具体出处找不到了,做了少量修改
    * @author loveyu
    */

    /**
    * 头像HASH值
    */
    define("AVATAR_HASH", (isset($_GET['hash']) && !empty($_GET['hash'])) ? md5($_GET['hash']) : md5(rand(0, 1000000)));

    /**
    * 头像大小
    */
    define("AVATAR_SIZE", (isset($_GET['size']) && $_GET['size'] > 10) ? $_GET['size'] : 100);

    /**
    * generate sprite for corners and sides
    * @param $shape
    * @param $R
    * @param $G
    * @param $B
    * @param $rotation
    * @return resource
    */
    function getsprite($shape, $R, $G, $B, $rotation){
    global $spriteZ;
    $sprite = imagecreatetruecolor($spriteZ, $spriteZ);
    imageantialias($sprite, true);
    $fg = imagecolorallocate($sprite, $R, $G, $B);
    $bg = imagecolorallocate($sprite, 255, 255, 255);
    imagefilledrectangle($sprite, 0, 0, $spriteZ, $spriteZ, $bg);
    switch($shape){
    case 0: // triangle
    $shape = array(0.5, 1, 1, 0, 1, 1);
    break;
    case 1: // parallelogram
    $shape = array(0.5, 0, 1, 0, 0.5, 1, 0, 1);
    break;
    case 2: // mouse ears
    $shape = array(0.5, 0, 1, 0, 1, 1, 0.5, 1, 1, 0.5);
    break;
    case 3: // ribbon
    $shape = array(0, 0.5, 0.5, 0, 1, 0.5, 0.5, 1, 0.5, 0.5);
    break;
    case 4: // sails
    $shape = array(0, 0.5, 1, 0, 1, 1, 0, 1, 1, 0.5);
    break;
    case 5: // fins
    $shape = array(1, 0, 1, 1, 0.5, 1, 1, 0.5, 0.5, 0.5);
    break;
    case 6: // beak
    $shape = array(0, 0, 1, 0, 1, 0.5, 0, 0, 0.5, 1, 0, 1);
    break;
    case 7: // chevron
    $shape = array(0, 0, 0.5, 0, 1, 0.5, 0.5, 1, 0, 1, 0.5, 0.5);
    break;
    case 8: // fish
    $shape = array(0.5, 0, 0.5, 0.5, 1, 0.5, 1, 1, 0.5, 1, 0.5, 0.5, 0, 0.5);
    break;
    case 9: // kite
    $shape = array(0, 0, 1, 0, 0.5, 0.5, 1, 0.5, 0.5, 1, 0.5, 0.5, 0, 1);
    break;
    case 10: // trough
    $shape = array(0, 0.5, 0.5, 1, 1, 0.5, 0.5, 0, 1, 0, 1, 1, 0, 1);
    break;
    case 11: // rays
    $shape = array(0.5, 0, 1, 0, 1, 1, 0.5, 1, 1, 0.75, 0.5, 0.5, 1, 0.25);
    break;
    case 12: // double rhombus
    $shape = array(0, 0.5, 0.5, 0, 0.5, 0.5, 1, 0, 1, 0.5, 0.5, 1, 0.5, 0.5, 0, 1);
    break;
    case 13: // crown
    $shape = array(0, 0, 1, 0, 1, 1, 0, 1, 1, 0.5, 0.5, 0.25, 0.5, 0.75, 0, 0.5, 0.5, 0.25);
    break;
    case 14: // radioactive
    $shape = array(0, 0.5, 0.5, 0.5, 0.5, 0, 1, 0, 0.5, 0.5, 1, 0.5, 0.5, 1, 0.5, 0.5, 0, 1);
    break;
    default: // tiles
    $shape = array(0, 0, 1, 0, 0.5, 0.5, 0.5, 0, 0, 0.5, 1, 0.5, 0.5, 1, 0.5, 0.5, 0, 1);
    break;
    }
    /* apply ratios */
    for($i = 0; $i < count($shape); $i++){
    $shape[$i] = $shape[$i] * $spriteZ;
    }
    imagefilledpolygon($sprite, $shape, count($shape) / 2, $fg);
    /* rotate the sprite */
    for($i = 0; $i < $rotation; $i++){
    $sprite = imagerotate($sprite, 90, $bg);
    }
    return $sprite;
    }

    /**
    * generate sprite for center block
    * @param $shape
    * @param $fR
    * @param $fG
    * @param $fB
    * @param $bR
    * @param $bG
    * @param $bB
    * @param $usebg
    * @return resource
    */
    function getcenter($shape, $fR, $fG, $fB, $bR, $bG, $bB, $usebg){
    global $spriteZ;
    $sprite = imagecreatetruecolor($spriteZ, $spriteZ);
    imageantialias($sprite, true);
    $fg = imagecolorallocate($sprite, $fR, $fG, $fB);
    /* make sure there's enough contrast before we use background color of side sprite */
    if($usebg > 0 && (abs($fR - $bR) > 127 || abs($fG - $bG) > 127 || abs($fB - $bB) > 127)){
    $bg = imagecolorallocate($sprite, $bR, $bG, $bB);
    } else{
    $bg = imagecolorallocate($sprite, 255, 255, 255);
    }
    imagefilledrectangle($sprite, 0, 0, $spriteZ, $spriteZ, $bg);
    switch($shape){
    case 0: // empty
    $shape = array();
    break;
    case 1: // fill
    $shape = array(0, 0, 1, 0, 1, 1, 0, 1);
    break;
    case 2: // diamond
    $shape = array(0.5, 0, 1, 0.5, 0.5, 1, 0, 0.5);
    break;
    case 3: // reverse diamond
    $shape = array(0, 0, 1, 0, 1, 1, 0, 1, 0, 0.5, 0.5, 1, 1, 0.5, 0.5, 0, 0, 0.5);
    break;
    case 4: // cross
    $shape = array(0.25, 0, 0.75, 0, 0.5, 0.5, 1, 0.25, 1, 0.75, 0.5, 0.5, 0.75, 1, 0.25, 1, 0.5, 0.5, 0, 0.75, 0, 0.25, 0.5, 0.5);
    break;
    case 5: // morning star
    $shape = array(0, 0, 0.5, 0.25, 1, 0, 0.75, 0.5, 1, 1, 0.5, 0.75, 0, 1, 0.25, 0.5);
    break;
    case 6: // small square
    $shape = array(0.33, 0.33, 0.67, 0.33, 0.67, 0.67, 0.33, 0.67);
    break;
    case 7: // checkerboard
    $shape = array(0, 0, 0.33, 0, 0.33, 0.33, 0.66, 0.33, 0.67, 0, 1, 0, 1, 0.33, 0.67, 0.33, 0.67, 0.67, 1, 0.67, 1, 1, 0.67, 1, 0.67, 0.67,
    0.33, 0.67, 0.33, 1, 0, 1, 0, 0.67, 0.33, 0.67, 0.33, 0.33, 0, 0.33);
    break;
    }
    /* apply ratios */
    for($i = 0; $i < count($shape); $i++){
    $shape[$i] = $shape[$i] * $spriteZ;
    }
    if(count($shape) > 0){
    imagefilledpolygon($sprite, $shape, count($shape) / 2, $fg);
    }
    return $sprite;
    }

    /**
    * 调整颜色
    * @param $r
    * @param $g
    * @param $b
    */
    function fix_rgb(&$r, &$g, &$b){
    if($r==0){
    $r = 10;
    }
    if($g==0){
    $g = 10;
    }
    if($b ==0){
    $b = 10;
    }
    while($r < 210){
    $r *= 1.3;
    }
    while($g < 100){
    $g *= 1.3;
    }
    while($b < 180){
    $b *= 1.3;
    }
    if($r > 255){
    $r = 511 - $r;
    }
    if($g > 255){
    $g = 511 - $g;
    }
    if($b > 255){
    $b = 511 - $b;
    }
    }


    $csh = hexdec(substr(AVATAR_HASH, 0, 1)); // corner sprite shape
    $ssh = hexdec(substr(AVATAR_HASH, 1, 1)); // side sprite shape
    $xsh = hexdec(substr(AVATAR_HASH, 2, 1)) & 7; // center sprite shape

    $cro = hexdec(substr(AVATAR_HASH, 3, 1)) & 3; // corner sprite rotation
    $sro = hexdec(substr(AVATAR_HASH, 4, 1)) & 3; // side sprite rotation
    $xbg = hexdec(substr(AVATAR_HASH, 5, 1)) % 2; // center sprite background

    /* corner sprite foreground color */
    $cfr = hexdec(substr(AVATAR_HASH, 6, 2));
    $cfg = hexdec(substr(AVATAR_HASH, 8, 2));
    $cfb = hexdec(substr(AVATAR_HASH, 10, 2));
    fix_rgb($cfr, $cfg, $cfb);

    /* side sprite foreground color */
    $sfr = hexdec(substr(AVATAR_HASH, 12, 2));
    $sfg = hexdec(substr(AVATAR_HASH, 14, 2));
    $sfb = hexdec(substr(AVATAR_HASH, 16, 2));
    fix_rgb($sfr, $sfg, $sfb);

    /* final angle of rotation */
    $angle = hexdec(substr(AVATAR_HASH, 18, 2));


    /* size of each sprite */
    $spriteZ = 128;

    /* start with blank 3x3 identicon */
    $identicon = imagecreatetruecolor($spriteZ * 3, $spriteZ * 3);
    imageantialias($identicon, true);

    /* assign white as background */
    $bg = imagecolorallocate($identicon, 255, 255, 255);
    imagefilledrectangle($identicon, 0, 0, $spriteZ, $spriteZ, $bg);

    /* generate corner sprites */
    $corner = getsprite($csh, $cfr, $cfg, $cfb, $cro);
    imagecopy($identicon, $corner, 0, 0, 0, 0, $spriteZ, $spriteZ);
    $corner = imagerotate($corner, 90, $bg);
    imagecopy($identicon, $corner, 0, $spriteZ * 2, 0, 0, $spriteZ, $spriteZ);
    $corner = imagerotate($corner, 90, $bg);
    imagecopy($identicon, $corner, $spriteZ * 2, $spriteZ * 2, 0, 0, $spriteZ, $spriteZ);
    $corner = imagerotate($corner, 90, $bg);
    imagecopy($identicon, $corner, $spriteZ * 2, 0, 0, 0, $spriteZ, $spriteZ);

    /* generate side sprites */
    $side = getsprite($ssh, $sfr, $sfg, $sfb, $sro);
    imagecopy($identicon, $side, $spriteZ, 0, 0, 0, $spriteZ, $spriteZ);
    $side = imagerotate($side, 90, $bg);
    imagecopy($identicon, $side, 0, $spriteZ, 0, 0, $spriteZ, $spriteZ);
    $side = imagerotate($side, 90, $bg);
    imagecopy($identicon, $side, $spriteZ, $spriteZ * 2, 0, 0, $spriteZ, $spriteZ);
    $side = imagerotate($side, 90, $bg);
    imagecopy($identicon, $side, $spriteZ * 2, $spriteZ, 0, 0, $spriteZ, $spriteZ);

    /* generate center sprite */
    $center = getcenter($xsh, $cfr, $cfg, $cfb, $sfr, $sfg, $sfb, $xbg);
    imagecopy($identicon, $center, $spriteZ, $spriteZ, 0, 0, $spriteZ, $spriteZ);

    // $identicon=imagerotate($identicon,$angle,$bg);

    /* make white transparent */
    imagecolortransparent($identicon, $bg);

    /* create blank image according to specified dimensions */
    $resized = imagecreatetruecolor(AVATAR_SIZE, AVATAR_SIZE);
    imageantialias($resized, true);

    /* assign white as background */
    $bg = imagecolorallocate($resized, 255, 255, 255);
    imagefilledrectangle($resized, 0, 0, AVATAR_SIZE, AVATAR_SIZE, $bg);

    /* resize identicon according to specification */
    imagecopyresampled($resized, $identicon, 0, 0, (imagesx($identicon) - $spriteZ * 3) / 2, (imagesx($identicon) - $spriteZ * 3) / 2, AVATAR_SIZE, AVATAR_SIZE, $spriteZ * 3, $spriteZ * 3);

    /* make white transparent */
    imagecolortransparent($resized, $bg);

    /* and finally, send to standard output */
    header("Content-Type: image/png");
    imagepng($resized);