File indexing completed on 2024-05-12 06:02:11

0001 <?php
0002 /**
0003  *  ocs-webserver
0004  *
0005  *  Copyright 2016 by pling GmbH.
0006  *
0007  *    This file is part of ocs-webserver.
0008  *
0009  *    This program is free software: you can redistribute it and/or modify
0010  *    it under the terms of the GNU Affero General Public License as
0011  *    published by the Free Software Foundation, either version 3 of the
0012  *    License, or (at your option) any later version.
0013  *
0014  *    This program is distributed in the hope that it will be useful,
0015  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
0016  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0017  *    GNU Affero General Public License for more details.
0018  *
0019  *    You should have received a copy of the GNU Affero General Public License
0020  *    along with this program.  If not, see <http://www.gnu.org/licenses/>.
0021  **/
0022 
0023 /**
0024  * Class Local_Tools_Identicon
0025  *
0026  * This is based on the source from the PHP Identicons Project
0027  * from sourceforge.net.
0028  */
0029 class Local_Tools_Identicon
0030 {
0031 
0032     protected $_spriteZ;
0033 
0034     function __construct()
0035     {
0036         $this->_spriteZ = 128;
0037     }
0038 
0039 
0040     /* generate sprite for corners and sides */
0041 
0042     public function renderIdentIcon($hash = '', $size = 100)
0043     {
0044         /* parse hash string */
0045         $csh = hexdec(substr($hash, 0, 1)); // corner sprite shape
0046         $ssh = hexdec(substr($hash, 1, 1)); // side sprite shape
0047         $xsh = hexdec(substr($hash, 2, 1)) & 7; // center sprite shape
0048 
0049         $cro = hexdec(substr($hash, 3, 1)) & 3; // corner sprite rotation
0050         $sro = hexdec(substr($hash, 4, 1)) & 3; // side sprite rotation
0051         $xbg = hexdec(substr($hash, 5, 1)) % 2; // center sprite background
0052 
0053         /* corner sprite foreground color */
0054         $cfr = hexdec(substr($hash, 6, 2));
0055         $cfg = hexdec(substr($hash, 8, 2));
0056         $cfb = hexdec(substr($hash, 10, 2));
0057 
0058         /* side sprite foreground color */
0059         $sfr = hexdec(substr($hash, 12, 2));
0060         $sfg = hexdec(substr($hash, 14, 2));
0061         $sfb = hexdec(substr($hash, 16, 2));
0062 
0063         /* final angle of rotation */
0064         $angle = hexdec(substr($hash, 18, 2));
0065 
0066         /* size of each sprite */
0067         $spriteZ = $this->_spriteZ;
0068 
0069         /* start with blank 3x3 identicon */
0070         $identicon = imagecreatetruecolor($spriteZ * 3, $spriteZ * 3);
0071         if (function_exists('imageantialias')) {
0072             imageantialias($identicon, true);
0073         }
0074 
0075         /* assign white as background */
0076         $bg = imagecolorallocate($identicon, 255, 255, 255);
0077         imagefilledrectangle($identicon, 0, 0, $spriteZ, $spriteZ, $bg);
0078 
0079         /* generate corner sprites */
0080         $corner = $this->getsprite($csh, $cfr, $cfg, $cfb, $cro);
0081         imagecopy($identicon, $corner, 0, 0, 0, 0, $spriteZ, $spriteZ);
0082         $corner = imagerotate($corner, 90, $bg);
0083         imagecopy($identicon, $corner, 0, $spriteZ * 2, 0, 0, $spriteZ, $spriteZ);
0084         $corner = imagerotate($corner, 90, $bg);
0085         imagecopy($identicon, $corner, $spriteZ * 2, $spriteZ * 2, 0, 0, $spriteZ, $spriteZ);
0086         $corner = imagerotate($corner, 90, $bg);
0087         imagecopy($identicon, $corner, $spriteZ * 2, 0, 0, 0, $spriteZ, $spriteZ);
0088 
0089         /* generate side sprites */
0090         $side = $this->getsprite($ssh, $sfr, $sfg, $sfb, $sro);
0091         imagecopy($identicon, $side, $spriteZ, 0, 0, 0, $spriteZ, $spriteZ);
0092         $side = imagerotate($side, 90, $bg);
0093         imagecopy($identicon, $side, 0, $spriteZ, 0, 0, $spriteZ, $spriteZ);
0094         $side = imagerotate($side, 90, $bg);
0095         imagecopy($identicon, $side, $spriteZ, $spriteZ * 2, 0, 0, $spriteZ, $spriteZ);
0096         $side = imagerotate($side, 90, $bg);
0097         imagecopy($identicon, $side, $spriteZ * 2, $spriteZ, 0, 0, $spriteZ, $spriteZ);
0098 
0099         /* generate center sprite */
0100         $center = $this->getcenter($xsh, $cfr, $cfg, $cfb, $sfr, $sfg, $sfb, $xbg);
0101         imagecopy($identicon, $center, $spriteZ, $spriteZ, 0, 0, $spriteZ, $spriteZ);
0102 
0103 // $identicon=imagerotate($identicon,$angle,$bg);
0104 
0105         /* make white transparent */
0106         imagecolortransparent($identicon, $bg);
0107 
0108         /* create blank image according to specified dimensions */
0109         $resized = imagecreatetruecolor($size, $size);
0110         if (function_exists('imageantialias')) {
0111             imageantialias($resized, true);
0112         }
0113 
0114         /* assign white as background */
0115         $bg = imagecolorallocate($resized, 255, 255, 255);
0116         imagefilledrectangle($resized, 0, 0, $size, $size, $bg);
0117 
0118         /* resize identicon according to specification */
0119         imagecopyresampled($resized, $identicon, 0, 0, (imagesx($identicon) - $spriteZ * 3) / 2, (imagesx($identicon) - $spriteZ * 3) / 2, $size,
0120             $size, $spriteZ * 3, $spriteZ * 3);
0121 
0122         /* make white transparent */
0123         imagecolortransparent($resized, $bg);
0124 
0125         return $resized;
0126 
0127         /* and finally, send to standard output */
0128         //header("Content-Type: image/png");
0129         //imagepng($resized);
0130     }
0131 
0132     /* generate sprite for center block */
0133 
0134     protected function getsprite($shape, $R, $G, $B, $rotation)
0135     {
0136         $spriteZ = $this->_spriteZ;
0137         $sprite = imagecreatetruecolor($spriteZ, $spriteZ);
0138         if (function_exists('imageantialias')) {
0139             imageantialias($sprite, true);
0140         }
0141         $fg = imagecolorallocate($sprite, $R, $G, $B);
0142         $bg = imagecolorallocate($sprite, 255, 255, 255);
0143         imagefilledrectangle($sprite, 0, 0, $spriteZ, $spriteZ, $bg);
0144         switch ($shape) {
0145             case 0: // triangle
0146                 $shape = array(
0147                     0.5,
0148                     1,
0149                     1,
0150                     0,
0151                     1,
0152                     1
0153                 );
0154                 break;
0155             case 1: // parallelogram
0156                 $shape = array(
0157                     0.5,
0158                     0,
0159                     1,
0160                     0,
0161                     0.5,
0162                     1,
0163                     0,
0164                     1
0165                 );
0166                 break;
0167             case 2: // mouse ears
0168                 $shape = array(
0169                     0.5,
0170                     0,
0171                     1,
0172                     0,
0173                     1,
0174                     1,
0175                     0.5,
0176                     1,
0177                     1,
0178                     0.5
0179                 );
0180                 break;
0181             case 3: // ribbon
0182                 $shape = array(
0183                     0,
0184                     0.5,
0185                     0.5,
0186                     0,
0187                     1,
0188                     0.5,
0189                     0.5,
0190                     1,
0191                     0.5,
0192                     0.5
0193                 );
0194                 break;
0195             case 4: // sails
0196                 $shape = array(
0197                     0,
0198                     0.5,
0199                     1,
0200                     0,
0201                     1,
0202                     1,
0203                     0,
0204                     1,
0205                     1,
0206                     0.5
0207                 );
0208                 break;
0209             case 5: // fins
0210                 $shape = array(
0211                     1,
0212                     0,
0213                     1,
0214                     1,
0215                     0.5,
0216                     1,
0217                     1,
0218                     0.5,
0219                     0.5,
0220                     0.5
0221                 );
0222                 break;
0223             case 6: // beak
0224                 $shape = array(
0225                     0,
0226                     0,
0227                     1,
0228                     0,
0229                     1,
0230                     0.5,
0231                     0,
0232                     0,
0233                     0.5,
0234                     1,
0235                     0,
0236                     1
0237                 );
0238                 break;
0239             case 7: // chevron
0240                 $shape = array(
0241                     0,
0242                     0,
0243                     0.5,
0244                     0,
0245                     1,
0246                     0.5,
0247                     0.5,
0248                     1,
0249                     0,
0250                     1,
0251                     0.5,
0252                     0.5
0253                 );
0254                 break;
0255             case 8: // fish
0256                 $shape = array(
0257                     0.5,
0258                     0,
0259                     0.5,
0260                     0.5,
0261                     1,
0262                     0.5,
0263                     1,
0264                     1,
0265                     0.5,
0266                     1,
0267                     0.5,
0268                     0.5,
0269                     0,
0270                     0.5
0271                 );
0272                 break;
0273             case 9: // kite
0274                 $shape = array(
0275                     0,
0276                     0,
0277                     1,
0278                     0,
0279                     0.5,
0280                     0.5,
0281                     1,
0282                     0.5,
0283                     0.5,
0284                     1,
0285                     0.5,
0286                     0.5,
0287                     0,
0288                     1
0289                 );
0290                 break;
0291             case 10: // trough
0292                 $shape = array(
0293                     0,
0294                     0.5,
0295                     0.5,
0296                     1,
0297                     1,
0298                     0.5,
0299                     0.5,
0300                     0,
0301                     1,
0302                     0,
0303                     1,
0304                     1,
0305                     0,
0306                     1
0307                 );
0308                 break;
0309             case 11: // rays
0310                 $shape = array(
0311                     0.5,
0312                     0,
0313                     1,
0314                     0,
0315                     1,
0316                     1,
0317                     0.5,
0318                     1,
0319                     1,
0320                     0.75,
0321                     0.5,
0322                     0.5,
0323                     1,
0324                     0.25
0325                 );
0326                 break;
0327             case 12: // double rhombus
0328                 $shape = array(
0329                     0,
0330                     0.5,
0331                     0.5,
0332                     0,
0333                     0.5,
0334                     0.5,
0335                     1,
0336                     0,
0337                     1,
0338                     0.5,
0339                     0.5,
0340                     1,
0341                     0.5,
0342                     0.5,
0343                     0,
0344                     1
0345                 );
0346                 break;
0347             case 13: // crown
0348                 $shape = array(
0349                     0,
0350                     0,
0351                     1,
0352                     0,
0353                     1,
0354                     1,
0355                     0,
0356                     1,
0357                     1,
0358                     0.5,
0359                     0.5,
0360                     0.25,
0361                     0.5,
0362                     0.75,
0363                     0,
0364                     0.5,
0365                     0.5,
0366                     0.25
0367                 );
0368                 break;
0369             case 14: // radioactive
0370                 $shape = array(
0371                     0,
0372                     0.5,
0373                     0.5,
0374                     0.5,
0375                     0.5,
0376                     0,
0377                     1,
0378                     0,
0379                     0.5,
0380                     0.5,
0381                     1,
0382                     0.5,
0383                     0.5,
0384                     1,
0385                     0.5,
0386                     0.5,
0387                     0,
0388                     1
0389                 );
0390                 break;
0391             default: // tiles
0392                 $shape = array(
0393                     0,
0394                     0,
0395                     1,
0396                     0,
0397                     0.5,
0398                     0.5,
0399                     0.5,
0400                     0,
0401                     0,
0402                     0.5,
0403                     1,
0404                     0.5,
0405                     0.5,
0406                     1,
0407                     0.5,
0408                     0.5,
0409                     0,
0410                     1
0411                 );
0412                 break;
0413         }
0414         /* apply ratios */
0415         for ($i = 0; $i < count($shape); $i++) {
0416             $shape[$i] = $shape[$i] * $spriteZ;
0417         }
0418         imagefilledpolygon($sprite, $shape, count($shape) / 2, $fg);
0419         /* rotate the sprite */
0420         for ($i = 0; $i < $rotation; $i++) {
0421             $sprite = imagerotate($sprite, 90, $bg);
0422         }
0423         return $sprite;
0424     }
0425 
0426     protected function getcenter($shape, $fR, $fG, $fB, $bR, $bG, $bB, $usebg)
0427     {
0428         $spriteZ = $this->_spriteZ;
0429         $sprite = imagecreatetruecolor($spriteZ, $spriteZ);
0430         if (function_exists('imageantialias')) {
0431             imageantialias($sprite, true);
0432         }
0433 
0434         $fg = imagecolorallocate($sprite, $fR, $fG, $fB);
0435         /* make sure there's enough contrast before we use background color of side sprite */
0436         if ($usebg > 0 && (abs($fR - $bR) > 127 || abs($fG - $bG) > 127 || abs($fB - $bB) > 127)) {
0437             $bg = imagecolorallocate($sprite, $bR, $bG, $bB);
0438         } else {
0439             $bg = imagecolorallocate($sprite, 255, 255, 255);
0440         }
0441         imagefilledrectangle($sprite, 0, 0, $spriteZ, $spriteZ, $bg);
0442         switch ($shape) {
0443             case 0: // empty
0444                 $shape = array();
0445                 break;
0446             case 1: // fill
0447                 $shape = array(
0448                     0,
0449                     0,
0450                     1,
0451                     0,
0452                     1,
0453                     1,
0454                     0,
0455                     1
0456                 );
0457                 break;
0458             case 2: // diamond
0459                 $shape = array(
0460                     0.5,
0461                     0,
0462                     1,
0463                     0.5,
0464                     0.5,
0465                     1,
0466                     0,
0467                     0.5
0468                 );
0469                 break;
0470             case 3: // reverse diamond
0471                 $shape = array(
0472                     0,
0473                     0,
0474                     1,
0475                     0,
0476                     1,
0477                     1,
0478                     0,
0479                     1,
0480                     0,
0481                     0.5,
0482                     0.5,
0483                     1,
0484                     1,
0485                     0.5,
0486                     0.5,
0487                     0,
0488                     0,
0489                     0.5
0490                 );
0491                 break;
0492             case 4: // cross
0493                 $shape = array(
0494                     0.25,
0495                     0,
0496                     0.75,
0497                     0,
0498                     0.5,
0499                     0.5,
0500                     1,
0501                     0.25,
0502                     1,
0503                     0.75,
0504                     0.5,
0505                     0.5,
0506                     0.75,
0507                     1,
0508                     0.25,
0509                     1,
0510                     0.5,
0511                     0.5,
0512                     0,
0513                     0.75,
0514                     0,
0515                     0.25,
0516                     0.5,
0517                     0.5
0518                 );
0519                 break;
0520             case 5: // morning star
0521                 $shape = array(
0522                     0,
0523                     0,
0524                     0.5,
0525                     0.25,
0526                     1,
0527                     0,
0528                     0.75,
0529                     0.5,
0530                     1,
0531                     1,
0532                     0.5,
0533                     0.75,
0534                     0,
0535                     1,
0536                     0.25,
0537                     0.5
0538                 );
0539                 break;
0540             case 6: // small square
0541                 $shape = array(
0542                     0.33,
0543                     0.33,
0544                     0.67,
0545                     0.33,
0546                     0.67,
0547                     0.67,
0548                     0.33,
0549                     0.67
0550                 );
0551                 break;
0552             case 7: // checkerboard
0553                 $shape = array(
0554                     0,
0555                     0,
0556                     0.33,
0557                     0,
0558                     0.33,
0559                     0.33,
0560                     0.66,
0561                     0.33,
0562                     0.67,
0563                     0,
0564                     1,
0565                     0,
0566                     1,
0567                     0.33,
0568                     0.67,
0569                     0.33,
0570                     0.67,
0571                     0.67,
0572                     1,
0573                     0.67,
0574                     1,
0575                     1,
0576                     0.67,
0577                     1,
0578                     0.67,
0579                     0.67,
0580                     0.33,
0581                     0.67,
0582                     0.33,
0583                     1,
0584                     0,
0585                     1,
0586                     0,
0587                     0.67,
0588                     0.33,
0589                     0.67,
0590                     0.33,
0591                     0.33,
0592                     0,
0593                     0.33
0594                 );
0595                 break;
0596         }
0597         /* apply ratios */
0598         for ($i = 0; $i < count($shape); $i++) {
0599             $shape[$i] = $shape[$i] * $spriteZ;
0600         }
0601         if (count($shape) > 0) {
0602             imagefilledpolygon($sprite, $shape, count($shape) / 2, $fg);
0603         }
0604         return $sprite;
0605     }
0606 
0607 }