Passed
Push — main ( 278554...709a03 )
by smiley
01:53
created

QRImagick::drawImage()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 10
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 5
nc 3
nop 0
dl 0
loc 10
rs 10
c 1
b 0
f 0
1
<?php
2
/**
3
 * Class QRImagick
4
 *
5
 * @created      04.07.2018
6
 * @author       smiley <[email protected]>
7
 * @copyright    2018 smiley
8
 * @license      MIT
9
 *
10
 * @noinspection PhpComposerExtensionStubsInspection
11
 */
12
13
namespace chillerlan\QRCode\Output;
14
15
use chillerlan\QRCode\Data\QRMatrix;
16
use chillerlan\Settings\SettingsContainerInterface;
17
use Imagick, ImagickDraw, ImagickPixel;
18
19
use function extension_loaded, is_string;
20
21
/**
22
 * ImageMagick output module (requires ext-imagick)
23
 *
24
 * @see http://php.net/manual/book.imagick.php
25
 * @see http://phpimagick.com
26
 */
27
class QRImagick extends QROutputAbstract{
28
29
	protected Imagick $imagick;
30
	protected ImagickDraw $imagickDraw;
31
32
	/**
33
	 * @inheritDoc
34
	 *
35
	 * @throws \chillerlan\QRCode\Output\QRCodeOutputException
36
	 */
37
	public function __construct(SettingsContainerInterface $options, QRMatrix $matrix){
38
39
		if(!extension_loaded('imagick')){
40
			throw new QRCodeOutputException('ext-imagick not loaded'); // @codeCoverageIgnore
41
		}
42
43
		parent::__construct($options, $matrix);
44
	}
45
46
	/**
47
	 * @inheritDoc
48
	 */
49
	protected function setModuleValues():void{
50
51
		foreach($this::DEFAULT_MODULE_VALUES as $type => $defaultValue){
52
			$v = $this->options->moduleValues[$type] ?? null;
53
54
			if(!is_string($v)){
55
				$this->moduleValues[$type] = $defaultValue
56
					? new ImagickPixel($this->options->markupDark)
57
					: new ImagickPixel($this->options->markupLight);
58
			}
59
			else{
60
				$this->moduleValues[$type] = new ImagickPixel($v);
61
			}
62
		}
63
	}
64
65
	/**
66
	 * @inheritDoc
67
	 *
68
	 * @return string|\Imagick
69
	 */
70
	public function dump(string $file = null){
71
		$file ??= $this->options->cachefile;
72
		$this->imagick = new Imagick;
73
74
		$this->imagick->newImage(
75
			$this->length,
76
			$this->length,
77
			new ImagickPixel($this->options->imagickBG ?? 'transparent'),
78
			$this->options->imagickFormat
79
		);
80
81
		$this->drawImage();
82
83
		if($this->options->returnResource){
84
			return $this->imagick;
85
		}
86
87
		$imageData = $this->imagick->getImageBlob();
88
89
		$this->imagick->destroy();
90
91
		if($file !== null){
92
			$this->saveToFile($imageData, $file);
93
		}
94
95
		return $imageData;
96
	}
97
98
	/**
99
	 * Creates the QR image via ImagickDraw
100
	 */
101
	protected function drawImage():void{
102
		$this->imagickDraw = new ImagickDraw;
103
104
		foreach($this->matrix->matrix() as $y => $row){
105
			foreach($row as $x => $M_TYPE){
106
				$this->setPixel($x, $y, $M_TYPE);
107
			}
108
		}
109
110
		$this->imagick->drawImage($this->imagickDraw);
111
	}
112
113
	/**
114
	 * draws a single pixel at the given position
115
	 */
116
	protected function setPixel(int $x, int $y, int $M_TYPE):void{
117
		$this->imagickDraw->setStrokeColor($this->moduleValues[$M_TYPE]);
118
		$this->imagickDraw->setFillColor($this->moduleValues[$M_TYPE]);
119
120
		$this->options->drawCircularModules && !$this->matrix->checkTypes($x, $y, $this->options->keepAsSquare)
0 ignored issues
show
Bug introduced by
It seems like $this->options->keepAsSquare can also be of type null; however, parameter $M_TYPES of chillerlan\QRCode\Data\QRMatrix::checkTypes() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

120
		$this->options->drawCircularModules && !$this->matrix->checkTypes($x, $y, /** @scrutinizer ignore-type */ $this->options->keepAsSquare)
Loading history...
121
			? $this->imagickDraw->circle(
122
				($x + 0.5) * $this->scale,
123
				($y + 0.5) * $this->scale,
124
				($x + 0.5 + $this->options->circleRadius) * $this->scale,
125
				($y + 0.5) * $this->scale
126
			)
127
			: $this->imagickDraw->rectangle(
128
				$x * $this->scale,
129
				$y * $this->scale,
130
				($x + 1) * $this->scale,
131
				($y + 1) * $this->scale
132
		);
133
	}
134
135
}
136