Passed
Push — main ( 0a0d87...5e9cf0 )
by smiley
02:11
created

LuminanceSourceAbstract   A

Complexity

Total Complexity 15

Size/Duplication

Total Lines 74
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 24
dl 0
loc 74
rs 10
c 0
b 0
f 0
wmc 15

7 Methods

Rating   Name   Duplication   Size   Complexity  
A getWidth() 0 2 1
A checkFile() 0 14 5
A getMatrix() 0 2 1
A getRow() 0 11 3
A getHeight() 0 2 1
A setLuminancePixel() 0 6 3
A __construct() 0 6 1
1
<?php
2
/**
3
 * Class LuminanceSourceAbstract
4
 *
5
 * @created      24.01.2021
6
 * @author       ZXing Authors
7
 * @author       Smiley <[email protected]>
8
 * @copyright    2021 Smiley
9
 * @license      Apache-2.0
10
 */
11
12
namespace chillerlan\QRCode\Decoder;
13
14
use InvalidArgumentException;
15
use function array_slice, array_splice, file_exists, is_file, is_readable, realpath;
16
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. The interface
20
 * only provides immutable methods; therefore crop and rotation create copies. This is to ensure
21
 * that one Reader does not modify the original luminance source and leave it in an unknown state
22
 * for other Readers in the chain.
23
 *
24
 * @author [email protected] (Daniel Switkin)
25
 */
26
abstract class LuminanceSourceAbstract implements LuminanceSourceInterface{
27
28
	protected array $luminances;
29
	protected int   $width;
30
	protected int   $height;
31
32
	/**
33
	 *
34
	 */
35
	public function __construct(int $width, int $height){
36
		$this->width  = $width;
37
		$this->height = $height;
38
		// In order to measure pure decoding speed, we convert the entire image to a greyscale array
39
		// up front, which is the same as the Y channel of the YUVLuminanceSource in the real app.
40
		$this->luminances = [];
41
	}
42
43
	/** @inheritDoc */
44
	public function getMatrix():array{
45
		return $this->luminances;
46
	}
47
48
	/** @inheritDoc */
49
	public function getWidth():int{
50
		return $this->width;
51
	}
52
53
	/** @inheritDoc */
54
	public function getHeight():int{
55
		return $this->height;
56
	}
57
58
	/** @inheritDoc */
59
	public function getRow(int $y):array{
60
61
		if($y < 0 || $y >= $this->getHeight()){
62
			throw new InvalidArgumentException('Requested row is outside the image: '.$y);
63
		}
64
65
		$arr = [];
66
67
		array_splice($arr, 0, $this->width, array_slice($this->luminances, $y * $this->width, $this->width));
68
69
		return $arr;
70
	}
71
72
	/**
73
	 *
74
	 */
75
	protected function setLuminancePixel(int $r, int $g, int $b):void{
76
		$this->luminances[] = $r === $g && $g === $b
77
			// Image is already greyscale, so pick any channel.
78
			? $r // (($r + 128) % 256) - 128;
79
			// Calculate luminance cheaply, favoring green.
80
			: ($r + 2 * $g + $b) / 4; // (((($r + 2 * $g + $b) / 4) + 128) % 256) - 128;
81
	}
82
83
	/**
84
	 *
85
	 */
86
	protected static function checkFile(string $path):string{
87
		$path = trim($path);
88
89
		if(!file_exists($path) || !is_file($path) || !is_readable($path)){
90
			throw new InvalidArgumentException('invalid file: '.$path);
91
		}
92
93
		$realpath = realpath($path);
94
95
		if($realpath === false){
96
			throw new InvalidArgumentException('unable to resolve path: '.$path);
97
		}
98
99
		return $realpath;
100
	}
101
102
}
103