Test Failed
Push — master ( 1c3827...8aff3a )
by smiley
03:00
created

QRImage::setModuleValues()   A

Complexity

Conditions 5
Paths 4

Size

Total Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
nc 4
nop 0
dl 0
loc 17
rs 9.3888
c 0
b 0
f 0
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
17
/**
18
 * Converts the matrix into GD images, raw or base64 output
19
 * requires ext-gd
20
 * @link http://php.net/manual/book.image.php
21
 */
22
class QRImage extends QROutputAbstract{
23
24
	protected const TRANSPARENCY_TYPES = [
25
		QRCode::OUTPUT_IMAGE_PNG,
26
		QRCode::OUTPUT_IMAGE_GIF,
27
	];
28
29
	/**
30
	 * @var string
31
	 */
32
	protected $defaultMode  = QRCode::OUTPUT_IMAGE_PNG;
33
34
	/**
35
	 * @see imagecreatetruecolor()
36
	 * @var resource
37
	 */
38
	protected $image;
39
40
	/**
41
	 * @see imagecolorallocate()
42
	 * @var int
43
	 */
44
	protected $background;
45
46
	/**
47
	 * @return void
48
	 */
49
	protected function setModuleValues():void{
50
51
		foreach($this::DEFAULT_MODULE_VALUES as $M_TYPE => $defaultValue){
52
			$v = $this->options->moduleValues[$M_TYPE] ?? null;
53
54
			if(!is_array($v) || count($v) < 3){
55
				$this->moduleValues[$M_TYPE] = $defaultValue
56
					? [0, 0, 0]
57
					: [255, 255, 255];
58
			}
59
			else{
60
				$this->moduleValues[$M_TYPE] = array_values($v);
61
			}
62
63
		}
64
65
	}
66
67
	/**
68
	 * @param string|null $file
69
	 *
70
	 * @return string
71
	 */
72
	public function dump(string $file = null):string{
73
		$this->image      = imagecreatetruecolor($this->length, $this->length);
74
		$this->background = imagecolorallocate($this->image, ...array_values($this->options->imageTransparencyBG));
75
76
		if((bool)$this->options->imageTransparent && in_array($this->options->outputType, $this::TRANSPARENCY_TYPES, true)){
77
			imagecolortransparent($this->image, $this->background);
78
		}
79
80
		imagefilledrectangle($this->image, 0, 0, $this->length, $this->length, $this->background);
81
82
		foreach($this->matrix->matrix() as $y => $row){
83
			foreach($row as $x => $M_TYPE){
84
				$this->setPixel($x, $y, $this->moduleValues[$M_TYPE]);
85
			}
86
		}
87
88
		$imageData = $this->dumpImage($file);
89
90
		if((bool)$this->options->imageBase64){
91
			$imageData = 'data:image/'.$this->options->outputType.';base64,'.base64_encode($imageData);
92
		}
93
94
		return $imageData;
95
	}
96
97
	/**
98
	 * @param int   $x
99
	 * @param int   $y
100
	 * @param array $rgb
101
	 *
102
	 * @return void
103
	 */
104
	protected function setPixel(int $x, int $y, array $rgb):void{
105
		imagefilledrectangle(
106
			$this->image,
107
			$x * $this->scale,
108
			$y * $this->scale,
109
			($x + 1) * $this->scale,
110
			($y + 1) * $this->scale,
111
			imagecolorallocate($this->image, ...$rgb)
112
		);
113
	}
114
115
	/**
116
	 * @param string|null $file
117
	 *
118
	 * @return string
119
120
	 * @throws \chillerlan\QRCode\Output\QRCodeOutputException
121
	 */
122
	protected function dumpImage(string $file = null):string{
123
		$file = $file ?? $this->options->cachefile;
124
125
		ob_start();
126
127
		try{
128
			call_user_func([$this, $this->outputMode ?? $this->defaultMode]);
129
		}
130
		// not going to cover edge cases
131
		// @codeCoverageIgnoreStart
132
		catch(\Exception $e){
133
			throw new QRCodeOutputException($e->getMessage());
134
		}
135
		// @codeCoverageIgnoreEnd
136
137
		$imageData = ob_get_contents();
138
		imagedestroy($this->image);
139
140
		ob_end_clean();
141
142
		if($file !== null){
143
			$this->saveToFile($imageData, $file);
144
		}
145
146
		return $imageData;
147
	}
148
149
	/**
150
	 * @return void
151
	 */
152
	protected function png():void{
153
		imagepng(
154
			$this->image,
155
			null,
156
			in_array($this->options->pngCompression, range(-1, 9), true)
157
				? $this->options->pngCompression
158
				: -1
159
		);
160
	}
161
162
	/**
163
	 * Jiff - like... JitHub!
164
	 * @return void
165
	 */
166
	protected function gif():void{
167
		imagegif($this->image);
168
	}
169
170
	/**
171
	 * @return void
172
	 */
173
	protected function jpg():void{
174
		imagejpeg(
175
			$this->image,
176
			null,
177
			in_array($this->options->jpegQuality, range(0, 100), true)
178
				? $this->options->jpegQuality
179
				: 85
180
		);
181
	}
182
183
}
184