<?php
/*
 * Material-Design-Avatars
 * https://github.com/lincanbin/Material-Design-Avatars
 *
 * Copyright 2015 Canbin Lin (lincanbin@hotmail.com)
 * http://www.94cb.com/
 *
 * Licensed under the Apache License, Version 2.0:
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Create material deisgn avatars for users just like Gmail or Messager in Android.
 */
declare (strict_types = 1);
namespace avatars;

class MDAvatars
{
    public $Char;
    public $AvatarSize;
    public $Shape;
    public $Padding;
    public $Avatar;
    public $FontFile;
    public $IsNotLetter;
    public $LetterFont;
    public $AsianFont;
    public $EnableAsianChar;


    function __construct($Char, $AvatarSize = 256 ,$Shape = 1)
    {
        $this->Char            = mb_strtoupper(mb_substr($Char, 0, 1, "UTF-8"));
        $this->AvatarSize      = $AvatarSize;
        $this->Shape           = $Shape;
        $this->Padding         = 30 * ($this->AvatarSize / 256);
        $this->LetterFont      = dirname(__FILE__) . '/fonts/SourceCodePro-Light.ttf';
        $this->AsianFont       = dirname(__FILE__) . '/fonts/SourceHanSansCN-Normal.ttf';
        $this->EnableAsianChar = is_file($this->AsianFont);
        $path='./storage/avatars/';
        if(!is_dir($path)){
            mkdir($path, 0755, true);
        }
        $CNChar = ord($this->Char);
        if (!$this->EnableAsianChar &&
            preg_match("/^[\x7f-\xff]/", $this->Char) &&
            !($CNChar >= ord("A") && $CNChar <= ord("z"))
        ) {
            //如果是中文,并且没有中文字体包,则按拼音首字母对其进行转换
            $CNByte = iconv("UTF-8", "gb2312", $this->Char);
            $Code   = ord($CNByte[0]) * 256 + ord($CNByte[1]) - 65536;//求其偏移量
            if ($Code >= -20319 and $Code <= -20284) $this->Char = "A";
            if ($Code >= -20283 and $Code <= -19776) $this->Char = "B";
            if ($Code >= -19775 and $Code <= -19219) $this->Char = "C";
            if ($Code >= -19218 and $Code <= -18711) $this->Char = "D";
            if ($Code >= -18710 and $Code <= -18527) $this->Char = "E";
            if ($Code >= -18526 and $Code <= -18240) $this->Char = "F";
            if ($Code >= -18239 and $Code <= -17923) $this->Char = "G";
            if ($Code >= -17922 and $Code <= -17418) $this->Char = "H";
            if ($Code >= -17417 and $Code <= -16475) $this->Char = "J";
            if ($Code >= -16474 and $Code <= -16213) $this->Char = "K";
            if ($Code >= -16212 and $Code <= -15641) $this->Char = "L";
            if ($Code >= -15640 and $Code <= -15166) $this->Char = "M";
            if ($Code >= -15165 and $Code <= -14923) $this->Char = "N";
            if ($Code >= -14922 and $Code <= -14915) $this->Char = "O";
            if ($Code >= -14914 and $Code <= -14631) $this->Char = "P";
            if ($Code >= -14630 and $Code <= -14150) $this->Char = "Q";
            if ($Code >= -14149 and $Code <= -14091) $this->Char = "R";
            if ($Code >= -14090 and $Code <= -13319) $this->Char = "S";
            if ($Code >= -13318 and $Code <= -12839) $this->Char = "T";
            if ($Code >= -12838 and $Code <= -12557) $this->Char = "W";
            if ($Code >= -12556 and $Code <= -11848) $this->Char = "X";
            if ($Code >= -11847 and $Code <= -11056) $this->Char = "Y";
            if ($Code >= -11055 and $Code <= -10247) $this->Char = "Z";
        }
        if (in_array($this->Char, str_split('QWERTYUIOPASDFGHJKLZXCVBNM0123456789', 1))) {
            $this->IsNotLetter = false;
            $this->FontFile    = $this->LetterFont;
        } else {
            $this->IsNotLetter = true;
            $this->FontFile    = $this->AsianFont;
        }
        $this->Initialize();
    }

