LuminanceSourceAbstract.php 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. <?php
  2. /**
  3. * Class LuminanceSourceAbstract
  4. *
  5. * @created 24.01.2021
  6. * @author ZXing Authors
  7. * @author Ashot Khanamiryan
  8. * @author Smiley <smiley@chillerlan.net>
  9. * @copyright 2021 Smiley
  10. * @license Apache-2.0
  11. */
  12. namespace chillerlan\QRCode\Common;
  13. use chillerlan\QRCode\Decoder\QRCodeDecoderException;
  14. use chillerlan\QRCode\QROptions;
  15. use chillerlan\Settings\SettingsContainerInterface;
  16. use function array_slice, array_splice, file_exists, is_file, is_readable, realpath;
  17. /**
  18. * The purpose of this class hierarchy is to abstract different bitmap implementations across
  19. * platforms into a standard interface for requesting greyscale luminance values.
  20. *
  21. * @author dswitkin@google.com (Daniel Switkin)
  22. */
  23. abstract class LuminanceSourceAbstract implements LuminanceSourceInterface{
  24. /** @var \chillerlan\QRCode\QROptions|\chillerlan\Settings\SettingsContainerInterface */
  25. protected SettingsContainerInterface $options;
  26. protected array $luminances;
  27. protected int $width;
  28. protected int $height;
  29. /**
  30. *
  31. */
  32. public function __construct(int $width, int $height, ?SettingsContainerInterface $options = null){
  33. $this->width = $width;
  34. $this->height = $height;
  35. $this->options = ($options ?? new QROptions);
  36. $this->luminances = [];
  37. }
  38. /** @inheritDoc */
  39. public function getLuminances():array{
  40. return $this->luminances;
  41. }
  42. /** @inheritDoc */
  43. public function getWidth():int{
  44. return $this->width;
  45. }
  46. /** @inheritDoc */
  47. public function getHeight():int{
  48. return $this->height;
  49. }
  50. /** @inheritDoc */
  51. public function getRow(int $y):array{
  52. if($y < 0 || $y >= $this->getHeight()){
  53. throw new QRCodeDecoderException('Requested row is outside the image: '.$y);
  54. }
  55. $arr = [];
  56. array_splice($arr, 0, $this->width, array_slice($this->luminances, ($y * $this->width), $this->width));
  57. return $arr;
  58. }
  59. /**
  60. *
  61. */
  62. protected function setLuminancePixel(int $r, int $g, int $b):void{
  63. $this->luminances[] = ($r === $g && $g === $b)
  64. // Image is already greyscale, so pick any channel.
  65. ? $r // (($r + 128) % 256) - 128;
  66. // Calculate luminance cheaply, favoring green.
  67. : (($r + 2 * $g + $b) / 4); // (((($r + 2 * $g + $b) / 4) + 128) % 256) - 128;
  68. }
  69. /**
  70. * @throws \chillerlan\QRCode\Decoder\QRCodeDecoderException
  71. */
  72. protected static function checkFile(string $path):string{
  73. $path = trim($path);
  74. if(!file_exists($path) || !is_file($path) || !is_readable($path)){
  75. throw new QRCodeDecoderException('invalid file: '.$path);
  76. }
  77. $realpath = realpath($path);
  78. if($realpath === false){
  79. throw new QRCodeDecoderException('unable to resolve path: '.$path);
  80. }
  81. return $realpath;
  82. }
  83. }