-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathqr.go
163 lines (131 loc) · 3.83 KB
/
qr.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
package qrcode
import (
"fmt"
"io"
"qrcode/encode"
)
const (
// DEFAULT_SCALE is the default scale for the QR Code image.
DEFAULT_SCALE = 4
// DEFAULT_BORDER is the default border for the QR Code image.
DEFAULT_BORDER = 0
// DEFAULT_OUTPUT_FORMAT is the default output format for the QR Code image.
DEFAULT_OUTPUT_FORMAT = PNG
)
const (
// MicroQR versions
M1 = -1
M2 = -2
M3 = -3
M4 = -4
)
// QRCode is a struct that represents a QR Code.
type QRCode struct {
// Content
Content string
// Options
options *QRCodeOptions
// Data
Data [][]Cell
}
// QRCodeOptions is a struct that represents the options for the QR Code.
type QRCodeOptions struct {
// Encoding is the encoding mode.
// Default: calculated based on the content (can undestand only numeric, alphanumeric, byte, kanji or utf-8 with ECI)
Mode encode.EncodingMode
// Level is the error correction level.
// Default: ErrorCorrectionLevelLow.
ErrorLevel ErrorCorrectionLevel
// Version is the version of the QR Code.
// Default: calculated based on the content.
Version int
// Enable micro QR code
// Default: false
MicroQR bool
}
// QRCodeOptionsMultiMode is a struct that represents the options for building multi-mode QR Codes.
type QRCodeOptionsMultiMode struct {
// Level is the error correction level.
// Default: ErrorCorrectionLevelLow.
ErrorLevel ErrorCorrectionLevel
// Version is the version of the QR Code.
// Default: calculated based on the content.
Version int
// Enable micro QR code
// Default: false
MicroQR bool
}
type PlotOptions struct {
// Scale is the scale for the QR Code image (in pixels).
// The image will be len(data) * Scale x len(data) * Scale pixels.
Scale int
// Border is the border for the QR Code image (in pixels).
Border int
// OutputFormat is the format of the output image.
OutputFormat OutputFormat
}
// CreateMultiMode creates a QR Code with multiple modes.
func CreateMultiMode(blocks []*encode.EncodeBlock, options *QRCodeOptionsMultiMode) (*QRCode, error) {
var err error
if options == nil {
options = &QRCodeOptionsMultiMode{}
}
qrCodeOptions := &QRCodeOptions{
ErrorLevel: options.ErrorLevel,
}
version := options.Version
if version == 0 {
version, err = calculateMinVersion(blocks, qrCodeOptions.ErrorLevel, options.MicroQR)
if err != nil {
return nil, fmt.Errorf("failed to calculate min version: %w", err)
}
}
qrCodeOptions.Version = version
buf, err := getBytesData(blocks, options.ErrorLevel, version)
if err != nil {
return nil, fmt.Errorf("failed to get bytes data: %w", err)
}
data := generateField(buf, version, options.ErrorLevel)
return &QRCode{
options: qrCodeOptions,
Data: data,
}, nil
}
// Create creates a QR Code with the given content and options.
func Create(content string, options *QRCodeOptions) (*QRCode, error) {
if options == nil {
options = &QRCodeOptions{}
}
encodeBlock := &encode.EncodeBlock{
Mode: options.Mode,
Data: content,
}
if encodeBlock.Mode == 0 {
var err error
encodeBlock.Mode, err = encode.GetEncodingMode(content)
// If the content is not valid for any mode, use UTF-8 with ECI
if err != nil {
encodeBlock.Mode = encode.EncodingModeECI
encodeBlock.SubMode = encode.EncodingModeByte
encodeBlock.AssignmentNumber = 26
}
}
return CreateMultiMode([]*encode.EncodeBlock{encodeBlock}, &QRCodeOptionsMultiMode{
ErrorLevel: options.ErrorLevel,
Version: options.Version,
MicroQR: options.MicroQR,
})
}
// Plot plots the QR Code to the given writer with the given options.
func (qr *QRCode) Plot(writer io.Writer, options *PlotOptions) error {
if options == nil {
options = &PlotOptions{}
}
if options.Scale == 0 {
options.Scale = DEFAULT_SCALE
}
if options.OutputFormat == "" {
options.OutputFormat = DEFAULT_OUTPUT_FORMAT
}
return plot(qr.Data, writer, options.Scale, options.Border, options.OutputFormat)
}