    private function Initialize()
    {
        //extension_loaded('gd')
        $Width        = $this->AvatarSize;//Width of avatar
        $Height       = $this->AvatarSize;//Height of avatar
        $Padding      = $this->Padding;
        $this->Avatar = imagecreatetruecolor($Width, $Height);
        //全透明背景
        imageSaveAlpha($this->Avatar, true);
        $BackgroundAlpha = imagecolorallocatealpha($this->Avatar, 255, 255, 255, 127);
        imagefill($this->Avatar, 0, 0, $BackgroundAlpha);
        //抗锯齿
        if (function_exists('imageantialias')) {
            imageantialias($this->Avatar, true);
        }
        //Material Design参考颜色
        //http://www.google.com/design/spec/style/color.html#color-color-palette
        $MaterialDesignColor  = array(
            array(239, 154, 154),
            array(229, 115, 115),
            array(239, 83, 80),
            array(244, 67, 54),
            array(229, 57, 53),
            array(211, 47, 47),
            array(198, 40, 40),
            array(183, 28, 28),
            array(255, 138, 128),
            array(255, 82, 82),
            array(255, 23, 68),
            array(213, 0, 0),
            array(248, 187, 208),
            array(244, 143, 177),
            array(240, 98, 146),
            array(236, 64, 122),
            array(233, 30, 99),
            array(216, 27, 96),
            array(194, 24, 91),
            array(173, 20, 87),
            array(136, 14, 79),
            array(255, 128, 171),
            array(255, 64, 129),
            array(245, 0, 87),
            array(197, 17, 98),
            array(206, 147, 216),
            array(186, 104, 200),
            array(171, 71, 188),
            array(156, 39, 176),
            array(142, 36, 170),
            array(123, 31, 162),
            array(106, 27, 154),
            array(74, 20, 140),
            array(234, 128, 252),
            array(224, 64, 251),
            array(213, 0, 249),
            array(170, 0, 255),
            array(179, 157, 219),
            array(149, 117, 205),
            array(126, 87, 194),
            array(103, 58, 183),
            array(94, 53, 177),
            array(81, 45, 168),
            array(69, 39, 160),
            array(49, 27, 146),
            array(179, 136, 255),
            array(124, 77, 255),
            array(101, 31, 255),
            array(98, 0, 234),
            array(197, 202, 233),
            array(159, 168, 218),
            array(121, 134, 203),
            array(92, 107, 192),
            array(63, 81, 181),
            array(57, 73, 171),
            array(48, 63, 159),
            array(40, 53, 147),
            array(26, 35, 126),
            array(140, 158, 255),
            array(83, 109, 254),
            array(61, 90, 254),
            array(48, 79, 254),
            array(227, 242, 253),
            array(187, 222, 251),
            array(144, 202, 249),
            array(100, 181, 246),
            array(66, 165, 245),
            array(33, 150, 243),
            array(30, 136, 229),
            array(25, 118, 210),
            array(21, 101, 192),
            array(13, 71, 161),
            array(130, 177, 255),
            array(68, 138, 255),
            array(41, 121, 255),
            array(41, 98, 255),
            array(179, 229, 252),
            array(129, 212, 250),
            array(79, 195, 247),
            array(41, 182, 252),
            array(3, 169, 244),
            array(3, 155, 229),
            array(2, 136, 209),
            array(2, 119, 189),
            array(1, 87, 155),
            array(128, 216, 255),
            array(64, 196, 255),
            array(0, 176, 255),
            array(0, 145, 234),
            array(178, 235, 242),
            array(128, 222, 234),
            array(77, 208, 225),
            array(38, 198, 218),
            array(0, 188, 212),
            array(0, 172, 193),
            array(0, 151, 167),
            array(0, 131, 143),
            array(0, 96, 100),
            array(132, 255, 255),
            array(24, 255, 255),
            array(0, 229, 255),
            array(0, 184, 212),
            array(178, 223, 219),
            array(128, 203, 196),
            array(77, 182, 172),
            array(38, 166, 154),
            array(0, 150, 136),
            array(0, 137, 123),
            array(0, 121, 107),
            array(0, 105, 92),
            array(0, 77, 64),
            array(167, 255, 235),
            array(100, 255, 218),
            array(29, 233, 182),
            array(0, 191, 165),
            array(165, 214, 167),
            array(129, 199, 132),
            array(102, 187, 106),
            array(76, 175, 80),
            array(67, 160, 71),
            array(56, 142, 60),
            array(46, 125, 50),
            array(27, 94, 32),
            array(185, 246, 202),
            array(105, 240, 174),
            array(0, 230, 118),
            array(0, 200, 83),
            array(197, 225, 165),
            array(174, 213, 129),
            array(156, 204, 101),
            array(139, 195, 74),
            array(124, 179, 66),
            array(104, 159, 56),
            array(85, 139, 47),
            array(51, 105, 30),
            array(178, 255, 89),
            array(118, 255, 3),
            array(100, 221, 23),
            array(249, 251, 231),
            array(240, 244, 195),
            array(230, 238, 156),
            array(220, 231, 117),
            array(212, 225, 87),
            array(205, 220, 57),
            array(192, 202, 51),
            array(164, 180, 43),
            array(158, 157, 36),
            array(130, 119, 23),
            array(198, 255, 0),
            array(174, 234, 0),
            array(251, 192, 45),
            array(249, 168, 37),
            array(245, 127, 23),
            array(255, 179, 0),
            array(255, 160, 0),
            array(255, 143, 0),
            array(255, 111, 0),
            array(255, 171, 0),
            array(255, 183, 77),
            array(255, 167, 38),
            array(255, 152, 0),
            array(251, 140, 0),
            array(245, 124, 0),
            array(239, 108, 0),
            array(230, 81, 0),
            array(255, 171, 64),
            array(255, 145, 0),
            array(255, 109, 0),
            array(255, 171, 145),
            array(255, 138, 101),
            array(255, 112, 67),
            array(255, 87, 34),
            array(244, 81, 30),
            array(230, 74, 25),
            array(216, 67, 21),
            array(191, 54, 12),
            array(255, 158, 128),
            array(255, 110, 64),
            array(255, 61, 0),
            array(221, 38, 0),
            array(188, 170, 164),
            array(161, 136, 127),
            array(141, 110, 99),
            array(121, 85, 72),
            array(109, 76, 65),
            array(93, 64, 55),
            array(78, 52, 46),
            array(62, 39, 35),
            array(189, 189, 189),
            array(158, 158, 158),
            array(117, 117, 117),
            array(97, 97, 97),
            array(66, 66, 66),
            array(33, 33, 33),
            array(236, 239, 241),
            array(176, 187, 197),
            array(144, 164, 174),
            array(120, 144, 156),
            array(96, 125, 139),
            array(84, 110, 122),
            array(69, 90, 100),
            array(55, 71, 79),
            array(38, 50, 56)
        );
        $BackgroundColorIndex = mt_rand(0, count($MaterialDesignColor) - 1);
        $BackgroundColor      = imagecolorallocate($this->Avatar,
            $MaterialDesignColor[$BackgroundColorIndex][0],
            $MaterialDesignColor[$BackgroundColorIndex][1],
            $MaterialDesignColor[$BackgroundColorIndex][2]
        );
		if($this->Shape == 1){
			//画一个矩形
			imagerectangle($this->Avatar,
				0,
				0,
				$Width,
				$Height,
				$BackgroundColor
			);
			imagefilledrectangle($this->Avatar,
				0,
				0,
				$Width,
				$Height,
				$BackgroundColor
			);
		}
		else{
			//画一个居中圆形
			imagefilledellipse($this->Avatar,
				$Width / 2,
				$Height / 2,
				$Width,
				$Height,
				$BackgroundColor
			);
		}
        //字体
        $FontColor = imagecolorallocate($this->Avatar, 255, 255, 255);
        if ($this->IsNotLetter) {
            //中文字符偏移
            $FontSize = $Width - $Padding * 3.5;
            $X        = $Padding + (-2 / 166) * $FontSize;
            $Y        = $Height - $Padding - (23.5 / 166) * $FontSize;
        } else {
            $FontSize = $Width - $Padding * 2;
            $X        = $Padding + (20 / 196) * $FontSize;
            $Y        = $Height - $Padding - (13 / 196) * $FontSize;
        }
        // 在圆正中央填入字符
        imagettftext($this->Avatar, $FontSize,0,intval($X), intval($Y),$FontColor,$this->FontFile, $this->Char);
    }

