Explorar el Código

:shower: replaced generic exceptions

codemasher hace 4 años
padre
commit
21b414cab0

+ 2 - 3
src/Decoder/Binarizer.php

@@ -11,7 +11,6 @@
 
 
 namespace chillerlan\QRCode\Decoder;
 namespace chillerlan\QRCode\Decoder;
 
 
-use RuntimeException;
 use function array_fill, count, max;
 use function array_fill, count, max;
 
 
 /**
 /**
@@ -55,7 +54,7 @@ final class Binarizer{
 	}
 	}
 
 
 	/**
 	/**
-	 * @throws \RuntimeException
+	 * @throws \chillerlan\QRCode\Decoder\QRCodeDecoderException
 	 */
 	 */
 	private function estimateBlackPoint(array $buckets):int{
 	private function estimateBlackPoint(array $buckets):int{
 		// Find the tallest peak in the histogram.
 		// Find the tallest peak in the histogram.
@@ -101,7 +100,7 @@ final class Binarizer{
 		// If there is too little contrast in the image to pick a meaningful black point, throw rather
 		// If there is too little contrast in the image to pick a meaningful black point, throw rather
 		// than waste time trying to decode the image, and risk false positives.
 		// than waste time trying to decode the image, and risk false positives.
 		if($secondPeak - $firstPeak <= $numBuckets / 16){
 		if($secondPeak - $firstPeak <= $numBuckets / 16){
-			throw new RuntimeException('no meaningful dark point found');
+			throw new QRCodeDecoderException('no meaningful dark point found');
 		}
 		}
 
 
 		// Find a valley between them that is low and closer to the white peak.
 		// Find a valley between them that is low and closer to the white peak.

+ 14 - 15
src/Decoder/BitMatrix.php

@@ -12,7 +12,6 @@
 namespace chillerlan\QRCode\Decoder;
 namespace chillerlan\QRCode\Decoder;
 
 
 use chillerlan\QRCode\Common\{FormatInformation, Version};
 use chillerlan\QRCode\Common\{FormatInformation, Version};
-use InvalidArgumentException, RuntimeException;
 use function array_fill, count;
 use function array_fill, count;
 use const PHP_INT_MAX, PHP_INT_SIZE;
 use const PHP_INT_MAX, PHP_INT_SIZE;
 
 
@@ -74,23 +73,23 @@ final class BitMatrix{
 	 * @param int $width  ;  The width of the region
 	 * @param int $width  ;  The width of the region
 	 * @param int $height ;  The height of the region
 	 * @param int $height ;  The height of the region
 	 *
 	 *
-	 * @throws \InvalidArgumentException
+	 * @throws \chillerlan\QRCode\Decoder\QRCodeDecoderException
 	 */
 	 */
 	public function setRegion(int $left, int $top, int $width, int $height):self{
 	public function setRegion(int $left, int $top, int $width, int $height):self{
 
 
 		if($top < 0 || $left < 0){
 		if($top < 0 || $left < 0){
-			throw new InvalidArgumentException('Left and top must be nonnegative');
+			throw new QRCodeDecoderException('Left and top must be non-negative');
 		}
 		}
 
 
 		if($height < 1 || $width < 1){
 		if($height < 1 || $width < 1){
-			throw new InvalidArgumentException('Height and width must be at least 1');
+			throw new QRCodeDecoderException('Height and width must be at least 1');
 		}
 		}
 
 
 		$right  = $left + $width;
 		$right  = $left + $width;
 		$bottom = $top + $height;
 		$bottom = $top + $height;
 
 
 		if($bottom > $this->dimension || $right > $this->dimension){
 		if($bottom > $this->dimension || $right > $this->dimension){
-			throw new InvalidArgumentException('The region must fit inside the matrix');
+			throw new QRCodeDecoderException('The region must fit inside the matrix');
 		}
 		}
 
 
 		for($y = $top; $y < $bottom; $y++){
 		for($y = $top; $y < $bottom; $y++){
@@ -256,7 +255,7 @@ final class BitMatrix{
 	 * QR Code.
 	 * QR Code.
 	 *
 	 *
 	 * @return array bytes encoded within the QR Code
 	 * @return array bytes encoded within the QR Code
-	 * @throws \RuntimeException if the exact number of bytes expected is not read
+	 * @throws \chillerlan\QRCode\Decoder\QRCodeDecoderException if the exact number of bytes expected is not read
 	 */
 	 */
 	public function readCodewords():array{
 	public function readCodewords():array{
 		$this->formatInfo = $this->readFormatInformation();
 		$this->formatInfo = $this->readFormatInformation();
@@ -308,7 +307,7 @@ final class BitMatrix{
 		}
 		}
 
 
 		if($resultOffset !== $this->version->getTotalCodewords()){
 		if($resultOffset !== $this->version->getTotalCodewords()){
-			throw new RuntimeException('offset differs from total codewords for version');
+			throw new QRCodeDecoderException('offset differs from total codewords for version');
 		}
 		}
 
 
 		return $result;
 		return $result;
@@ -317,9 +316,9 @@ final class BitMatrix{
 	/**
 	/**
 	 * Reads format information from one of its two locations within the QR Code.
 	 * Reads format information from one of its two locations within the QR Code.
 	 *
 	 *
-	 * @return \chillerlan\QRCode\Common\FormatInformation encapsulating the QR Code's format info
-	 * @throws \RuntimeException                           if both format information locations cannot be parsed as
-	 *                                                     the valid encoding of format information
+	 * @return \chillerlan\QRCode\Common\FormatInformation       encapsulating the QR Code's format info
+	 * @throws \chillerlan\QRCode\Decoder\QRCodeDecoderException if both format information locations cannot be parsed as
+	 *                                                           the valid encoding of format information
 	 */
 	 */
 	private function readFormatInformation():FormatInformation{
 	private function readFormatInformation():FormatInformation{
 
 
@@ -372,7 +371,7 @@ final class BitMatrix{
 			return $this->formatInfo;
 			return $this->formatInfo;
 		}
 		}
 
 
-		throw new RuntimeException('failed to read format info');
+		throw new QRCodeDecoderException('failed to read format info');
 	}
 	}
 
 
 	/**
 	/**
@@ -424,9 +423,9 @@ final class BitMatrix{
 	/**
 	/**
 	 * Reads version information from one of its two locations within the QR Code.
 	 * Reads version information from one of its two locations within the QR Code.
 	 *
 	 *
-	 * @return \chillerlan\QRCode\Common\Version encapsulating the QR Code's version
-	 * @throws \RuntimeException                 if both version information locations cannot be parsed as
-	 *                                           the valid encoding of version information
+	 * @return \chillerlan\QRCode\Common\Version                 encapsulating the QR Code's version
+	 * @throws \chillerlan\QRCode\Decoder\QRCodeDecoderException if both version information locations cannot be parsed as
+	 *                                                           the valid encoding of version information
 	 */
 	 */
 	private function readVersion():Version{
 	private function readVersion():Version{
 
 
@@ -471,7 +470,7 @@ final class BitMatrix{
 			return $this->version;
 			return $this->version;
 		}
 		}
 
 
-		throw new RuntimeException('failed to read version');
+		throw new QRCodeDecoderException('failed to read version');
 	}
 	}
 
 
 	/**
 	/**

+ 10 - 12
src/Decoder/Decoder.php

@@ -11,7 +11,7 @@
 
 
 namespace chillerlan\QRCode\Decoder;
 namespace chillerlan\QRCode\Decoder;
 
 
-use InvalidArgumentException, RuntimeException, Throwable;
+use Throwable;
 use chillerlan\QRCode\Common\{BitBuffer, EccLevel, Mode, ReedSolomonDecoder, Version};
 use chillerlan\QRCode\Common\{BitBuffer, EccLevel, Mode, ReedSolomonDecoder, Version};
 use chillerlan\QRCode\Data\{AlphaNum, Byte, ECI, Kanji, Number};
 use chillerlan\QRCode\Data\{AlphaNum, Byte, ECI, Kanji, Number};
 use chillerlan\QRCode\Detector\Detector;
 use chillerlan\QRCode\Detector\Detector;
@@ -33,8 +33,8 @@ final class Decoder{
 	 *
 	 *
 	 * @param \chillerlan\QRCode\Decoder\LuminanceSourceInterface $source
 	 * @param \chillerlan\QRCode\Decoder\LuminanceSourceInterface $source
 	 *
 	 *
-	 * @return \chillerlan\QRCode\Decoder\DecoderResult text and bytes encoded within the QR Code
-	 * @throws \Throwable if the QR Code cannot be decoded
+	 * @return \chillerlan\QRCode\Decoder\DecoderResult                     text and bytes encoded within the QR Code
+	 * @throws \Throwable|\chillerlan\QRCode\Decoder\QRCodeDecoderException if the QR Code cannot be decoded
 	 */
 	 */
 	public function decode(LuminanceSourceInterface $source):DecoderResult{
 	public function decode(LuminanceSourceInterface $source):DecoderResult{
 		$bitMatrix = (new Detector($source))->detect();
 		$bitMatrix = (new Detector($source))->detect();
@@ -66,9 +66,7 @@ final class Decoder{
 	}
 	}
 
 
 	/**
 	/**
-	 * @param \chillerlan\QRCode\Decoder\BitMatrix $bitMatrix
-	 *
-	 * @return \chillerlan\QRCode\Decoder\DecoderResult
+	 * @throws \chillerlan\QRCode\Decoder\QRCodeDecoderException
 	 */
 	 */
 	private function decodeMatrix(BitMatrix $bitMatrix):DecoderResult{
 	private function decodeMatrix(BitMatrix $bitMatrix):DecoderResult{
 		// Read raw codewords
 		// Read raw codewords
@@ -78,7 +76,7 @@ final class Decoder{
 
 
 		// technically this shouldn't happen as the respective read meathods would throw first
 		// technically this shouldn't happen as the respective read meathods would throw first
 		if($version === null || $formatInfo === null){
 		if($version === null || $formatInfo === null){
-			throw new RuntimeException('unable to read version or ecc level');
+			throw new QRCodeDecoderException('unable to read version or ecc level');
 		}
 		}
 
 
 		$eccLevel = $formatInfo->getErrorCorrectionLevel();
 		$eccLevel = $formatInfo->getErrorCorrectionLevel();
@@ -114,12 +112,12 @@ final class Decoder{
 	 * @param \chillerlan\QRCode\Common\EccLevel $eccLevel     error-correction level of the QR Code
 	 * @param \chillerlan\QRCode\Common\EccLevel $eccLevel     error-correction level of the QR Code
 	 *
 	 *
 	 * @return array DataBlocks containing original bytes, "de-interleaved" from representation in the QR Code
 	 * @return array DataBlocks containing original bytes, "de-interleaved" from representation in the QR Code
-	 * @throws \InvalidArgumentException
+	 * @throws \chillerlan\QRCode\Decoder\QRCodeDecoderException
 	 */
 	 */
 	private function getDataBlocks(array $rawCodewords, Version $version, EccLevel $eccLevel):array{
 	private function getDataBlocks(array $rawCodewords, Version $version, EccLevel $eccLevel):array{
 
 
 		if(count($rawCodewords) !== $version->getTotalCodewords()){
 		if(count($rawCodewords) !== $version->getTotalCodewords()){
-			throw new InvalidArgumentException('$rawCodewords differ from total codewords for version');
+			throw new QRCodeDecoderException('$rawCodewords differ from total codewords for version');
 		}
 		}
 
 
 		// Figure out the number and size of data blocks used by this version and
 		// Figure out the number and size of data blocks used by this version and
@@ -210,7 +208,7 @@ final class Decoder{
 	}
 	}
 
 
 	/**
 	/**
-	 * @throws \RuntimeException
+	 * @throws \chillerlan\QRCode\Decoder\QRCodeDecoderException
 	 */
 	 */
 	private function decodeBitStream(array $bytes, Version $version, EccLevel $ecLevel):DecoderResult{
 	private function decodeBitStream(array $bytes, Version $version, EccLevel $ecLevel):DecoderResult{
 		$bits           = new BitBuffer($bytes);
 		$bits           = new BitBuffer($bytes);
@@ -242,7 +240,7 @@ final class Decoder{
 			}
 			}
 			elseif($datamode === Mode::STRCTURED_APPEND){
 			elseif($datamode === Mode::STRCTURED_APPEND){
 				if($bits->available() < 16){
 				if($bits->available() < 16){
-					throw new RuntimeException('structured append: not enough bits left');
+					throw new QRCodeDecoderException('structured append: not enough bits left');
 				}
 				}
 				// sequence number and parity is added later to the result metadata
 				// sequence number and parity is added later to the result metadata
 				// Read next 8 bits (symbol sequence #) and 8 bits (parity data), then continue
 				// Read next 8 bits (symbol sequence #) and 8 bits (parity data), then continue
@@ -312,7 +310,7 @@ final class Decoder{
 						$result .= Kanji::decodeSegment($bits, $versionNumber);
 						$result .= Kanji::decodeSegment($bits, $versionNumber);
 					}
 					}
 					else{
 					else{
-						throw new RuntimeException('invalid data mode');
+						throw new QRCodeDecoderException('invalid data mode');
 					}
 					}
 #				}
 #				}
 			}
 			}

+ 2 - 3
src/Decoder/GDLuminanceSource.php

@@ -13,7 +13,6 @@
 
 
 namespace chillerlan\QRCode\Decoder;
 namespace chillerlan\QRCode\Decoder;
 
 
-use InvalidArgumentException;
 use function file_get_contents, get_resource_type, imagecolorat, imagecolorsforindex,
 use function file_get_contents, get_resource_type, imagecolorat, imagecolorsforindex,
 	imagecreatefromstring, imagesx, imagesy, is_resource;
 	imagecreatefromstring, imagesx, imagesy, is_resource;
 use const PHP_MAJOR_VERSION;
 use const PHP_MAJOR_VERSION;
@@ -34,7 +33,7 @@ final class GDLuminanceSource extends LuminanceSourceAbstract{
 	 *
 	 *
 	 * @param resource|\GdImage $gdImage
 	 * @param resource|\GdImage $gdImage
 	 *
 	 *
-	 * @throws \InvalidArgumentException
+	 * @throws \chillerlan\QRCode\Decoder\QRCodeDecoderException
 	 */
 	 */
 	public function __construct($gdImage){
 	public function __construct($gdImage){
 
 
@@ -43,7 +42,7 @@ final class GDLuminanceSource extends LuminanceSourceAbstract{
 			(PHP_MAJOR_VERSION >= 8 && !$gdImage instanceof \GdImage)
 			(PHP_MAJOR_VERSION >= 8 && !$gdImage instanceof \GdImage)
 			|| (PHP_MAJOR_VERSION < 8 && (!is_resource($gdImage) || get_resource_type($gdImage) !== 'gd'))
 			|| (PHP_MAJOR_VERSION < 8 && (!is_resource($gdImage) || get_resource_type($gdImage) !== 'gd'))
 		){
 		){
-			throw new InvalidArgumentException('Invalid GD image source.');
+			throw new QRCodeDecoderException('Invalid GD image source.');
 		}
 		}
 
 
 		parent::__construct(imagesx($gdImage), imagesy($gdImage));
 		parent::__construct(imagesx($gdImage), imagesy($gdImage));

+ 4 - 5
src/Decoder/LuminanceSourceAbstract.php

@@ -11,7 +11,6 @@
 
 
 namespace chillerlan\QRCode\Decoder;
 namespace chillerlan\QRCode\Decoder;
 
 
-use InvalidArgumentException;
 use function array_slice, array_splice, file_exists, is_file, is_readable, realpath;
 use function array_slice, array_splice, file_exists, is_file, is_readable, realpath;
 
 
 /**
 /**
@@ -59,7 +58,7 @@ abstract class LuminanceSourceAbstract implements LuminanceSourceInterface{
 	public function getRow(int $y):array{
 	public function getRow(int $y):array{
 
 
 		if($y < 0 || $y >= $this->getHeight()){
 		if($y < 0 || $y >= $this->getHeight()){
-			throw new InvalidArgumentException('Requested row is outside the image: '.$y);
+			throw new QRCodeDecoderException('Requested row is outside the image: '.$y);
 		}
 		}
 
 
 		$arr = [];
 		$arr = [];
@@ -81,19 +80,19 @@ abstract class LuminanceSourceAbstract implements LuminanceSourceInterface{
 	}
 	}
 
 
 	/**
 	/**
-	 *
+	 * @throws \chillerlan\QRCode\Decoder\QRCodeDecoderException
 	 */
 	 */
 	protected static function checkFile(string $path):string{
 	protected static function checkFile(string $path):string{
 		$path = trim($path);
 		$path = trim($path);
 
 
 		if(!file_exists($path) || !is_file($path) || !is_readable($path)){
 		if(!file_exists($path) || !is_file($path) || !is_readable($path)){
-			throw new InvalidArgumentException('invalid file: '.$path);
+			throw new QRCodeDecoderException('invalid file: '.$path);
 		}
 		}
 
 
 		$realpath = realpath($path);
 		$realpath = realpath($path);
 
 
 		if($realpath === false){
 		if($realpath === false){
-			throw new InvalidArgumentException('unable to resolve path: '.$path);
+			throw new QRCodeDecoderException('unable to resolve path: '.$path);
 		}
 		}
 
 
 		return $realpath;
 		return $realpath;

+ 1 - 0
src/Decoder/LuminanceSourceInterface.php

@@ -44,6 +44,7 @@ interface LuminanceSourceInterface{
 	 * @param int $y  The row to fetch, which must be in [0,getHeight())
 	 * @param int $y  The row to fetch, which must be in [0,getHeight())
 	 *
 	 *
 	 * @return array An array containing the luminance data.
 	 * @return array An array containing the luminance data.
+	 * @throws \chillerlan\QRCode\Decoder\QRCodeDecoderException
 	 */
 	 */
 	public function getRow(int $y):array;
 	public function getRow(int $y):array;
 
 

+ 15 - 0
src/Decoder/QRCodeDecoderException.php

@@ -0,0 +1,15 @@
+<?php
+/**
+ * Class QRCodeDecoderException
+ *
+ * @created      01.12.2021
+ * @author       smiley <smiley@chillerlan.net>
+ * @copyright    2021 smiley
+ * @license      MIT
+ */
+
+namespace chillerlan\QRCode\Decoder;
+
+use chillerlan\QRCode\QRCodeException;
+
+class QRCodeDecoderException extends QRCodeException{}

+ 5 - 6
src/Detector/Detector.php

@@ -12,7 +12,6 @@
 namespace chillerlan\QRCode\Detector;
 namespace chillerlan\QRCode\Detector;
 
 
 use chillerlan\QRCode\Decoder\{Binarizer, LuminanceSourceInterface};
 use chillerlan\QRCode\Decoder\{Binarizer, LuminanceSourceInterface};
-use RuntimeException;
 use chillerlan\QRCode\Common\Version;
 use chillerlan\QRCode\Common\Version;
 use chillerlan\QRCode\Decoder\BitMatrix;
 use chillerlan\QRCode\Decoder\BitMatrix;
 use function abs, is_nan, max, min, round;
 use function abs, is_nan, max, min, round;
@@ -78,7 +77,7 @@ final class Detector{
 	 * Computes an average estimated module size based on estimated derived from the positions
 	 * Computes an average estimated module size based on estimated derived from the positions
 	 * of the three finder patterns.
 	 * of the three finder patterns.
 	 *
 	 *
-	 * @throws \RuntimeException
+	 * @throws \chillerlan\QRCode\Detector\QRCodeDetectorException
 	 */
 	 */
 	private function calculateModuleSize(FinderPattern $topLeft, FinderPattern $topRight, FinderPattern $bottomLeft):float{
 	private function calculateModuleSize(FinderPattern $topLeft, FinderPattern $topRight, FinderPattern $bottomLeft):float{
 		// Take the average
 		// Take the average
@@ -88,7 +87,7 @@ final class Detector{
 		) / 2.0;
 		) / 2.0;
 
 
 		if($moduleSize < 1.0){
 		if($moduleSize < 1.0){
-			throw new RuntimeException('module size < 1.0');
+			throw new QRCodeDetectorException('module size < 1.0');
 		}
 		}
 
 
 		return $moduleSize;
 		return $moduleSize;
@@ -244,7 +243,7 @@ final class Detector{
 	 * Computes the dimension (number of modules on a size) of the QR Code based on the position
 	 * Computes the dimension (number of modules on a size) of the QR Code based on the position
 	 * of the finder patterns and estimated module size.
 	 * of the finder patterns and estimated module size.
 	 *
 	 *
-	 * @throws \RuntimeException
+	 * @throws \chillerlan\QRCode\Detector\QRCodeDetectorException
 	 */
 	 */
 	private function computeDimension(
 	private function computeDimension(
 		FinderPattern $topLeft,
 		FinderPattern $topLeft,
@@ -265,11 +264,11 @@ final class Detector{
 				$dimension--;
 				$dimension--;
 				break;
 				break;
 			case 3:
 			case 3:
-				throw new RuntimeException('estimated dimension: '.$dimension);
+				throw new QRCodeDetectorException('estimated dimension: '.$dimension);
 		}
 		}
 
 
 		if($dimension % 4 !== 1){
 		if($dimension % 4 !== 1){
-			throw new RuntimeException('dimension mod 4 is not 1');
+			throw new QRCodeDetectorException('dimension mod 4 is not 1');
 		}
 		}
 
 
 		return $dimension;
 		return $dimension;

+ 3 - 4
src/Detector/FinderPatternFinder.php

@@ -13,7 +13,6 @@
 
 
 namespace chillerlan\QRCode\Detector;
 namespace chillerlan\QRCode\Detector;
 
 
-use RuntimeException;
 use chillerlan\QRCode\Decoder\BitMatrix;
 use chillerlan\QRCode\Decoder\BitMatrix;
 use function abs, count, usort;
 use function abs, count, usort;
 use const PHP_FLOAT_MAX;
 use const PHP_FLOAT_MAX;
@@ -617,13 +616,13 @@ final class FinderPatternFinder{
 	 * @return \chillerlan\QRCode\Detector\FinderPattern[] the 3 best FinderPatterns from our list of candidates. The "best" are
 	 * @return \chillerlan\QRCode\Detector\FinderPattern[] the 3 best FinderPatterns from our list of candidates. The "best" are
 	 *         those that have been detected at least #CENTER_QUORUM times, and whose module
 	 *         those that have been detected at least #CENTER_QUORUM times, and whose module
 	 *         size differs from the average among those patterns the least
 	 *         size differs from the average among those patterns the least
-	 * @throws \RuntimeException if 3 such finder patterns do not exist
+	 * @throws \chillerlan\QRCode\Detector\QRCodeDetectorException if 3 such finder patterns do not exist
 	 */
 	 */
 	private function selectBestPatterns():array{
 	private function selectBestPatterns():array{
 		$startSize = count($this->possibleCenters);
 		$startSize = count($this->possibleCenters);
 
 
 		if($startSize < 3){
 		if($startSize < 3){
-			throw new RuntimeException('could not find enough finder patterns');
+			throw new QRCodeDetectorException('could not find enough finder patterns');
 		}
 		}
 
 
 		usort(
 		usort(
@@ -708,7 +707,7 @@ final class FinderPatternFinder{
 		}
 		}
 
 
 		if($distortion === PHP_FLOAT_MAX){
 		if($distortion === PHP_FLOAT_MAX){
-			throw new RuntimeException('finder patterns may be too distorted');
+			throw new QRCodeDetectorException('finder patterns may be too distorted');
 		}
 		}
 
 
 		return $bestPatterns;
 		return $bestPatterns;

+ 8 - 8
src/Detector/GridSampler.php

@@ -11,8 +11,8 @@
 
 
 namespace chillerlan\QRCode\Detector;
 namespace chillerlan\QRCode\Detector;
 
 
-use Exception, RuntimeException;
 use chillerlan\QRCode\Decoder\BitMatrix;
 use chillerlan\QRCode\Decoder\BitMatrix;
+use Throwable;
 use function array_fill, count, sprintf;
 use function array_fill, count, sprintf;
 
 
 /**
 /**
@@ -44,7 +44,7 @@ final class GridSampler{
 	 * @param \chillerlan\QRCode\Decoder\BitMatrix $bitMatrix image into which the points should map
 	 * @param \chillerlan\QRCode\Decoder\BitMatrix $bitMatrix image into which the points should map
 	 * @param float[]                  $points    actual points in x1,y1,...,xn,yn form
 	 * @param float[]                  $points    actual points in x1,y1,...,xn,yn form
 	 *
 	 *
-	 * @throws \RuntimeException if an endpoint is lies outside the image boundaries
+	 * @throws \chillerlan\QRCode\Detector\QRCodeDetectorException if an endpoint is lies outside the image boundaries
 	 */
 	 */
 	private function checkAndNudgePoints(BitMatrix $bitMatrix, array $points):void{
 	private function checkAndNudgePoints(BitMatrix $bitMatrix, array $points):void{
 		$dimension = $bitMatrix->getDimension();
 		$dimension = $bitMatrix->getDimension();
@@ -57,7 +57,7 @@ final class GridSampler{
 			$y = (int)$points[$offset + 1];
 			$y = (int)$points[$offset + 1];
 
 
 			if($x < -1 || $x > $dimension || $y < -1 || $y > $dimension){
 			if($x < -1 || $x > $dimension || $y < -1 || $y > $dimension){
-				throw new RuntimeException(sprintf('checkAndNudgePoints 1, x: %s, y: %s, d: %s', $x, $y, $dimension));
+				throw new QRCodeDetectorException(sprintf('checkAndNudgePoints 1, x: %s, y: %s, d: %s', $x, $y, $dimension));
 			}
 			}
 
 
 			$nudged = false;
 			$nudged = false;
@@ -87,7 +87,7 @@ final class GridSampler{
 			$y = (int)$points[$offset + 1];
 			$y = (int)$points[$offset + 1];
 
 
 			if($x < -1 || $x > $dimension || $y < -1 || $y > $dimension){
 			if($x < -1 || $x > $dimension || $y < -1 || $y > $dimension){
-				throw new RuntimeException(sprintf('checkAndNudgePoints 2, x: %s, y: %s, d: %s', $x, $y, $dimension));
+				throw new QRCodeDetectorException(sprintf('checkAndNudgePoints 2, x: %s, y: %s, d: %s', $x, $y, $dimension));
 			}
 			}
 
 
 			$nudged = false;
 			$nudged = false;
@@ -118,13 +118,13 @@ final class GridSampler{
 	 *
 	 *
 	 * @return \chillerlan\QRCode\Decoder\BitMatrix representing a grid of points sampled from the image within a region
 	 * @return \chillerlan\QRCode\Decoder\BitMatrix representing a grid of points sampled from the image within a region
 	 *   defined by the "from" parameters
 	 *   defined by the "from" parameters
-	 * @throws \RuntimeException if image can't be sampled, for example, if the transformation defined
+	 * @throws \chillerlan\QRCode\Detector\QRCodeDetectorException if image can't be sampled, for example, if the transformation defined
 	 *   by the given points is invalid or results in sampling outside the image boundaries
 	 *   by the given points is invalid or results in sampling outside the image boundaries
 	 */
 	 */
 	public function sampleGrid(BitMatrix $image, int $dimension, PerspectiveTransform $transform):BitMatrix{
 	public function sampleGrid(BitMatrix $image, int $dimension, PerspectiveTransform $transform):BitMatrix{
 
 
 		if($dimension <= 0){
 		if($dimension <= 0){
-			throw new RuntimeException('invalid matrix size');
+			throw new QRCodeDetectorException('invalid matrix size');
 		}
 		}
 
 
 		$bits   = new BitMatrix($dimension);
 		$bits   = new BitMatrix($dimension);
@@ -152,7 +152,7 @@ final class GridSampler{
 					}
 					}
 				}
 				}
 			}
 			}
-			catch(Exception $aioobe){//ArrayIndexOutOfBoundsException
+			catch(Throwable $aioobe){//ArrayIndexOutOfBoundsException
 				// This feels wrong, but, sometimes if the finder patterns are misidentified, the resulting
 				// This feels wrong, but, sometimes if the finder patterns are misidentified, the resulting
 				// transform gets "twisted" such that it maps a straight line of points to a set of points
 				// transform gets "twisted" such that it maps a straight line of points to a set of points
 				// whose endpoints are in bounds, but others are not. There is probably some mathematical
 				// whose endpoints are in bounds, but others are not. There is probably some mathematical
@@ -160,7 +160,7 @@ final class GridSampler{
 				// This results in an ugly runtime exception despite our clever checks above -- can't have
 				// This results in an ugly runtime exception despite our clever checks above -- can't have
 				// that. We could check each point's coordinates but that feels duplicative. We settle for
 				// that. We could check each point's coordinates but that feels duplicative. We settle for
 				// catching and wrapping ArrayIndexOutOfBoundsException.
 				// catching and wrapping ArrayIndexOutOfBoundsException.
-				throw new RuntimeException('ArrayIndexOutOfBoundsException');
+				throw new QRCodeDetectorException('ArrayIndexOutOfBoundsException');
 			}
 			}
 
 
 		}
 		}

+ 15 - 0
src/Detector/QRCodeDetectorException.php

@@ -0,0 +1,15 @@
+<?php
+/**
+ * Class QRCodeDetectorException
+ *
+ * @created      01.12.2021
+ * @author       smiley <smiley@chillerlan.net>
+ * @copyright    2021 smiley
+ * @license      MIT
+ */
+
+namespace chillerlan\QRCode\Detector;
+
+use chillerlan\QRCode\QRCodeException;
+
+class QRCodeDetectorException extends QRCodeException{}