aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/chillerlan/php-qrcode/src/Detector/PerspectiveTransform.php
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/chillerlan/php-qrcode/src/Detector/PerspectiveTransform.php')
-rw-r--r--vendor/chillerlan/php-qrcode/src/Detector/PerspectiveTransform.php182
1 files changed, 182 insertions, 0 deletions
diff --git a/vendor/chillerlan/php-qrcode/src/Detector/PerspectiveTransform.php b/vendor/chillerlan/php-qrcode/src/Detector/PerspectiveTransform.php
new file mode 100644
index 000000000..7964092e3
--- /dev/null
+++ b/vendor/chillerlan/php-qrcode/src/Detector/PerspectiveTransform.php
@@ -0,0 +1,182 @@
+<?php
+/**
+ * Class PerspectiveTransform
+ *
+ * @created 17.01.2021
+ * @author ZXing Authors
+ * @author Smiley <smiley@chillerlan.net>
+ * @copyright 2021 Smiley
+ * @license Apache-2.0
+ */
+
+namespace chillerlan\QRCode\Detector;
+
+use function count;
+
+/**
+ * This class implements a perspective transform in two dimensions. Given four source and four
+ * destination points, it will compute the transformation implied between them. The code is based
+ * directly upon section 3.4.2 of George Wolberg's "Digital Image Warping"; see pages 54-56.
+ *
+ * @author Sean Owen
+ */
+final class PerspectiveTransform{
+
+ private float $a11;
+ private float $a12;
+ private float $a13;
+ private float $a21;
+ private float $a22;
+ private float $a23;
+ private float $a31;
+ private float $a32;
+ private float $a33;
+
+ /**
+ *
+ */
+ private function set(
+ float $a11, float $a21, float $a31,
+ float $a12, float $a22, float $a32,
+ float $a13, float $a23, float $a33
+ ):self{
+ $this->a11 = $a11;
+ $this->a12 = $a12;
+ $this->a13 = $a13;
+ $this->a21 = $a21;
+ $this->a22 = $a22;
+ $this->a23 = $a23;
+ $this->a31 = $a31;
+ $this->a32 = $a32;
+ $this->a33 = $a33;
+
+ return $this;
+ }
+
+ /**
+ * @SuppressWarnings(PHPMD.ExcessiveParameterList)
+ */
+ public function quadrilateralToQuadrilateral(
+ float $x0, float $y0, float $x1, float $y1, float $x2, float $y2, float $x3, float $y3,
+ float $x0p, float $y0p, float $x1p, float $y1p, float $x2p, float $y2p, float $x3p, float $y3p
+ ):self{
+ return (new self)
+ ->squareToQuadrilateral($x0p, $y0p, $x1p, $y1p, $x2p, $y2p, $x3p, $y3p)
+ ->times($this->quadrilateralToSquare($x0, $y0, $x1, $y1, $x2, $y2, $x3, $y3));
+ }
+
+ /**
+ *
+ */
+ private function quadrilateralToSquare(
+ float $x0, float $y0, float $x1, float $y1,
+ float $x2, float $y2, float $x3, float $y3
+ ):self{
+ // Here, the adjoint serves as the inverse:
+ return $this
+ ->squareToQuadrilateral($x0, $y0, $x1, $y1, $x2, $y2, $x3, $y3)
+ ->buildAdjoint();
+ }
+
+ /**
+ *
+ */
+ private function buildAdjoint():self{
+ // Adjoint is the transpose of the cofactor matrix:
+ return $this->set(
+ ($this->a22 * $this->a33 - $this->a23 * $this->a32),
+ ($this->a23 * $this->a31 - $this->a21 * $this->a33),
+ ($this->a21 * $this->a32 - $this->a22 * $this->a31),
+ ($this->a13 * $this->a32 - $this->a12 * $this->a33),
+ ($this->a11 * $this->a33 - $this->a13 * $this->a31),
+ ($this->a12 * $this->a31 - $this->a11 * $this->a32),
+ ($this->a12 * $this->a23 - $this->a13 * $this->a22),
+ ($this->a13 * $this->a21 - $this->a11 * $this->a23),
+ ($this->a11 * $this->a22 - $this->a12 * $this->a21)
+ );
+ }
+
+ /**
+ *
+ */
+ private function squareToQuadrilateral(
+ float $x0, float $y0, float $x1, float $y1,
+ float $x2, float $y2, float $x3, float $y3
+ ):self{
+ $dx3 = ($x0 - $x1 + $x2 - $x3);
+ $dy3 = ($y0 - $y1 + $y2 - $y3);
+
+ if($dx3 === 0.0 && $dy3 === 0.0){
+ // Affine
+ return $this->set(($x1 - $x0), ($x2 - $x1), $x0, ($y1 - $y0), ($y2 - $y1), $y0, 0.0, 0.0, 1.0);
+ }
+
+ $dx1 = ($x1 - $x2);
+ $dx2 = ($x3 - $x2);
+ $dy1 = ($y1 - $y2);
+ $dy2 = ($y3 - $y2);
+ $denominator = ($dx1 * $dy2 - $dx2 * $dy1);
+ $a13 = (($dx3 * $dy2 - $dx2 * $dy3) / $denominator);
+ $a23 = (($dx1 * $dy3 - $dx3 * $dy1) / $denominator);
+
+ return $this->set(
+ ($x1 - $x0 + $a13 * $x1),
+ ($x3 - $x0 + $a23 * $x3),
+ $x0,
+ ($y1 - $y0 + $a13 * $y1),
+ ($y3 - $y0 + $a23 * $y3),
+ $y0,
+ $a13,
+ $a23,
+ 1.0
+ );
+ }
+
+ /**
+ *
+ */
+ private function times(PerspectiveTransform $other):self{
+ return $this->set(
+ ($this->a11 * $other->a11 + $this->a21 * $other->a12 + $this->a31 * $other->a13),
+ ($this->a11 * $other->a21 + $this->a21 * $other->a22 + $this->a31 * $other->a23),
+ ($this->a11 * $other->a31 + $this->a21 * $other->a32 + $this->a31 * $other->a33),
+ ($this->a12 * $other->a11 + $this->a22 * $other->a12 + $this->a32 * $other->a13),
+ ($this->a12 * $other->a21 + $this->a22 * $other->a22 + $this->a32 * $other->a23),
+ ($this->a12 * $other->a31 + $this->a22 * $other->a32 + $this->a32 * $other->a33),
+ ($this->a13 * $other->a11 + $this->a23 * $other->a12 + $this->a33 * $other->a13),
+ ($this->a13 * $other->a21 + $this->a23 * $other->a22 + $this->a33 * $other->a23),
+ ($this->a13 * $other->a31 + $this->a23 * $other->a32 + $this->a33 * $other->a33)
+ );
+ }
+
+ /**
+ * @return array[] [$xValues, $yValues]
+ */
+ public function transformPoints(array $xValues, ?array $yValues = null):array{
+ $max = count($xValues);
+
+ if($yValues !== null){ // unused
+
+ for($i = 0; $i < $max; $i++){
+ $x = $xValues[$i];
+ $y = $yValues[$i];
+ $denominator = ($this->a13 * $x + $this->a23 * $y + $this->a33);
+ $xValues[$i] = (($this->a11 * $x + $this->a21 * $y + $this->a31) / $denominator);
+ $yValues[$i] = (($this->a12 * $x + $this->a22 * $y + $this->a32) / $denominator);
+ }
+
+ return [$xValues, $yValues];
+ }
+
+ for($i = 0; $i < $max; $i += 2){
+ $x = $xValues[$i];
+ $y = $xValues[($i + 1)];
+ $denominator = ($this->a13 * $x + $this->a23 * $y + $this->a33);
+ $xValues[$i] = (($this->a11 * $x + $this->a21 * $y + $this->a31) / $denominator);
+ $xValues[($i + 1)] = (($this->a12 * $x + $this->a22 * $y + $this->a32) / $denominator);
+ }
+
+ return [$xValues, []];
+ }
+
+}