Invision Power Services, Inc. * @copyright (c) Invision Power Services, Inc. * @license https://www.invisioncommunity.com/legal/standards/ * @package Invision Community * @since 3 Feb 2017 */ namespace IPS\Member; /* To prevent PHP errors (extending class does not exist) revealing path */ use function defined; use function mb_strtolower; use function ord; if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) ) { header( ( $_SERVER['SERVER_PROTOCOL'] ?? 'HTTP/1.0' ) . ' 403 Forbidden' ); exit; } /** * Letter photo generator for member accounts */ class LetterPhoto { /** * @brief Member name */ protected ?string $memberName = NULL; /** * Create a new photo object * * @param string $name Member name * @return void */ public function __construct( string $name ) { $this->memberName = $name; } /** * @brief Color saturation to use for HSV colors */ protected float $colorCodeSaturation = .45; /** * @brief Color value to use for HSV colors */ protected float $colorCodeValue = 0.575; /** * @brief If we have just generated a hue on this page load, store it to better randomize the next color */ protected static ?float $lastHue = NULL; /** * Return a unique hex color code based on the name. * * @return string */ public function generateColorCode() : string { /* If we've already generated a hue on this page load, use the golden ratio to find a number sufficiently distinct */ if( static::$lastHue ) { $hue = static::$lastHue + 0.618033988749895; if( $hue > 1.0 ) { $hue -= 1.0; } static::$lastHue = $hue; return $this->convertRgbToHex( $this->convertHsvToRgb( $hue, $this->colorCodeSaturation, $this->colorCodeValue ) ); } $hue = ( ( ord( mb_strtolower( $this->memberName ) ) - 97 ) / 25.0 ) + 0.25; $hue *= 1.61803398875; $hue *= (float) ( '1.' . rand() ) / 1; if( rand( 0, 1 ) ) { $float = (float) ( "1." . ord( array_rand( range( 'a', 'z' ) ) ) ); $hue = abs( $float - $hue ); } while( $hue > 1.0 ) { $hue -= 1.0; } static::$lastHue = $hue; return $this->convertRgbToHex( $this->convertHsvToRgb( $hue, $this->colorCodeSaturation, $this->colorCodeValue ) ); } /** * Convert the HSV value to RGB * * @param float $h Hue * @param float $s Saturation * @param float $v Value * @return array */ protected function convertHsvToRgb( float $h, float $s, float $v ): array { $rgb = array( $v, $v, $v ); $diff = ( $v <= 0.5 ) ? ( $v * ( 1.0 + $s ) ) : ( $v + $s - $v * $s ); if( $diff ) { $m = $v + $v - $diff; $sv = ( $diff - $m ) / $diff; $h *= 6.0; $fract = $h - floor( $h ); $vsf = $diff * $sv * $fract; $mid1 = $m + $vsf; $mid2 = $diff - $vsf; switch( floor( $h ) ) { case 0: $rgb = array( $diff, $mid1, $m ); break; case 1: $rgb = array( $mid2, $diff, $m ); break; case 2: $rgb = array( $m, $diff, $mid1 ); break; case 3: $rgb = array( $m, $mid2, $diff ); break; case 4: $rgb = array( $mid1, $m, $diff ); break; case 5: $rgb = array( $diff, $m, $mid2 ); break; } } return array_map( function( $value ) { return round( $value * 256.0 ); }, $rgb ); } /** * Convert an RGB color value to hex * * @param array $rgb RGB color values * @return string */ protected function convertRgbToHex( array $rgb ): string { return sprintf( "%02x%02x%02x", $rgb[0], $rgb[1], $rgb[2] ); } }