GDLuminanceSource.php 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. <?php
  2. namespace Zxing;
  3. /**
  4. * This class is used to help decode images from files which arrive as GD Resource
  5. * It does not support rotation.
  6. *
  7. *
  8. *
  9. */
  10. final class GDLuminanceSource extends LuminanceSource
  11. {
  12. public $luminances;
  13. private $dataWidth;
  14. private $dataHeight;
  15. private $left;
  16. private $top;
  17. private $gdImage;
  18. public function __construct(
  19. $gdImage,
  20. $dataWidth,
  21. $dataHeight,
  22. $left = null,
  23. $top = null,
  24. $width = null,
  25. $height = null
  26. ) {
  27. if (!$left && !$top && !$width && !$height) {
  28. $this->GDLuminanceSource($gdImage, $dataWidth, $dataHeight);
  29. return;
  30. }
  31. parent::__construct($width, $height);
  32. if ($left + $width > $dataWidth || $top + $height > $dataHeight) {
  33. throw new \InvalidArgumentException("Crop rectangle does not fit within image data.");
  34. }
  35. $this->luminances = $gdImage;
  36. $this->dataWidth = $dataWidth;
  37. $this->dataHeight = $dataHeight;
  38. $this->left = $left;
  39. $this->top = $top;
  40. }
  41. public function GDLuminanceSource($gdImage, $width, $height)
  42. {
  43. parent::__construct($width, $height);
  44. $this->dataWidth = $width;
  45. $this->dataHeight = $height;
  46. $this->left = 0;
  47. $this->top = 0;
  48. $this->$gdImage = $gdImage;
  49. // In order to measure pure decoding speed, we convert the entire image to a greyscale array
  50. // up front, which is the same as the Y channel of the YUVLuminanceSource in the real app.
  51. $this->luminances = [];
  52. //$this->luminances = $this->grayScaleToBitmap($this->grayscale());
  53. $array = [];
  54. $rgb = [];
  55. for ($j = 0; $j < $height; $j++) {
  56. for ($i = 0; $i < $width; $i++) {
  57. $argb = imagecolorat($this->$gdImage, $i, $j);
  58. $pixel = imagecolorsforindex($this->$gdImage, $argb);
  59. $r = $pixel['red'];
  60. $g = $pixel['green'];
  61. $b = $pixel['blue'];
  62. if ($r == $g && $g == $b) {
  63. // Image is already greyscale, so pick any channel.
  64. $this->luminances[] = $r;//(($r + 128) % 256) - 128;
  65. } else {
  66. // Calculate luminance cheaply, favoring green.
  67. $this->luminances[] = ($r + 2 * $g + $b) / 4;//(((($r + 2 * $g + $b) / 4) + 128) % 256) - 128;
  68. }
  69. }
  70. }
  71. /*
  72. for ($y = 0; $y < $height; $y++) {
  73. $offset = $y * $width;
  74. for ($x = 0; $x < $width; $x++) {
  75. $pixel = $pixels[$offset + $x];
  76. $r = ($pixel >> 16) & 0xff;
  77. $g = ($pixel >> 8) & 0xff;
  78. $b = $pixel & 0xff;
  79. if ($r == $g && $g == $b) {
  80. // Image is already greyscale, so pick any channel.
  81. $this->luminances[(int)($offset + $x)] = (($r+128) % 256) - 128;
  82. } else {
  83. // Calculate luminance cheaply, favoring green.
  84. $this->luminances[(int)($offset + $x)] = (((($r + 2 * $g + $b) / 4)+128)%256) - 128;
  85. }
  86. }
  87. */
  88. //}
  89. // $this->luminances = $this->grayScaleToBitmap($this->luminances);
  90. }
  91. //@Override
  92. public function getRow($y, $row = null)
  93. {
  94. if ($y < 0 || $y >= $this->getHeight()) {
  95. throw new \InvalidArgumentException('Requested row is outside the image: ' . $y);
  96. }
  97. $width = $this->getWidth();
  98. if ($row == null || count($row) < $width) {
  99. $row = [];
  100. }
  101. $offset = ($y + $this->top) * $this->dataWidth + $this->left;
  102. $row = arraycopy($this->luminances, $offset, $row, 0, $width);
  103. return $row;
  104. }
  105. //@Override
  106. public function getMatrix()
  107. {
  108. $width = $this->getWidth();
  109. $height = $this->getHeight();
  110. // If the caller asks for the entire underlying image, save the copy and give them the
  111. // original data. The docs specifically warn that result.length must be ignored.
  112. if ($width == $this->dataWidth && $height == $this->dataHeight) {
  113. return $this->luminances;
  114. }
  115. $area = $width * $height;
  116. $matrix = [];
  117. $inputOffset = $this->top * $this->dataWidth + $this->left;
  118. // If the width matches the full width of the underlying data, perform a single copy.
  119. if ($width == $this->dataWidth) {
  120. $matrix = arraycopy($this->luminances, $inputOffset, $matrix, 0, $area);
  121. return $matrix;
  122. }
  123. // Otherwise copy one cropped row at a time.
  124. $rgb = $this->luminances;
  125. for ($y = 0; $y < $height; $y++) {
  126. $outputOffset = $y * $width;
  127. $matrix = arraycopy($rgb, $inputOffset, $matrix, $outputOffset, $width);
  128. $inputOffset += $this->dataWidth;
  129. }
  130. return $matrix;
  131. }
  132. //@Override
  133. public function isCropSupported()
  134. {
  135. return true;
  136. }
  137. //@Override
  138. public function crop($left, $top, $width, $height)
  139. {
  140. return new GDLuminanceSource($this->luminances,
  141. $this->dataWidth,
  142. $this->dataHeight,
  143. $this->left + $left,
  144. $this->top + $top,
  145. $width,
  146. $height);
  147. }
  148. }