labfreed 0.0.16__py2.py3-none-any.whl → 0.0.18__py2.py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- labfreed/QR_Generator/generate_qr.py +450 -0
- labfreed/__init__.py +1 -1
- {labfreed-0.0.16.dist-info → labfreed-0.0.18.dist-info}/METADATA +18 -30
- {labfreed-0.0.16.dist-info → labfreed-0.0.18.dist-info}/RECORD +6 -5
- {labfreed-0.0.16.dist-info → labfreed-0.0.18.dist-info}/WHEEL +1 -1
- {labfreed-0.0.16.dist-info → labfreed-0.0.18.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,450 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
import typer
|
|
3
|
+
import io
|
|
4
|
+
from rich import print
|
|
5
|
+
from typing_extensions import Annotated
|
|
6
|
+
import numpy as np
|
|
7
|
+
import segno
|
|
8
|
+
from segno import DataOverflowError, writers
|
|
9
|
+
from typing import List
|
|
10
|
+
from enum import Enum
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class Direction(str, Enum):
|
|
15
|
+
LEFT_TO_RIGHT = "LTR"
|
|
16
|
+
TOP_TO_BOTTOM = "TTB"
|
|
17
|
+
RIGHT_TO_LEFT = "RTL"
|
|
18
|
+
|
|
19
|
+
# 5x5 block of bits that can be used to place decoration next to barcode.
|
|
20
|
+
class VisualMarker:
|
|
21
|
+
size = 5
|
|
22
|
+
|
|
23
|
+
def __init__(self, bits):
|
|
24
|
+
# true means 1 bit, false means 0 bit (eg: 1 means black, 0 means white)
|
|
25
|
+
self.bits = bits
|
|
26
|
+
|
|
27
|
+
marker_dict = {
|
|
28
|
+
'A': bytearray([
|
|
29
|
+
0x00, 0x01, 0x01, 0x01, 0x00, # preformatted
|
|
30
|
+
0x01, 0x00, 0x00, 0x00, 0x01,
|
|
31
|
+
0x01, 0x01, 0x01, 0x01, 0x01,
|
|
32
|
+
0x01, 0x00, 0x00, 0x00, 0x01,
|
|
33
|
+
0x01, 0x00, 0x00, 0x00, 0x01,
|
|
34
|
+
]),
|
|
35
|
+
'B': bytearray([
|
|
36
|
+
0x01, 0x01, 0x01, 0x01, 0x00, # preformatted
|
|
37
|
+
0x01, 0x00, 0x00, 0x00, 0x01,
|
|
38
|
+
0x01, 0x01, 0x01, 0x01, 0x00,
|
|
39
|
+
0x01, 0x00, 0x00, 0x00, 0x01,
|
|
40
|
+
0x01, 0x01, 0x01, 0x01, 0x00,
|
|
41
|
+
]),
|
|
42
|
+
'C': bytearray([
|
|
43
|
+
0x00, 0x01, 0x01, 0x01, 0x01, # preformatted
|
|
44
|
+
0x01, 0x00, 0x00, 0x00, 0x00,
|
|
45
|
+
0x01, 0x00, 0x00, 0x00, 0x00,
|
|
46
|
+
0x01, 0x00, 0x00, 0x00, 0x00,
|
|
47
|
+
0x00, 0x01, 0x01, 0x01, 0x01,
|
|
48
|
+
]),
|
|
49
|
+
'D': bytearray([
|
|
50
|
+
0x01, 0x01, 0x01, 0x01, 0x00, # preformatted
|
|
51
|
+
0x01, 0x00, 0x00, 0x00, 0x01,
|
|
52
|
+
0x01, 0x00, 0x00, 0x00, 0x01,
|
|
53
|
+
0x01, 0x00, 0x00, 0x00, 0x01,
|
|
54
|
+
0x01, 0x01, 0x01, 0x01, 0x00,
|
|
55
|
+
]),
|
|
56
|
+
'E': bytearray([
|
|
57
|
+
0x01, 0x01, 0x01, 0x01, 0x01, # preformatted
|
|
58
|
+
0x01, 0x00, 0x00, 0x00, 0x00,
|
|
59
|
+
0x01, 0x01, 0x01, 0x01, 0x01,
|
|
60
|
+
0x01, 0x00, 0x00, 0x00, 0x00,
|
|
61
|
+
0x01, 0x01, 0x01, 0x01, 0x01,
|
|
62
|
+
]),
|
|
63
|
+
'F': bytearray([
|
|
64
|
+
0x01, 0x01, 0x01, 0x01, 0x01, # preformatted
|
|
65
|
+
0x01, 0x00, 0x00, 0x00, 0x00,
|
|
66
|
+
0x01, 0x01, 0x01, 0x01, 0x01,
|
|
67
|
+
0x01, 0x00, 0x00, 0x00, 0x00,
|
|
68
|
+
0x01, 0x00, 0x00, 0x00, 0x00,
|
|
69
|
+
]),
|
|
70
|
+
'G': bytearray([
|
|
71
|
+
0x00, 0x01, 0x01, 0x01, 0x01, # preformatted
|
|
72
|
+
0x01, 0x00, 0x00, 0x00, 0x00,
|
|
73
|
+
0x01, 0x00, 0x01, 0x01, 0x00,
|
|
74
|
+
0x01, 0x00, 0x00, 0x00, 0x01,
|
|
75
|
+
0x00, 0x01, 0x01, 0x01, 0x01,
|
|
76
|
+
]),
|
|
77
|
+
'H': bytearray([
|
|
78
|
+
0x01, 0x00, 0x00, 0x00, 0x01, # preformatted
|
|
79
|
+
0x01, 0x00, 0x00, 0x00, 0x01,
|
|
80
|
+
0x01, 0x01, 0x01, 0x01, 0x01,
|
|
81
|
+
0x01, 0x00, 0x00, 0x00, 0x01,
|
|
82
|
+
0x01, 0x00, 0x00, 0x00, 0x01,
|
|
83
|
+
]),
|
|
84
|
+
'I': bytearray([
|
|
85
|
+
0x00, 0x00, 0x01, 0x00, 0x00, # preformatted
|
|
86
|
+
0x00, 0x00, 0x01, 0x00, 0x00,
|
|
87
|
+
0x00, 0x00, 0x01, 0x00, 0x00,
|
|
88
|
+
0x00, 0x00, 0x01, 0x00, 0x00,
|
|
89
|
+
0x00, 0x00, 0x01, 0x00, 0x00,
|
|
90
|
+
]),
|
|
91
|
+
'J': bytearray([
|
|
92
|
+
0x00, 0x00, 0x01, 0x00, 0x00, # preformatted
|
|
93
|
+
0x00, 0x00, 0x01, 0x00, 0x00,
|
|
94
|
+
0x00, 0x00, 0x01, 0x00, 0x00,
|
|
95
|
+
0x00, 0x00, 0x01, 0x00, 0x00,
|
|
96
|
+
0x00, 0x01, 0x00, 0x00, 0x00,
|
|
97
|
+
]),
|
|
98
|
+
'K': bytearray([
|
|
99
|
+
0x01, 0x00, 0x00, 0x00, 0x01, # preformatted
|
|
100
|
+
0x01, 0x00, 0x00, 0x01, 0x00,
|
|
101
|
+
0x01, 0x01, 0x01, 0x00, 0x00,
|
|
102
|
+
0x01, 0x00, 0x00, 0x01, 0x00,
|
|
103
|
+
0x01, 0x00, 0x00, 0x00, 0x01,
|
|
104
|
+
]),
|
|
105
|
+
'L': bytearray([
|
|
106
|
+
0x01, 0x00, 0x00, 0x00, 0x00, # preformatted
|
|
107
|
+
0x01, 0x00, 0x00, 0x00, 0x00,
|
|
108
|
+
0x01, 0x00, 0x00, 0x00, 0x00,
|
|
109
|
+
0x01, 0x00, 0x00, 0x00, 0x00,
|
|
110
|
+
0x01, 0x01, 0x01, 0x01, 0x01,
|
|
111
|
+
]),
|
|
112
|
+
'M': bytearray([
|
|
113
|
+
0x01, 0x01, 0x00, 0x01, 0x01, # preformatted
|
|
114
|
+
0x01, 0x00, 0x01, 0x00, 0x01,
|
|
115
|
+
0x01, 0x00, 0x00, 0x00, 0x01,
|
|
116
|
+
0x01, 0x00, 0x00, 0x00, 0x01,
|
|
117
|
+
0x01, 0x00, 0x00, 0x00, 0x01,
|
|
118
|
+
]),
|
|
119
|
+
'N': bytearray([
|
|
120
|
+
0x01, 0x00, 0x00, 0x00, 0x01, # preformatted
|
|
121
|
+
0x01, 0x01, 0x00, 0x00, 0x01,
|
|
122
|
+
0x01, 0x00, 0x01, 0x00, 0x01,
|
|
123
|
+
0x01, 0x00, 0x00, 0x01, 0x01,
|
|
124
|
+
0x01, 0x00, 0x00, 0x00, 0x01,
|
|
125
|
+
]),
|
|
126
|
+
'O': bytearray([
|
|
127
|
+
0x00, 0x01, 0x01, 0x01, 0x00, # preformatted
|
|
128
|
+
0x01, 0x00, 0x00, 0x00, 0x01,
|
|
129
|
+
0x01, 0x00, 0x00, 0x00, 0x01,
|
|
130
|
+
0x01, 0x00, 0x00, 0x00, 0x01,
|
|
131
|
+
0x00, 0x01, 0x01, 0x01, 0x00,
|
|
132
|
+
]),
|
|
133
|
+
'P': bytearray([
|
|
134
|
+
0x01, 0x01, 0x01, 0x01, 0x00, # preformatted
|
|
135
|
+
0x01, 0x00, 0x00, 0x00, 0x01,
|
|
136
|
+
0x01, 0x01, 0x01, 0x01, 0x00,
|
|
137
|
+
0x01, 0x00, 0x00, 0x00, 0x00,
|
|
138
|
+
0x01, 0x00, 0x00, 0x00, 0x00,
|
|
139
|
+
]),
|
|
140
|
+
'Q': bytearray([
|
|
141
|
+
0x00, 0x01, 0x01, 0x01, 0x00, # preformatted
|
|
142
|
+
0x01, 0x00, 0x00, 0x00, 0x01,
|
|
143
|
+
0x01, 0x00, 0x01, 0x00, 0x01,
|
|
144
|
+
0x01, 0x00, 0x00, 0x01, 0x00,
|
|
145
|
+
0x00, 0x01, 0x01, 0x00, 0x01,
|
|
146
|
+
]),
|
|
147
|
+
'R': bytearray([
|
|
148
|
+
0x01, 0x01, 0x01, 0x01, 0x00, # preformatted
|
|
149
|
+
0x01, 0x00, 0x00, 0x01, 0x00,
|
|
150
|
+
0x01, 0x01, 0x01, 0x00, 0x00,
|
|
151
|
+
0x01, 0x00, 0x00, 0x01, 0x00,
|
|
152
|
+
0x01, 0x00, 0x00, 0x00, 0x01,
|
|
153
|
+
]),
|
|
154
|
+
'S': bytearray([
|
|
155
|
+
0x00, 0x01, 0x01, 0x01, 0x01, # preformatted
|
|
156
|
+
0x01, 0x00, 0x00, 0x00, 0x00,
|
|
157
|
+
0x00, 0x01, 0x01, 0x01, 0x00,
|
|
158
|
+
0x00, 0x00, 0x00, 0x00, 0x01,
|
|
159
|
+
0x01, 0x01, 0x01, 0x01, 0x00,
|
|
160
|
+
]),
|
|
161
|
+
'T': bytearray([
|
|
162
|
+
0x01, 0x01, 0x01, 0x01, 0x01, # preformatted
|
|
163
|
+
0x00, 0x00, 0x01, 0x00, 0x00,
|
|
164
|
+
0x00, 0x00, 0x01, 0x00, 0x00,
|
|
165
|
+
0x00, 0x00, 0x01, 0x00, 0x00,
|
|
166
|
+
0x00, 0x00, 0x01, 0x00, 0x00,
|
|
167
|
+
]),
|
|
168
|
+
'U': bytearray([
|
|
169
|
+
0x01, 0x00, 0x00, 0x00, 0x01, # preformatted
|
|
170
|
+
0x01, 0x00, 0x00, 0x00, 0x01,
|
|
171
|
+
0x01, 0x00, 0x00, 0x00, 0x01,
|
|
172
|
+
0x01, 0x00, 0x00, 0x00, 0x01,
|
|
173
|
+
0x00, 0x01, 0x01, 0x01, 0x00,
|
|
174
|
+
]),
|
|
175
|
+
'V': bytearray([
|
|
176
|
+
0x01, 0x00, 0x00, 0x00, 0x01, # preformatted
|
|
177
|
+
0x01, 0x00, 0x00, 0x00, 0x01,
|
|
178
|
+
0x00, 0x01, 0x00, 0x01, 0x00,
|
|
179
|
+
0x00, 0x01, 0x01, 0x01, 0x00,
|
|
180
|
+
0x00, 0x00, 0x01, 0x00, 0x00,
|
|
181
|
+
]),
|
|
182
|
+
'W': bytearray([
|
|
183
|
+
0x01, 0x00, 0x00, 0x00, 0x01, # preformatted
|
|
184
|
+
0x01, 0x00, 0x01, 0x00, 0x01,
|
|
185
|
+
0x01, 0x00, 0x01, 0x00, 0x01,
|
|
186
|
+
0x00, 0x01, 0x01, 0x01, 0x00,
|
|
187
|
+
0x00, 0x01, 0x00, 0x01, 0x00,
|
|
188
|
+
]),
|
|
189
|
+
'X': bytearray([
|
|
190
|
+
0x01, 0x00, 0x00, 0x00, 0x01, # preformatted
|
|
191
|
+
0x00, 0x01, 0x00, 0x01, 0x00,
|
|
192
|
+
0x00, 0x00, 0x01, 0x00, 0x00,
|
|
193
|
+
0x00, 0x01, 0x00, 0x01, 0x00,
|
|
194
|
+
0x01, 0x00, 0x00, 0x00, 0x01,
|
|
195
|
+
]),
|
|
196
|
+
'Y': bytearray([
|
|
197
|
+
0x01, 0x00, 0x00, 0x00, 0x01, # preformatted
|
|
198
|
+
0x01, 0x00, 0x00, 0x00, 0x01,
|
|
199
|
+
0x00, 0x01, 0x01, 0x01, 0x00,
|
|
200
|
+
0x00, 0x00, 0x01, 0x00, 0x00,
|
|
201
|
+
0x00, 0x00, 0x01, 0x00, 0x00,
|
|
202
|
+
]),
|
|
203
|
+
'Z': bytearray([
|
|
204
|
+
0x01, 0x01, 0x01, 0x01, 0x01, # preformatted
|
|
205
|
+
0x00, 0x00, 0x00, 0x01, 0x00,
|
|
206
|
+
0x00, 0x00, 0x01, 0x00, 0x00,
|
|
207
|
+
0x00, 0x01, 0x00, 0x00, 0x00,
|
|
208
|
+
0x01, 0x01, 0x01, 0x01, 0x01,
|
|
209
|
+
]),
|
|
210
|
+
'0': bytearray([
|
|
211
|
+
0x00, 0x00, 0x01, 0x00, 0x00, # preformatted
|
|
212
|
+
0x00, 0x01, 0x00, 0x01, 0x00,
|
|
213
|
+
0x00, 0x01, 0x00, 0x01, 0x00,
|
|
214
|
+
0x00, 0x01, 0x00, 0x01, 0x00,
|
|
215
|
+
0x00, 0x00, 0x01, 0x00, 0x00,
|
|
216
|
+
]),
|
|
217
|
+
'1': bytearray([
|
|
218
|
+
0x00, 0x00, 0x01, 0x00, 0x00, # preformatted
|
|
219
|
+
0x00, 0x01, 0x01, 0x00, 0x00,
|
|
220
|
+
0x01, 0x00, 0x01, 0x00, 0x00,
|
|
221
|
+
0x00, 0x00, 0x01, 0x00, 0x00,
|
|
222
|
+
0x00, 0x00, 0x01, 0x00, 0x00,
|
|
223
|
+
]),
|
|
224
|
+
'2': bytearray([
|
|
225
|
+
0x00, 0x01, 0x01, 0x01, 0x00, # preformatted
|
|
226
|
+
0x01, 0x00, 0x00, 0x00, 0x01,
|
|
227
|
+
0x00, 0x00, 0x01, 0x01, 0x00,
|
|
228
|
+
0x00, 0x01, 0x00, 0x00, 0x00,
|
|
229
|
+
0x01, 0x01, 0x01, 0x01, 0x01,
|
|
230
|
+
]),
|
|
231
|
+
'3': bytearray([
|
|
232
|
+
0x01, 0x01, 0x01, 0x01, 0x00, # preformatted
|
|
233
|
+
0x00, 0x00, 0x00, 0x00, 0x01,
|
|
234
|
+
0x01, 0x01, 0x01, 0x01, 0x00,
|
|
235
|
+
0x00, 0x00, 0x00, 0x00, 0x01,
|
|
236
|
+
0x01, 0x01, 0x01, 0x01, 0x00,
|
|
237
|
+
]),
|
|
238
|
+
'4': bytearray([
|
|
239
|
+
0x01, 0x00, 0x00, 0x00, 0x00, # preformatted
|
|
240
|
+
0x01, 0x00, 0x00, 0x01, 0x00,
|
|
241
|
+
0x01, 0x01, 0x01, 0x01, 0x01,
|
|
242
|
+
0x00, 0x00, 0x00, 0x01, 0x00,
|
|
243
|
+
0x00, 0x00, 0x00, 0x01, 0x00,
|
|
244
|
+
]),
|
|
245
|
+
'5': bytearray([
|
|
246
|
+
0x01, 0x01, 0x01, 0x01, 0x01, # preformatted
|
|
247
|
+
0x01, 0x00, 0x00, 0x00, 0x00,
|
|
248
|
+
0x01, 0x01, 0x01, 0x01, 0x00,
|
|
249
|
+
0x00, 0x00, 0x00, 0x00, 0x01,
|
|
250
|
+
0x01, 0x01, 0x01, 0x01, 0x00,
|
|
251
|
+
]),
|
|
252
|
+
'6': bytearray([
|
|
253
|
+
0x00, 0x01, 0x01, 0x01, 0x00, # preformatted
|
|
254
|
+
0x01, 0x00, 0x00, 0x00, 0x00,
|
|
255
|
+
0x01, 0x01, 0x01, 0x01, 0x00,
|
|
256
|
+
0x01, 0x00, 0x00, 0x00, 0x01,
|
|
257
|
+
0x00, 0x01, 0x01, 0x01, 0x00,
|
|
258
|
+
]),
|
|
259
|
+
'7': bytearray([
|
|
260
|
+
0x01, 0x01, 0x01, 0x01, 0x01, # preformatted
|
|
261
|
+
0x00, 0x00, 0x00, 0x01, 0x00,
|
|
262
|
+
0x00, 0x00, 0x01, 0x00, 0x00,
|
|
263
|
+
0x00, 0x01, 0x00, 0x00, 0x00,
|
|
264
|
+
0x01, 0x00, 0x00, 0x00, 0x00,
|
|
265
|
+
]),
|
|
266
|
+
'8': bytearray([
|
|
267
|
+
0x00, 0x01, 0x01, 0x01, 0x00, # preformatted
|
|
268
|
+
0x01, 0x00, 0x00, 0x00, 0x01,
|
|
269
|
+
0x00, 0x01, 0x01, 0x01, 0x00,
|
|
270
|
+
0x01, 0x00, 0x00, 0x00, 0x01,
|
|
271
|
+
0x00, 0x01, 0x01, 0x01, 0x00,
|
|
272
|
+
]),
|
|
273
|
+
'9': bytearray([
|
|
274
|
+
0x00, 0x01, 0x01, 0x01, 0x00, # preformatted
|
|
275
|
+
0x01, 0x00, 0x00, 0x00, 0x01,
|
|
276
|
+
0x00, 0x01, 0x01, 0x01, 0x01,
|
|
277
|
+
0x00, 0x00, 0x00, 0x00, 0x01,
|
|
278
|
+
0x00, 0x01, 0x01, 0x01, 0x00,
|
|
279
|
+
]),
|
|
280
|
+
'.': bytearray([
|
|
281
|
+
0x00, 0x00, 0x00, 0x00, 0x00, # preformatted
|
|
282
|
+
0x00, 0x00, 0x00, 0x00, 0x00,
|
|
283
|
+
0x00, 0x00, 0x01, 0x00, 0x00,
|
|
284
|
+
0x00, 0x00, 0x00, 0x00, 0x00,
|
|
285
|
+
0x00, 0x00, 0x00, 0x00, 0x00,
|
|
286
|
+
]),
|
|
287
|
+
',': bytearray([
|
|
288
|
+
0x00, 0x00, 0x00, 0x00, 0x00, # preformatted
|
|
289
|
+
0x00, 0x00, 0x00, 0x00, 0x00,
|
|
290
|
+
0x00, 0x00, 0x00, 0x00, 0x00,
|
|
291
|
+
0x00, 0x00, 0x01, 0x00, 0x00,
|
|
292
|
+
0x00, 0x00, 0x01, 0x00, 0x00,
|
|
293
|
+
]),
|
|
294
|
+
':': bytearray([
|
|
295
|
+
0x00, 0x00, 0x00, 0x00, 0x00, # preformatted
|
|
296
|
+
0x00, 0x00, 0x01, 0x00, 0x00,
|
|
297
|
+
0x00, 0x00, 0x00, 0x00, 0x00,
|
|
298
|
+
0x00, 0x00, 0x00, 0x00, 0x00,
|
|
299
|
+
0x00, 0x00, 0x01, 0x00, 0x00,
|
|
300
|
+
]),
|
|
301
|
+
';': bytearray([
|
|
302
|
+
0x00, 0x00, 0x00, 0x00, 0x00, # preformatted
|
|
303
|
+
0x00, 0x00, 0x01, 0x00, 0x00,
|
|
304
|
+
0x00, 0x00, 0x00, 0x00, 0x00,
|
|
305
|
+
0x00, 0x00, 0x01, 0x00, 0x00,
|
|
306
|
+
0x00, 0x00, 0x01, 0x00, 0x00,
|
|
307
|
+
]),
|
|
308
|
+
'-': bytearray([
|
|
309
|
+
0x00, 0x00, 0x00, 0x00, 0x00, # preformatted
|
|
310
|
+
0x00, 0x00, 0x00, 0x00, 0x00,
|
|
311
|
+
0x00, 0x01, 0x01, 0x01, 0x00,
|
|
312
|
+
0x00, 0x00, 0x00, 0x00, 0x00,
|
|
313
|
+
0x00, 0x00, 0x00, 0x00, 0x00,
|
|
314
|
+
])
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
def generate_from_text(chars: str, direction:Direction, size_in_modules: int):
|
|
318
|
+
# fill up with "."
|
|
319
|
+
squares_cnt = (size_in_modules + 1) // (VisualMarker.size+1)
|
|
320
|
+
leftover = (size_in_modules + 1) % (VisualMarker.size+1)
|
|
321
|
+
if len(chars) < squares_cnt:
|
|
322
|
+
chars = chars + '.' * (squares_cnt - len(chars))
|
|
323
|
+
result: List[bytearray] = []
|
|
324
|
+
for char in chars[:squares_cnt]:
|
|
325
|
+
if char in VisualMarker.marker_dict:
|
|
326
|
+
marker = VisualMarker.marker_dict[char]
|
|
327
|
+
else:
|
|
328
|
+
marker = VisualMarker.marker_dict['.']
|
|
329
|
+
result.append(marker)
|
|
330
|
+
return VisualMarker.generate_from_squares(result, direction, leftover)
|
|
331
|
+
|
|
332
|
+
def generate_from_squares(marker_squares: List[bytearray], direction:Direction, padding_at_end: int):
|
|
333
|
+
# spacer is a column of zeros if RTL/LTR, or a row if TTB/BTT
|
|
334
|
+
axis = 0 if direction == Direction.TOP_TO_BOTTOM else 1
|
|
335
|
+
spacer_dim = (1, VisualMarker.size) if axis==0 else (VisualMarker.size, 1)
|
|
336
|
+
spacer = np.zeros(spacer_dim, dtype=np.uint8)
|
|
337
|
+
result = np.array([])
|
|
338
|
+
for marker in marker_squares:
|
|
339
|
+
if len(marker) != VisualMarker.size*VisualMarker.size:
|
|
340
|
+
raise ValueError("All markers must be 5x5")
|
|
341
|
+
|
|
342
|
+
np_marker = np.array(marker).reshape(VisualMarker.size, VisualMarker.size)
|
|
343
|
+
if result.size == 0:
|
|
344
|
+
# the first item doesn't need a spacer
|
|
345
|
+
result = np_marker
|
|
346
|
+
else:
|
|
347
|
+
# append in direction specified
|
|
348
|
+
if direction == Direction.RIGHT_TO_LEFT:
|
|
349
|
+
result = np.concatenate((np_marker, spacer, result), axis=1)
|
|
350
|
+
else:
|
|
351
|
+
result = np.concatenate((result, spacer, np_marker), axis=axis)
|
|
352
|
+
if(padding_at_end > 0):
|
|
353
|
+
padding_dim = (padding_at_end, VisualMarker.size) if axis==0 else (VisualMarker.size, padding_at_end)
|
|
354
|
+
padding= np.zeros(padding_dim, dtype=np.uint8)
|
|
355
|
+
|
|
356
|
+
# append in direction specified
|
|
357
|
+
if direction == Direction.RIGHT_TO_LEFT:
|
|
358
|
+
result = np.concatenate((padding, result), axis=1)
|
|
359
|
+
else:
|
|
360
|
+
result = np.concatenate((result, padding), axis=axis)
|
|
361
|
+
return result
|
|
362
|
+
|
|
363
|
+
|
|
364
|
+
app = typer.Typer()
|
|
365
|
+
|
|
366
|
+
|
|
367
|
+
def generate_qr_with_markers(url, text="PAC", title=None, direction = Direction.LEFT_TO_RIGHT):
|
|
368
|
+
if title:
|
|
369
|
+
#try to use standard size 10. Go bigger if 10 does not fit the data
|
|
370
|
+
try:
|
|
371
|
+
qr = segno.make_qr(url, error="L", version=10)
|
|
372
|
+
except DataOverflowError as e:
|
|
373
|
+
qr = segno.make_qr(url, error="L")
|
|
374
|
+
v = qr.version
|
|
375
|
+
else:
|
|
376
|
+
qr = segno.make_qr(url, error="L")
|
|
377
|
+
v = qr.version
|
|
378
|
+
|
|
379
|
+
if(qr.mode != "alphanumeric"):
|
|
380
|
+
print("[bold yellow]Large QR:[/bold yellow] Provided URL is not alphanumeric!")
|
|
381
|
+
block_count = len(qr.matrix)
|
|
382
|
+
print(f"[bold]Size:[/bold] {block_count}")
|
|
383
|
+
print(f"[bold]Version:[/bold] {qr.version}")
|
|
384
|
+
print(f"[bold]Error Level:[/bold] {qr.error}")
|
|
385
|
+
|
|
386
|
+
|
|
387
|
+
qr_matrix = np.array(qr.matrix)
|
|
388
|
+
visual_marker = VisualMarker.generate_from_text(text.upper(), direction, block_count)
|
|
389
|
+
if title:
|
|
390
|
+
title_marker = VisualMarker.generate_from_text(title.upper(), direction, block_count)
|
|
391
|
+
|
|
392
|
+
append_axis = 1 if direction == Direction.TOP_TO_BOTTOM else 0
|
|
393
|
+
padding_dim = (4, block_count) if append_axis==0 else (block_count, qr.default_border_size)
|
|
394
|
+
padding= np.zeros(padding_dim, dtype=np.uint8)
|
|
395
|
+
if title:
|
|
396
|
+
combined_matrix = np.concatenate((title_marker, padding, qr_matrix, padding, visual_marker), axis=append_axis)
|
|
397
|
+
else:
|
|
398
|
+
combined_matrix = np.concatenate((qr_matrix, padding, visual_marker), axis=append_axis)
|
|
399
|
+
|
|
400
|
+
return combined_matrix
|
|
401
|
+
|
|
402
|
+
def generate_qr_with_markers_file(url, text="PAC", title=None, direction = Direction.LEFT_TO_RIGHT, fmt='svg', path=str):
|
|
403
|
+
combined_matrix = generate_qr_with_markers(url, text="PAC", title=None, direction = Direction.LEFT_TO_RIGHT)
|
|
404
|
+
outfile = f'{path}.{fmt}'
|
|
405
|
+
match fmt:
|
|
406
|
+
case 'png':
|
|
407
|
+
segno.writers.write_png(combined_matrix, combined_matrix.shape[::-1], out=outfile, border=9)
|
|
408
|
+
case 'svg':
|
|
409
|
+
segno.writers.write_svg(combined_matrix, combined_matrix.shape[::-1], out=outfile, border=9)
|
|
410
|
+
|
|
411
|
+
|
|
412
|
+
def generate_qr_with_markers_uri(url, text="PAC", title=None, direction = Direction.LEFT_TO_RIGHT, fmt='svg'):
|
|
413
|
+
combined_matrix = generate_qr_with_markers(url, text="PAC", title=None, direction = Direction.LEFT_TO_RIGHT)
|
|
414
|
+
match fmt:
|
|
415
|
+
case 'png':
|
|
416
|
+
out = segno.writers.as_png_data_uri(combined_matrix, combined_matrix.shape[::-1], border=9)
|
|
417
|
+
case 'svg':
|
|
418
|
+
out = segno.writers.as_svg_data_uri(combined_matrix, combined_matrix.shape[::-1], border=9)
|
|
419
|
+
return out
|
|
420
|
+
|
|
421
|
+
def generate_qr_with_markers_svg(url, text="PAC", title=None, direction = Direction.LEFT_TO_RIGHT, width=None, height=None, border=9, svg_omitsize=False):
|
|
422
|
+
combined_matrix = generate_qr_with_markers(url, text="PAC", title=None, direction = Direction.LEFT_TO_RIGHT)
|
|
423
|
+
with io.BytesIO() as out:
|
|
424
|
+
version = combined_matrix.shape[::-1]
|
|
425
|
+
scalex = width / (version[0] + 2*border) if width else 1
|
|
426
|
+
scaley = height / (version[1] + 2*border) if height else 1
|
|
427
|
+
scale = min(scalex, scaley)
|
|
428
|
+
segno.writers.write_svg(combined_matrix, version, out, border=border,
|
|
429
|
+
xmldecl=False, svgns=True, scale=scale, omitsize=svg_omitsize
|
|
430
|
+
)
|
|
431
|
+
s = out.getvalue().decode()
|
|
432
|
+
return s
|
|
433
|
+
|
|
434
|
+
|
|
435
|
+
|
|
436
|
+
|
|
437
|
+
|
|
438
|
+
def main(url: Annotated[str, typer.Argument(help="The PAC-ID to be rendered as QR.")],
|
|
439
|
+
outfile: Annotated[typer.FileBinaryWrite, typer.Option(help="The file the qr will be written to.")] = "qr.svg",
|
|
440
|
+
text: Annotated[str, typer.Option(help="The text of the PAC decoration.")] = "PAC",
|
|
441
|
+
direction: Annotated[Direction, typer.Option(help="The position/direction of the PAC decoration.")] = Direction.TOP_TO_BOTTOM):
|
|
442
|
+
|
|
443
|
+
img = generate_qr_with_markers(url, text=text, direction=direction)
|
|
444
|
+
img.save('generated_codes', f"{outfile}.svg", format='svg')
|
|
445
|
+
|
|
446
|
+
|
|
447
|
+
|
|
448
|
+
if __name__ == "__main__":
|
|
449
|
+
typer.run(main)
|
|
450
|
+
|
labfreed/__init__.py
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: labfreed
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.18
|
|
4
4
|
Summary: Python implementation of LabFREED building blocks
|
|
5
5
|
Author-email: Reto Thürer <thuerer.r@buchi.com>
|
|
6
6
|
Description-Content-Type: text/markdown
|
|
7
7
|
License-Expression: MIT
|
|
8
8
|
License-File: LICENSE
|
|
9
|
+
Requires-Dist: numpy>=2.2.4
|
|
10
|
+
Requires-Dist: pydantic>=2.11.3
|
|
11
|
+
Requires-Dist: segno>=1.6.6
|
|
12
|
+
Requires-Dist: typer>=0.15.2
|
|
9
13
|
|
|
10
14
|
# LabFREED for Python
|
|
11
15
|
|
|
@@ -46,10 +50,10 @@ pac_id = PAC_Parser().parse(pac_str).pac_id
|
|
|
46
50
|
# Check validity of this PAC-ID
|
|
47
51
|
pac_id = PAC_Parser().parse(pac_str).pac_id
|
|
48
52
|
is_valid = pac_id.is_valid()
|
|
49
|
-
print('PAC-ID is valid: {is_valid}')
|
|
53
|
+
print(f'PAC-ID is valid: {is_valid}')
|
|
50
54
|
```
|
|
51
55
|
```text
|
|
52
|
-
>>
|
|
56
|
+
>> [Error during execution: No module named 'quantities']
|
|
53
57
|
```
|
|
54
58
|
### Show recommendations:
|
|
55
59
|
Note that the PAC-ID -- while valid -- uses characters which are not recommended (results in larger QR code).
|
|
@@ -59,21 +63,7 @@ There is a nice function to highlight problems
|
|
|
59
63
|
pac_id.print_validation_messages()
|
|
60
64
|
```
|
|
61
65
|
```text
|
|
62
|
-
>>
|
|
63
|
-
>> Validation Results
|
|
64
|
-
>> ---------------------------------------
|
|
65
|
-
>>
|
|
66
|
-
>> Recommendation in id segment value bal500
|
|
67
|
-
>> HTTPS://PAC.METTORIUS.COM/-MD/bal500/@1234
|
|
68
|
-
>> Characters a b l should not be used.
|
|
69
|
-
>>
|
|
70
|
-
>> Recommendation in id segment value @1234
|
|
71
|
-
>> HTTPS://PAC.METTORIUS.COM/-MD/bal500/@1234
|
|
72
|
-
>> Characters @ should not be used.
|
|
73
|
-
>>
|
|
74
|
-
>> Warning in Category -MD
|
|
75
|
-
>> HTTPS://PAC.METTORIUS.COM/-MD/bal500/@1234
|
|
76
|
-
>> Category key -MD is not a well known key. It is recommended to use well known keys only
|
|
66
|
+
>> [Error during execution: name 'pac_id' is not defined]
|
|
77
67
|
```
|
|
78
68
|
### PAC-CAT
|
|
79
69
|
|
|
@@ -85,15 +75,7 @@ if isinstance(pac_id, PAC_CAT):
|
|
|
85
75
|
pac_id.print_categories()
|
|
86
76
|
```
|
|
87
77
|
```text
|
|
88
|
-
>>
|
|
89
|
-
>> ----------
|
|
90
|
-
>> key (): -DR
|
|
91
|
-
>> id (21): XQ908756
|
|
92
|
-
>> Category
|
|
93
|
-
>> ------
|
|
94
|
-
>> key (): -MD
|
|
95
|
-
>> model_number (240): bal500
|
|
96
|
-
>> serial_number (21): @1234
|
|
78
|
+
>> [Error during execution: name 'PAC_Parser' is not defined]
|
|
97
79
|
```
|
|
98
80
|
### Parse a PAC-ID with extensions
|
|
99
81
|
PAC-ID can have extensions. Here we parse a PAC-ID with attached display names and summary.
|
|
@@ -107,7 +89,7 @@ display_names = pac_id.get_extension('N') # display name has name 'N'
|
|
|
107
89
|
print(display_names)
|
|
108
90
|
```
|
|
109
91
|
```text
|
|
110
|
-
>>
|
|
92
|
+
>> [Error during execution: name 'PAC_Parser' is not defined]
|
|
111
93
|
```
|
|
112
94
|
```python
|
|
113
95
|
# TREX
|
|
@@ -117,7 +99,7 @@ v = trex.get_segment('WEIGHT').to_python_type()
|
|
|
117
99
|
print(f'WEIGHT = {v}')
|
|
118
100
|
```
|
|
119
101
|
```text
|
|
120
|
-
>>
|
|
102
|
+
>> [Error during execution: name 'pac_id' is not defined]
|
|
121
103
|
```
|
|
122
104
|
### Create a PAC-ID with Extensions
|
|
123
105
|
|
|
@@ -171,6 +153,9 @@ if trex.get_nested_validation_messages():
|
|
|
171
153
|
# Side Note: The TREX can be turned back into a dict
|
|
172
154
|
d = trex.dict()
|
|
173
155
|
```
|
|
156
|
+
```text
|
|
157
|
+
>> [Error during execution: No module named 'quantities']
|
|
158
|
+
```
|
|
174
159
|
#### Combine PAC-ID and TREX and serialize
|
|
175
160
|
|
|
176
161
|
```python
|
|
@@ -181,7 +166,7 @@ pac_str = pac_with_trex.serialize()
|
|
|
181
166
|
print(pac_str)
|
|
182
167
|
```
|
|
183
168
|
```text
|
|
184
|
-
>>
|
|
169
|
+
>> [Error during execution: No module named 'quantities']
|
|
185
170
|
```
|
|
186
171
|
<!-- END EXAMPLES -->
|
|
187
172
|
|
|
@@ -189,6 +174,9 @@ print(pac_str)
|
|
|
189
174
|
|
|
190
175
|
## Change Log
|
|
191
176
|
|
|
177
|
+
### v0.0.17
|
|
178
|
+
- dependencies are installed automatically
|
|
179
|
+
|
|
192
180
|
### v0.0.16
|
|
193
181
|
- supports PAC-ID, PAC-CAT, TREX and DisplayName
|
|
194
182
|
- ok-ish test coverage
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
labfreed/__init__.py,sha256=
|
|
1
|
+
labfreed/__init__.py,sha256=reRp78_6uZrtmaZRtPjFWADn6svJqLZMou47EfBjrmU,88
|
|
2
2
|
labfreed/parse_pac.py,sha256=7y65HO1A3OEr5zftiEtrCaiLLI_8LoRPtQpPcKUNVik,6251
|
|
3
3
|
labfreed/validation.py,sha256=QwkZWJhAjWbPUZtJJwjVYsw9TxeFhdbZaKjrPPIpuAA,5937
|
|
4
4
|
labfreed/DisplayNameExtension/DisplayNameExtension.py,sha256=l9JZY2eRS0V-H5h3-WXIHiiBJuljns-_e_t9Bp84_CU,1155
|
|
@@ -7,6 +7,7 @@ labfreed/PAC_CAT/data_model.py,sha256=dGwcQGLy1Dk6SFbs9utxKQKm_4ROZrXdv618APlQg7
|
|
|
7
7
|
labfreed/PAC_ID/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
8
8
|
labfreed/PAC_ID/data_model.py,sha256=g09qgC-TV6fjJw9VyDF6mTJ6co2i2RKZc0Z-BmiiUIQ,7483
|
|
9
9
|
labfreed/PAC_ID/extensions.py,sha256=bvuZnlNKUdwsDLrPm8fyifqPn_PR4wCVkkScFnvRiuM,1158
|
|
10
|
+
labfreed/QR_Generator/generate_qr.py,sha256=A4Bw_UESaB_igTDV2Y7a5T7vdz2Sb3yZCfHM0qKnu0M,18091
|
|
10
11
|
labfreed/TREX/UneceUnits.json,sha256=kwfQSp_nTuWbADfBBgqTWrvPl6XtM5SedEVLbMJrM7M,898953
|
|
11
12
|
labfreed/TREX/data_model.py,sha256=neKYBc5_S4t-v86DSaWLq81VJF4oS6eFUch3ChPTYJA,29705
|
|
12
13
|
labfreed/TREX/parse.py,sha256=86962VEJpkrTcT436iFIB5dNed5WHABzpjxRjkA3PXo,2043
|
|
@@ -15,7 +16,7 @@ labfreed/utilities/base36.py,sha256=_yX8aQ1OwrK5tnJU1NUEzQSFGr9xAVnNvPObpNzCPYs,
|
|
|
15
16
|
labfreed/utilities/extension_intertpreters.py,sha256=B3IFJLfVMJQuPfBBtX6ywlDUZEi7_x6tY4g8V7SpWSs,124
|
|
16
17
|
labfreed/utilities/utility_types.py,sha256=Zhk8Mu4hHjkn1gs8oh7vOxxaT7L7wLMVG40ZOWCKGK4,2865
|
|
17
18
|
labfreed/utilities/well_known_keys.py,sha256=nqk66kHdSwJTJfMKlP-xQbBglS8F_NoWsGkfOVITFN0,331
|
|
18
|
-
labfreed-0.0.
|
|
19
|
-
labfreed-0.0.
|
|
20
|
-
labfreed-0.0.
|
|
21
|
-
labfreed-0.0.
|
|
19
|
+
labfreed-0.0.18.dist-info/licenses/LICENSE,sha256=gHFOv9FRKHxO8cInP3YXyPoJnuNeqrvcHjaE_wPSsQ8,1100
|
|
20
|
+
labfreed-0.0.18.dist-info/WHEEL,sha256=Dyt6SBfaasWElUrURkknVFAZDHSTwxg3PaTza7RSbkY,100
|
|
21
|
+
labfreed-0.0.18.dist-info/METADATA,sha256=FiS8P177t3OE6BwQMsQCUhg4y4GQihwmU4-U98WacAU,5382
|
|
22
|
+
labfreed-0.0.18.dist-info/RECORD,,
|
|
File without changes
|