Completed
Push — master ( 7df5a4...fcf7fd )
by smiley
02:10
created

QRImage::setImage()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 12
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 8
c 0
b 0
f 0
nc 2
nop 0
dl 0
loc 12
rs 9.4285
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, Data\QRMatrix};
16
17
/**
18
 * Converts the matrix into images, raw or base64 output
19
 */
20
class QRImage extends QROutputAbstract{
21
22
	const transparencyTypes = [
23
		QRCode::OUTPUT_IMAGE_PNG,
24
		QRCode::OUTPUT_IMAGE_GIF,
25
	];
26
27
	protected $moduleValues = [
28
		// light
29
		QRMatrix::M_DATA            => [255, 255, 255],
30
		QRMatrix::M_FINDER          => [255, 255, 255],
31
		QRMatrix::M_SEPARATOR       => [255, 255, 255],
32
		QRMatrix::M_ALIGNMENT       => [255, 255, 255],
33
		QRMatrix::M_TIMING          => [255, 255, 255],
34
		QRMatrix::M_FORMAT          => [255, 255, 255],
35
		QRMatrix::M_VERSION         => [255, 255, 255],
36
		QRMatrix::M_QUIETZONE       => [255, 255, 255],
37
		QRMatrix::M_TEST            => [255, 255, 255],
38
		// dark
39
		QRMatrix::M_DARKMODULE << 8 => [0, 0, 0],
40
		QRMatrix::M_DATA << 8       => [0, 0, 0],
41
		QRMatrix::M_FINDER << 8     => [0, 0, 0],
42
		QRMatrix::M_ALIGNMENT << 8  => [0, 0, 0],
43
		QRMatrix::M_TIMING << 8     => [0, 0, 0],
44
		QRMatrix::M_FORMAT << 8     => [0, 0, 0],
45
		QRMatrix::M_VERSION << 8    => [0, 0, 0],
46
		QRMatrix::M_TEST << 8       => [0, 0, 0],
47
	];
48
49
	/**
50
	 * @see imagecreatetruecolor()
51
	 * @var resource
52
	 */
53
	protected $image;
54
55
	/**
56
	 * @var int
57
	 */
58
	protected $scale;
59
60
	/**
61
	 * @var int
62
	 */
63
	protected $length;
64
65
	/**
66
	 * @see imagecolorallocate()
67
	 * @var int
68
	 */
69
	protected $background;
70
71
	/**
72
	 * @return string
73
	 * @throws \chillerlan\QRCode\Output\QRCodeOutputException
74
	 */
75
	public function dump():string{
76
77
		if($this->options->cachefile !== null && !is_writable(dirname($this->options->cachefile))){
78
			throw new QRCodeOutputException('Could not write data to cache file: '.$this->options->cachefile);
79
		}
80
81
		$this->setImage();
82
83
		$moduleValues = is_array($this->options->moduleValues[$this->matrix::M_DATA])
84
			? $this->options->moduleValues // @codeCoverageIgnore
85
			: $this->moduleValues;
86
87
		foreach($this->matrix->matrix() as $y => $row){
88
			foreach($row as $x => $pixel){
89
				$this->setPixel($x, $y, imagecolorallocate($this->image, ...$moduleValues[$pixel]));
90
			}
91
		}
92
93
		$imageData = $this->dumpImage();
94
95
		if((bool)$this->options->imageBase64){
96
			$imageData = 'data:image/'.$this->options->outputType.';base64,'.base64_encode($imageData);
97
		}
98
99
		return $imageData;
100
	}
101
102
	/**
103
	 * @return void
104
	 */
105
	protected function setImage(){
106
		$this->scale        = $this->options->scale;
107
		$this->length       = $this->moduleCount * $this->scale;
108
		$this->image        = imagecreatetruecolor($this->length, $this->length);
109
		$this->background   = imagecolorallocate($this->image, ...$this->options->imageTransparencyBG);
110
111
		if((bool)$this->options->imageTransparent && in_array($this->options->outputType, $this::transparencyTypes, true)){
112
			imagecolortransparent($this->image, $this->background);
113
		}
114
115
		imagefilledrectangle($this->image, 0, 0, $this->length, $this->length, $this->background);
116
	}
117
118
	/**
119
	 * @param $x
120
	 * @param $y
121
	 * @param $color
122
	 * @return void
123
	 */
124
	protected function setPixel($x, $y, $color){
125
		imagefilledrectangle(
126
			$this->image,
127
			$x * $this->scale,
128
			$y * $this->scale,
129
			($x + 1) * $this->scale - 1,
130
			($y + 1) * $this->scale - 1,
131
			$color
132
		);
133
	}
134
135
	/**
136
	 * @return string
137
	 * @throws \chillerlan\QRCode\Output\QRCodeOutputException
138
	 */
139
	protected function dumpImage():string {
140
		ob_start();
141
142
		try{
143
			call_user_func([$this, $this->options->outputType ?? QRCode::OUTPUT_IMAGE_PNG]);
144
		}
145
		// not going to cover edge cases
146
		// @codeCoverageIgnoreStart
147
		catch(\Exception $e){
148
			throw new QRCodeOutputException($e->getMessage());
149
		}
150
		// @codeCoverageIgnoreEnd
151
152
		$imageData = ob_get_contents();
153
		imagedestroy($this->image);
154
155
		ob_end_clean();
156
157
		return $imageData;
158
	}
159
160
	/**
161
	 * @return void
162
	 */
163 View Code Duplication
	protected function png(){
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
164
		imagepng(
165
			$this->image,
166
			$this->options->cachefile,
167
			in_array($this->options->pngCompression, range(-1, 9), true)
168
				? $this->options->pngCompression
169
				: -1
170
		);
171
	}
172
173
	/**
174
	 * Jiff - like... JitHub!
175
	 * @return void
176
	 */
177
	protected function gif(){
178
		imagegif($this->image, $this->options->cachefile);
179
	}
180
181
	/**
182
	 * @return void
183
	 */
184 View Code Duplication
	protected function jpg(){
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
185
		imagejpeg(
186
			$this->image,
187
			$this->options->cachefile,
188
			in_array($this->options->jpegQuality, range(0, 100), true)
189
				? $this->options->jpegQuality
190
				: 85
191
		);
192
	}
193
194
}
195