PageRenderTime 55ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/Jyxo/Color.php

http://github.com/jyxo/php
PHP | 347 lines | 149 code | 44 blank | 154 comment | 4 complexity | f2a1e70817d831fcd50913f647c865aa MD5 | raw file
  1. <?php declare(strict_types = 1);
  2. /**
  3. * Jyxo PHP Library
  4. *
  5. * LICENSE
  6. *
  7. * This source file is subject to the new BSD license that is bundled
  8. * with this package in the file license.txt.
  9. * It is also available through the world-wide-web at this URL:
  10. * https://github.com/jyxo/php/blob/master/license.txt
  11. */
  12. namespace Jyxo;
  13. use InvalidArgumentException;
  14. use function dechex;
  15. use function floor;
  16. use function hexdec;
  17. use function is_array;
  18. use function is_int;
  19. use function is_string;
  20. use function ltrim;
  21. use function min;
  22. use function preg_match;
  23. use function sprintf;
  24. use function str_pad;
  25. use function strlen;
  26. use const STR_PAD_LEFT;
  27. /**
  28. * Class representing a RGB color.
  29. *
  30. * @copyright Copyright (c) 2005-2011 Jyxo, s.r.o.
  31. * @license https://github.com/jyxo/php/blob/master/license.txt
  32. * @author Roman Řáha
  33. */
  34. class Color
  35. {
  36. /**
  37. * Minimal luminance.
  38. */
  39. public const LUM_MIN = 0x00;
  40. /**
  41. * Maximal luminance.
  42. */
  43. public const LUM_MAX = 0xFF;
  44. /**
  45. * The red component of the color.
  46. *
  47. * @var int
  48. */
  49. private $red = self::LUM_MIN;
  50. /**
  51. * The green component of the color.
  52. *
  53. * @var int
  54. */
  55. private $green = self::LUM_MIN;
  56. /**
  57. * The blue component of the color.
  58. *
  59. * @var int
  60. */
  61. private $blue = self::LUM_MIN;
  62. /**
  63. * Constructor.
  64. *
  65. * Accepts the following definition formats:
  66. * * Hexadecimal string (with or without the hashmark at the beginning)
  67. * * Array with red, green and blue component luminance values (in this order)
  68. * * Number,
  69. * * {@link \Jyxo\Color},
  70. * * null
  71. *
  72. * @param mixed $color Color definition
  73. */
  74. public function __construct($color = null)
  75. {
  76. if (is_string($color)) {
  77. $this->initFromHex($color);
  78. } elseif (is_array($color)) {
  79. $this->initFromRgb($color);
  80. } elseif (is_int($color)) {
  81. $this->initFromInt($color);
  82. } elseif ($color instanceof self) {
  83. $this->red = $color->getRed();
  84. $this->green = $color->getGreen();
  85. $this->blue = $color->getBlue();
  86. }
  87. }
  88. /**
  89. * Returns an inverse color.
  90. *
  91. * @return Color
  92. */
  93. public function toInverse(): self
  94. {
  95. $negative = new self();
  96. // Subtracts color component values from the maximum luminance
  97. $negative->setRed(self::LUM_MAX - $this->red)
  98. ->setGreen(self::LUM_MAX - $this->green)
  99. ->setBlue(self::LUM_MAX - $this->blue);
  100. return $negative;
  101. }
  102. /**
  103. * Returns the currect color converted to grayscale.
  104. *
  105. * @return Color
  106. */
  107. public function toGrayScale(): self
  108. {
  109. $gray = new self();
  110. $gray->setLuminance($this->getLuminance());
  111. return $gray;
  112. }
  113. /**
  114. * Returns the current color as an array of the red, green and blue components.
  115. *
  116. * @return array
  117. */
  118. public function getRgb(): array
  119. {
  120. return [
  121. $this->red,
  122. $this->green,
  123. $this->blue,
  124. ];
  125. }
  126. /**
  127. * Returns the current color as a six-digit hexadecimal number.
  128. *
  129. * @return string
  130. */
  131. public function getHex(): string
  132. {
  133. return str_pad(dechex($this->red), 2, '0', STR_PAD_LEFT)
  134. . str_pad(dechex($this->green), 2, '0', STR_PAD_LEFT)
  135. . str_pad(dechex($this->blue), 2, '0', STR_PAD_LEFT);
  136. }
  137. /**
  138. * Returns the current color in binary form 0 - black, 1 - white).
  139. *
  140. * @return int
  141. */
  142. public function getBinary(): int
  143. {
  144. // Black or white corresponds to the most significant bit value
  145. $luminance = $this->getLuminance();
  146. return $luminance >> 7;
  147. }
  148. /**
  149. * Returns the red component luminance.
  150. *
  151. * @return int
  152. */
  153. public function getRed(): int
  154. {
  155. return $this->red;
  156. }
  157. /**
  158. * Sets the red component luminance.
  159. *
  160. * @param int|string $red Component luminance
  161. * @return Color
  162. */
  163. public function setRed($red): self
  164. {
  165. $this->red = $this->toInt($red);
  166. return $this;
  167. }
  168. /**
  169. * Returns the green component luminance.
  170. *
  171. * @return int
  172. */
  173. public function getGreen(): int
  174. {
  175. return $this->green;
  176. }
  177. /**
  178. * Sets the green component luminance.
  179. *
  180. * @param int|string $green Component luminance
  181. * @return Color
  182. */
  183. public function setGreen($green): self
  184. {
  185. $this->green = $this->toInt($green);
  186. return $this;
  187. }
  188. /**
  189. * Returns the blue component luminance.
  190. *
  191. * @return int
  192. */
  193. public function getBlue(): int
  194. {
  195. return $this->blue;
  196. }
  197. /**
  198. * Sets the blue component luminance.
  199. *
  200. * @param int|string $blue Component luminance
  201. * @return Color
  202. */
  203. public function setBlue($blue): self
  204. {
  205. $this->blue = $this->toInt($blue);
  206. return $this;
  207. }
  208. /**
  209. * Returns the color luminance according to the human perception.
  210. *
  211. * @return int
  212. */
  213. public function getLuminance(): int
  214. {
  215. $luminance = 0.11 * $this->red + 0.59 * $this->green + 0.3 * $this->blue;
  216. return (int) floor($luminance);
  217. }
  218. /**
  219. * Sets the color in grayscale according to the luminance value.
  220. *
  221. * @param int|string $luminance Luminance
  222. * @return Color
  223. */
  224. public function setLuminance($luminance): self
  225. {
  226. $luminance = $this->toInt($luminance);
  227. $this->red = $luminance;
  228. $this->green = $luminance;
  229. $this->blue = $luminance;
  230. return $this;
  231. }
  232. /**
  233. * Sets color components using a hexadecimal RRGGBB string.
  234. *
  235. * @param string $hex Color definition
  236. * @return Color
  237. */
  238. private function initFromHex(string $hex): self
  239. {
  240. // Trim the hashmark if present
  241. $hex = ltrim($hex, '#');
  242. if (strlen($hex) === 3) {
  243. // RGB format support
  244. $hex = $hex[0] . $hex[0] . $hex[1] . $hex[1] . $hex[2] . $hex[2];
  245. }
  246. if (!preg_match('~[a-f0-9]{6}~i', $hex)) {
  247. // Invalid color definition
  248. throw new InvalidArgumentException(sprintf('"%s" in not a valid hexadecimal color definition', $hex));
  249. }
  250. $this->initFromInt(hexdec($hex));
  251. return $this;
  252. }
  253. /**
  254. * Sets color components from an array.
  255. *
  256. * @param array $rgb Color definition
  257. * @return Color
  258. */
  259. private function initFromRgb(array $rgb): self
  260. {
  261. $this->setRed($rgb[0])
  262. ->setGreen($rgb[1])
  263. ->setBlue($rgb[2]);
  264. return $this;
  265. }
  266. /**
  267. * Sets color components from an integer.
  268. *
  269. * @param int $int Color definition
  270. * @return Color
  271. */
  272. private function initFromInt(int $int): self
  273. {
  274. $int = min([$int, 0xFFFFFF]);
  275. $this->red = self::LUM_MAX & ($int >> 16);
  276. $this->green = self::LUM_MAX & ($int >> 8);
  277. $this->blue = self::LUM_MAX & $int;
  278. return $this;
  279. }
  280. /**
  281. * Returns the color luminance as a decimal integer.
  282. *
  283. * @param int|string $value Luminance value
  284. * @return int
  285. */
  286. private function toInt($value): int
  287. {
  288. if (is_string($value)) {
  289. $value = hexdec($value);
  290. }
  291. // Luminance must not be greater than 0xFF
  292. return min([(int) $value, self::LUM_MAX]);
  293. }
  294. /**
  295. * Returns textual (#RRGGBB) representation of the current color.
  296. *
  297. * @return string
  298. */
  299. public function __toString(): string
  300. {
  301. return '#' . $this->getHex();
  302. }
  303. }