Completed
Push — master ( ef42ef...514bca )
by smiley
06:10
created

QRImage   A

Complexity

Total Complexity 20

Size/Duplication

Total Lines 158
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 4

Importance

Changes 0
Metric Value
dl 0
loc 158
rs 10
c 0
b 0
f 0
wmc 20
lcom 1
cbo 4
1
<?php
2
/**
3
 * Class QRImage
4
 *
5
 * @filesource   QRImage.php
6
 * @created      05.12.2015
7
 * @package      chillerlan\QRCode\Output
8
 * @author       Smiley <[email protected]>
9
 * @copyright    2015 Smiley
10
 * @license      MIT
11
 */
12
13
namespace chillerlan\QRCode\Output;
14
15
use chillerlan\QRCode\QRCode;
16
use Exception;
17
18
use function array_values, base64_encode, call_user_func, count, imagecolorallocate, imagecolortransparent,
19
	imagecreatetruecolor, imagedestroy, imagefilledrectangle, imagegif, imagejpeg, imagepng, in_array,
20
	is_array, ob_end_clean, ob_get_contents, ob_start, range, sprintf;
21
22
/**
23
 * Converts the matrix into GD images, raw or base64 output
24
 * requires ext-gd
25
 * @link http://php.net/manual/book.image.php
26
 */
27
class QRImage extends QROutputAbstract{
28
29
	protected const TRANSPARENCY_TYPES = [
30
		QRCode::OUTPUT_IMAGE_PNG,
31
		QRCode::OUTPUT_IMAGE_GIF,
32
	];
33
34
	protected string $defaultMode = QRCode::OUTPUT_IMAGE_PNG;
0 ignored issues
show
Bug introduced by
This code did not parse for me. Apparently, there is an error somewhere around this line:

Syntax error, unexpected T_STRING, expecting T_FUNCTION or T_CONST
Loading history...
35
36
	/**
37
	 * @see imagecreatetruecolor()
38
	 * @var resource
39
	 */
40
	protected $image;
41
42
	/**
43
	 * @inheritDoc
44
	 */
45
	protected function setModuleValues():void{
46
47
		foreach($this::DEFAULT_MODULE_VALUES as $M_TYPE => $defaultValue){
48
			$v = $this->options->moduleValues[$M_TYPE] ?? null;
49
50
			if(!is_array($v) || count($v) < 3){
51
				$this->moduleValues[$M_TYPE] = $defaultValue
52
					? [0, 0, 0]
53
					: [255, 255, 255];
54
			}
55
			else{
56
				$this->moduleValues[$M_TYPE] = array_values($v);
57
			}
58
59
		}
60
61
	}
62
63
	/**
64
	 * @inheritDoc
65
	 */
66
	public function dump(string $file = null):string{
67
		$this->image = imagecreatetruecolor($this->length, $this->length);
68
69
		// avoid: Indirect modification of overloaded property $imageTransparencyBG has no effect
70
		// https://stackoverflow.com/a/10455217
71
		$tbg = $this->options->imageTransparencyBG;
72
		$background  = imagecolorallocate($this->image, ...$tbg);
73
74
		if((bool)$this->options->imageTransparent && in_array($this->options->outputType, $this::TRANSPARENCY_TYPES, true)){
75
			imagecolortransparent($this->image, $background);
76
		}
77
78
		imagefilledrectangle($this->image, 0, 0, $this->length, $this->length, $background);
79
80
		foreach($this->matrix->matrix() as $y => $row){
81
			foreach($row as $x => $M_TYPE){
82
				$this->setPixel($x, $y, $this->moduleValues[$M_TYPE]);
83
			}
84
		}
85
86
		$imageData = $this->dumpImage($file);
87
88
		if((bool)$this->options->imageBase64){
89
			$imageData = sprintf('data:image/%s;base64,%s', $this->options->outputType, base64_encode($imageData));
90
		}
91
92
		return $imageData;
93
	}
94
95
	/**
96
	 *
97
	 */
98
	protected function setPixel(int $x, int $y, array $rgb):void{
99
		imagefilledrectangle(
100
			$this->image,
101
			$x * $this->scale,
102
			$y * $this->scale,
103
			($x + 1) * $this->scale,
104
			($y + 1) * $this->scale,
105
			imagecolorallocate($this->image, ...$rgb)
106
		);
107
	}
108
109
	/**
110
	 * @param string|null $file
111
	 *
112
	 * @return string
113
114
	 * @throws \chillerlan\QRCode\Output\QRCodeOutputException
115
	 */
116
	protected function dumpImage(string $file = null):string{
117
		$file ??= $this->options->cachefile;
118
119
		ob_start();
120
121
		try{
122
			call_user_func([$this, $this->outputMode ?? $this->defaultMode]);
123
		}
124
		// not going to cover edge cases
125
		// @codeCoverageIgnoreStart
126
		catch(Exception $e){
127
			throw new QRCodeOutputException($e->getMessage());
128
		}
129
		// @codeCoverageIgnoreEnd
130
131
		$imageData = ob_get_contents();
132
		imagedestroy($this->image);
133
134
		ob_end_clean();
135
136
		if($file !== null){
137
			$this->saveToFile($imageData, $file);
138
		}
139
140
		return $imageData;
141
	}
142
143
	/**
144
	 * @return void
145
	 */
146
	protected function png():void{
147
		imagepng(
148
			$this->image,
149
			null,
150
			in_array($this->options->pngCompression, range(-1, 9), true)
151
				? $this->options->pngCompression
152
				: -1
153
		);
154
	}
155
156
	/**
157
	 * Jiff - like... JitHub!
158
	 * @return void
159
	 */
160
	protected function gif():void{
161
		imagegif($this->image);
162
	}
163
164
	/**
165
	 * @return void
166
	 */
167
	protected function jpg():void{
168
		imagejpeg(
169
			$this->image,
170
			null,
171
			in_array($this->options->jpegQuality, range(0, 100), true)
172
				? $this->options->jpegQuality
173
				: 85
174
		);
175
	}
176
177
}
178