    private function Resize($TargetSize)
    {
        if (isset($this->Avatar)) {
            if ($this->AvatarSize > $TargetSize) {
                $Percent         = $TargetSize / $this->AvatarSize;
                $TargetWidth     = round($this->AvatarSize * $Percent);
                $TargetHeight    = round($this->AvatarSize * $Percent);
                $TargetImageData = imagecreatetruecolor($TargetWidth, $TargetHeight);
                //全透明背景
                imageSaveAlpha($TargetImageData, true);
                $BackgroundAlpha = imagecolorallocatealpha($TargetImageData, 255, 255, 255, 127);
                imagefill($TargetImageData, 0, 0, $BackgroundAlpha);
                imagecopyresampled($TargetImageData, $this->Avatar, 0, 0, 0, 0, $TargetWidth, $TargetHeight, $this->AvatarSize, $this->AvatarSize);
                return $TargetImageData;
            } else {
                return $this->Avatar;
            }
        } else {
            return false;
        }
    }

    public function Free()
    {
        imagedestroy($this->Avatar);
    }

    public function Output2Browser($AvatarSize = 0)
    {
        if (!$AvatarSize) {
            $AvatarSize = $this->AvatarSize;
        }
        header('Content-Type: image/png');
        return imagepng($this->Resize($AvatarSize));
    }

    /**
     * Get image resource identifier
     * @param int $AvatarSize
     * @return resource
     */
    public function Output2ImageResource($AvatarSize = 0)
    {
        if (!$AvatarSize) {
            $AvatarSize = $this->AvatarSize;
        }
        return $this->Resize($AvatarSize);
    }

    /**
     * Output Base64 encoded image data
     * @param int $AvatarSize
     * @return string
     */
    public function Output2Base64($AvatarSize = 0)
    {
        if (!$AvatarSize) {
            $AvatarSize = $this->AvatarSize;
        }

        ob_start();
        imagepng($this->Resize($AvatarSize));
        $content = ob_get_contents();
        ob_end_clean();

        return 'data:image/png;base64,' . base64_encode($content);
    }

    public function Save($Path, $AvatarSize = 0)
    {
        if (!$AvatarSize) {
            $AvatarSize = $this->AvatarSize;
        }
        return imagepng($this->Resize($AvatarSize), $Path);
    }
}