1
1
<?php
2
-
3
2
/**
4
3
* php-gd realization of QR code with rounded modules
5
- *
4
+ *
6
5
* @see https://github.com/chillerlan/php-qrcode/pull/215
7
6
* @see https://github.com/chillerlan/php-qrcode/issues/127
8
7
*
9
8
* @created 17.09.2023
10
9
* @author livingroot
11
10
* @copyright 2023 livingroot
12
11
* @license MIT
12
+ *
13
+ * @noinspection PhpComposerExtensionStubsInspection
13
14
*/
14
15
15
16
use chillerlan \QRCode \Common \EccLevel ;
18
19
use chillerlan \QRCode \Output \QROutputInterface ;
19
20
use chillerlan \QRCode \QRCode ;
20
21
use chillerlan \QRCode \QROptions ;
22
+ use chillerlan \Settings \SettingsContainerInterface ;
21
23
22
24
require_once __DIR__ . '/../vendor/autoload.php ' ;
23
25
24
26
// --------------------
25
27
// Class definition
26
28
// --------------------
27
29
28
- class QRGdRounded extends QRGdImage {
29
-
30
- protected function module (int $ x , int $ y , int $ M_TYPE ): void {
31
-
32
- $ x1 = ($ x * $ this ->scale );
33
- $ y1 = ($ y * $ this ->scale );
34
- $ x2 = (($ x + 1 ) * $ this ->scale );
35
- $ y2 = (($ y + 1 ) * $ this ->scale );
36
-
37
- $ rectsize = ($ this ->scale / 2 );
38
-
39
- /**
40
- * @var int $neighbours
41
- * The right bit order (starting from 0):
42
- * 0 1 2
43
- * 7 # 3
44
- * 6 5 4
45
- */
46
- $ neighbours = $ this ->matrix ->checkNeighbours ($ x , $ y );
47
-
48
- // ------------------
49
- // Outer rounding
50
- // ------------------
51
-
52
- if ($ neighbours & (1 << 7 )) { // neighbour left
53
- // top left
54
- imagefilledrectangle (
55
- $ this ->image ,
56
- $ x1 ,
57
- $ y1 ,
58
- ($ x1 + $ rectsize ),
59
- ($ y1 + $ rectsize ),
60
- $ this ->moduleValues [$ M_TYPE ]
61
- );
62
- // bottom left
63
- imagefilledrectangle (
64
- $ this ->image ,
65
- $ x1 ,
66
- ($ y2 - $ rectsize ),
67
- ($ x1 + $ rectsize ),
68
- $ y2 ,
69
- $ this ->moduleValues [$ M_TYPE ]
70
- );
71
- }
72
-
73
- if ($ neighbours & (1 << 3 )) { // neighbour right
74
- // top right
75
- imagefilledrectangle (
76
- $ this ->image ,
77
- ($ x2 - $ rectsize ),
78
- $ y1 ,
79
- $ x2 ,
80
- ($ y1 + $ rectsize ),
81
- $ this ->moduleValues [$ M_TYPE ]
82
- );
83
- // bottom right
84
- imagefilledrectangle (
85
- $ this ->image ,
86
- ($ x2 - $ rectsize ),
87
- ($ y2 - $ rectsize ),
88
- $ x2 ,
89
- $ y2 ,
90
- $ this ->moduleValues [$ M_TYPE ]
91
- );
92
- }
93
-
94
- if ($ neighbours & (1 << 1 )) { // neighbour top
95
- // top left
96
- imagefilledrectangle (
97
- $ this ->image ,
98
- $ x1 ,
99
- $ y1 ,
100
- ($ x1 + $ rectsize ),
101
- ($ y1 + $ rectsize ),
102
- $ this ->moduleValues [$ M_TYPE ]
103
- );
104
- // top right
105
- imagefilledrectangle (
106
- $ this ->image ,
107
- ($ x2 - $ rectsize ),
108
- $ y1 ,
109
- $ x2 ,
110
- ($ y1 + $ rectsize ),
111
- $ this ->moduleValues [$ M_TYPE ]
112
- );
113
- }
114
-
115
- if ($ neighbours & (1 << 5 )) { // neighbour bottom
116
- // bottom left
117
- imagefilledrectangle (
118
- $ this ->image ,
119
- $ x1 ,
120
- ($ y2 - $ rectsize ),
121
- ($ x1 + $ rectsize ),
122
- $ y2 ,
123
- $ this ->moduleValues [$ M_TYPE ]
124
- );
125
- // bottom right
126
- imagefilledrectangle (
127
- $ this ->image ,
128
- ($ x2 - $ rectsize ),
129
- ($ y2 - $ rectsize ),
130
- $ x2 ,
131
- $ y2 ,
132
- $ this ->moduleValues [$ M_TYPE ]
133
- );
134
- }
135
-
136
- // ---------------------
137
- // inner rounding
138
- // ---------------------
139
-
140
- if (!$ this ->matrix ->check ($ x , $ y )) {
141
-
142
- if (($ neighbours & 1 ) && ($ neighbours & (1 << 7 )) && ($ neighbours & (1 << 1 ))) {
143
- // top left
144
- imagefilledrectangle (
145
- $ this ->image ,
146
- $ x1 ,
147
- $ y1 ,
148
- ($ x1 + $ rectsize ),
149
- ($ y1 + $ rectsize ),
150
- $ this ->moduleValues [($ M_TYPE | QRMatrix::IS_DARK )]
151
- );
152
- }
153
-
154
- if (($ neighbours & (1 << 1 )) && ($ neighbours & (1 << 2 )) && ($ neighbours & (1 << 3 ))) {
155
- // top right
156
- imagefilledrectangle (
157
- $ this ->image ,
158
- ($ x2 - $ rectsize ),
159
- $ y1 ,
160
- $ x2 ,
161
- ($ y1 + $ rectsize ),
162
- $ this ->moduleValues [($ M_TYPE | QRMatrix::IS_DARK )]
163
- );
164
- }
165
-
166
- if (($ neighbours & (1 << 7 )) && ($ neighbours & (1 << 6 )) && ($ neighbours & (1 << 5 ))) {
167
- // bottom left
168
- imagefilledrectangle (
169
- $ this ->image ,
170
- $ x1 ,
171
- ($ y2 - $ rectsize ),
172
- ($ x1 + $ rectsize ),
173
- $ y2 ,
174
- $ this ->moduleValues [($ M_TYPE | QRMatrix::IS_DARK )]
175
- );
176
- }
177
-
178
- if (($ neighbours & (1 << 3 )) && ($ neighbours & (1 << 4 )) && ($ neighbours & (1 << 5 ))) {
179
- // bottom right
180
- imagefilledrectangle (
181
- $ this ->image ,
182
- ($ x2 - $ rectsize ),
183
- ($ y2 - $ rectsize ),
184
- $ x2 ,
185
- $ y2 ,
186
- $ this ->moduleValues [($ M_TYPE | QRMatrix::IS_DARK )]
187
- );
188
- }
189
- }
190
-
191
- imagefilledellipse (
192
- $ this ->image ,
193
- (int )(($ x * $ this ->scale ) + ($ this ->scale / 2 )),
194
- (int )(($ y * $ this ->scale ) + ($ this ->scale / 2 )),
195
- (int )($ this ->scale - 1 ),
196
- (int )($ this ->scale - 1 ),
197
- $ this ->moduleValues [$ M_TYPE ]
198
- );
199
- }
30
+ class QRGdRounded extends QRGdImage{
31
+
32
+ /** @inheritDoc */
33
+ public function __construct (SettingsContainerInterface $ options , QRMatrix $ matrix ){
34
+ // enable the internal scaling for better rounding results at scale < 20
35
+ $ options ->drawCircularModules = true ;
36
+
37
+ parent ::__construct ($ options , $ matrix );
38
+ }
39
+
40
+ /** @inheritDoc */
41
+ protected function module (int $ x , int $ y , int $ M_TYPE ):void {
42
+
43
+ /**
44
+ * The bit order (starting from 0):
45
+ *
46
+ * 0 1 2
47
+ * 7 # 3
48
+ * 6 5 4
49
+ */
50
+ $ neighbours = $ this ->matrix ->checkNeighbours ($ x , $ y );
51
+
52
+ $ x1 = ($ x * $ this ->scale );
53
+ $ y1 = ($ y * $ this ->scale );
54
+ $ x2 = (($ x + 1 ) * $ this ->scale );
55
+ $ y2 = (($ y + 1 ) * $ this ->scale );
56
+ $ rectsize = (int )($ this ->scale / 2 );
57
+
58
+ $ light = $ this ->getModuleValue ($ M_TYPE );
59
+ $ dark = $ this ->getModuleValue ($ M_TYPE | QRMatrix::IS_DARK );
60
+
61
+ // ------------------
62
+ // Outer rounding
63
+ // ------------------
64
+
65
+ if ($ neighbours & (1 << 7 )){ // neighbour left
66
+ // top left
67
+ imagefilledrectangle ($ this ->image , $ x1 , $ y1 , ($ x1 + $ rectsize ), ($ y1 + $ rectsize ), $ light );
68
+ // bottom left
69
+ imagefilledrectangle ($ this ->image , $ x1 , ($ y2 - $ rectsize ), ($ x1 + $ rectsize ), $ y2 , $ light );
70
+ }
71
+
72
+ if ($ neighbours & (1 << 3 )){ // neighbour right
73
+ // top right
74
+ imagefilledrectangle ($ this ->image , ($ x2 - $ rectsize ), $ y1 , $ x2 , ($ y1 + $ rectsize ), $ light );
75
+ // bottom right
76
+ imagefilledrectangle ($ this ->image , ($ x2 - $ rectsize ), ($ y2 - $ rectsize ), $ x2 , $ y2 , $ light );
77
+ }
78
+
79
+ if ($ neighbours & (1 << 1 )){ // neighbour top
80
+ // top left
81
+ imagefilledrectangle ($ this ->image , $ x1 , $ y1 , ($ x1 + $ rectsize ), ($ y1 + $ rectsize ), $ light );
82
+ // top right
83
+ imagefilledrectangle ($ this ->image , ($ x2 - $ rectsize ), $ y1 , $ x2 , ($ y1 + $ rectsize ), $ light );
84
+ }
85
+
86
+ if ($ neighbours & (1 << 5 )){ // neighbour bottom
87
+ // bottom left
88
+ imagefilledrectangle ($ this ->image , $ x1 , ($ y2 - $ rectsize ), ($ x1 + $ rectsize ), $ y2 , $ light );
89
+ // bottom right
90
+ imagefilledrectangle ($ this ->image , ($ x2 - $ rectsize ), ($ y2 - $ rectsize ), $ x2 , $ y2 , $ light );
91
+ }
92
+
93
+ // ---------------------
94
+ // inner rounding
95
+ // ---------------------
96
+
97
+ if (!$ this ->matrix ->check ($ x , $ y )){
98
+
99
+ if (($ neighbours & 1 ) && ($ neighbours & (1 << 7 )) && ($ neighbours & (1 << 1 ))){
100
+ // top left
101
+ imagefilledrectangle ($ this ->image , $ x1 , $ y1 , ($ x1 + $ rectsize ), ($ y1 + $ rectsize ), $ dark );
102
+ }
103
+
104
+ if (($ neighbours & (1 << 1 )) && ($ neighbours & (1 << 2 )) && ($ neighbours & (1 << 3 ))){
105
+ // top right
106
+ imagefilledrectangle ($ this ->image , ($ x2 - $ rectsize ), $ y1 , $ x2 , ($ y1 + $ rectsize ), $ dark );
107
+ }
108
+
109
+ if (($ neighbours & (1 << 7 )) && ($ neighbours & (1 << 6 )) && ($ neighbours & (1 << 5 ))){
110
+ // bottom left
111
+ imagefilledrectangle ($ this ->image , $ x1 , ($ y2 - $ rectsize ), ($ x1 + $ rectsize ), $ y2 , $ dark );
112
+ }
113
+
114
+ if (($ neighbours & (1 << 3 )) && ($ neighbours & (1 << 4 )) && ($ neighbours & (1 << 5 ))){
115
+ // bottom right
116
+ imagefilledrectangle ($ this ->image , ($ x2 - $ rectsize ), ($ y2 - $ rectsize ), $ x2 , $ y2 , $ dark );
117
+ }
118
+ }
119
+
120
+ imagefilledellipse (
121
+ $ this ->image ,
122
+ (int )($ x * $ this ->scale + $ this ->scale / 2 ),
123
+ (int )($ y * $ this ->scale + $ this ->scale / 2 ),
124
+ ($ this ->scale - 1 ),
125
+ ($ this ->scale - 1 ),
126
+ $ light
127
+ );
128
+ }
129
+
200
130
}
201
131
202
132
@@ -209,13 +139,12 @@ protected function module(int $x, int $y, int $M_TYPE): void {
209
139
'outputInterface ' => QRGdRounded::class,
210
140
'eccLevel ' => EccLevel::M,
211
141
'imageTransparent ' => false ,
212
- 'imageBase64 ' => false ,
213
- 'scale ' => 30
142
+ 'outputBase64 ' => false ,
143
+ 'scale ' => 30 ,
214
144
]);
215
145
216
- $ qrcode = new QRCode ($ options );
217
146
218
- $ img = $ qrcode ->render ('https://www.youtube.com/watch?v=dQw4w9WgXcQ ' );
147
+ $ img = ( new QRCode ( $ options )) ->render ('https://www.youtube.com/watch?v=dQw4w9WgXcQ ' );
219
148
220
149
header ('Content-type: image/png ' );
221
150
0 commit comments