%PDF- <> %âãÏÓ endobj 2 0 obj <> endobj 3 0 obj <>/ExtGState<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/Annots[ 28 0 R 29 0 R] /MediaBox[ 0 0 595.5 842.25] /Contents 4 0 R/Group<>/Tabs/S>> endobj ºaâÚÎΞ-ÌE1ÍØÄ÷{òò2ÿ ÛÖ^ÔÀá TÎ{¦?§®¥kuµùÕ5sLOšuY>endobj 2 0 obj<>endobj 2 0 obj<>endobj 2 0 obj<>endobj 2 0 obj<> endobj 2 0 obj<>endobj 2 0 obj<>es 3 0 R>> endobj 2 0 obj<> ox[ 0.000000 0.000000 609.600000 935.600000]/Fi endobj 3 0 obj<> endobj 7 1 obj<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI]>>/Subtype/Form>> stream
<?php /* * Copyright 2007 ZXing authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace Zxing\Common; /** * <p>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.</p> * * @author Sean Owen */ final class PerspectiveTransform { private function __construct(private $a11, private $a21, private $a31, private $a12, private $a22, private $a32, private $a13, private $a23, private $a33) { } public static 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 { $qToS = self::quadrilateralToSquare($x0, $y0, $x1, $y1, $x2, $y2, $x3, $y3); $sToQ = self::squareToQuadrilateral($x0p, $y0p, $x1p, $y1p, $x2p, $y2p, $x3p, $y3p); return $sToQ->times($qToS); } public static 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 self::squareToQuadrilateral($x0, $y0, $x1, $y1, $x2, $y2, $x3, $y3)->buildAdjoint(); } public function buildAdjoint(): \Zxing\Common\PerspectiveTransform { // Adjoint is the transpose of the cofactor matrix: return new PerspectiveTransform( $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 ); } public static function squareToQuadrilateral( float $x0, float $y0, float $x1, float $y1, float $x2, float $y2, float $x3, float $y3 ): \Zxing\Common\PerspectiveTransform { $dx3 = $x0 - $x1 + $x2 - $x3; $dy3 = $y0 - $y1 + $y2 - $y3; if ($dx3 == 0.0 && $dy3 == 0.0) { // Affine return new PerspectiveTransform( $x1 - $x0, $x2 - $x1, $x0, $y1 - $y0, $y2 - $y1, $y0, 0.0, 0.0, 1.0 ); } else { $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 new PerspectiveTransform( $x1 - $x0 + $a13 * $x1, $x3 - $x0 + $a23 * $x3, $x0, $y1 - $y0 + $a13 * $y1, $y3 - $y0 + $a23 * $y3, $y0, $a13, $a23, 1.0 ); } } public function times(self $other): \Zxing\Common\PerspectiveTransform { return new PerspectiveTransform( $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 ); } /** * @param (float|mixed)[] $points * * @psalm-param array<int, float|mixed> $points */ public function transformPoints(array &$points, &$yValues = 0): void { if ($yValues) { $this->transformPoints_($points, $yValues); return; } $max = is_countable($points) ? count($points) : 0; $a11 = $this->a11; $a12 = $this->a12; $a13 = $this->a13; $a21 = $this->a21; $a22 = $this->a22; $a23 = $this->a23; $a31 = $this->a31; $a32 = $this->a32; $a33 = $this->a33; for ($i = 0; $i < $max; $i += 2) { $x = $points[$i]; $y = $points[$i + 1]; $denominator = $a13 * $x + $a23 * $y + $a33; // TODO: think what we do if $denominator == 0 (division by zero) if ($denominator != 0.0) { $points[$i] = ($a11 * $x + $a21 * $y + $a31) / $denominator; $points[$i + 1] = ($a12 * $x + $a22 * $y + $a32) / $denominator; } } } /** * @param (float|mixed)[] $xValues * * @psalm-param array<int, float|mixed> $xValues */ public function transformPoints_(array &$xValues, &$yValues): void { $n = is_countable($xValues) ? count($xValues) : 0; for ($i = 0; $i < $n; $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; } } }