- commit
- da1b6568686e89143e94f980a98bc2dbd5537f13
- parent
- 7ac0b40b20381309a948070efde6bf158f0b75be
- Author
- Tom <tfh@skip.org>
- Date
- 2020-06-17 19:49
Encode mixed numeric/alphanumeric data segments as one alphanumeric data segment if that's more efficient. Also add error check to NewWithForcedVersion(): Check if the content is too large for the requested QR code version.
Diffstat
| M | encoder.go | 20 | ++++++++++++++++---- |
| M | encoder_test.go | 51 | +++++++++++++++++++++++++++++++++++++++++++++++++++ |
| M | qrcode.go | 7 | +++++++ |
3 files changed, 74 insertions, 4 deletions
diff --git a/encoder.go b/encoder.go
@@ -172,7 +172,7 @@ func (d *dataEncoder) encode(data []byte) (*bitset.Bitset, error) {
172 172 }
173 173
174 174 // Classify data into unoptimised segments.
175 -1 d.classifyDataModes()
-1 175 highestRequiredMode := d.classifyDataModes()
176 176
177 177 // Optimise segments.
178 178 err := d.optimiseDataModes()
@@ -190,13 +190,13 @@ func (d *dataEncoder) encode(data []byte) (*bitset.Bitset, error) {
190 190 optimizedLength += length
191 191 }
192 192
193 -1 singleByteSegmentLength, err := d.encodedLength(dataModeByte, len(d.data))
-1 193 singleByteSegmentLength, err := d.encodedLength(highestRequiredMode, len(d.data))
194 194 if err != nil {
195 195 return nil, err
196 196 }
197 197
198 198 if singleByteSegmentLength <= optimizedLength {
199 -1 d.optimised = []segment{segment{dataMode: dataModeByte, data: d.data}}
-1 199 d.optimised = []segment{segment{dataMode: highestRequiredMode, data: d.data}}
200 200 }
201 201
202 202 // Encode data.
@@ -211,9 +211,15 @@ func (d *dataEncoder) encode(data []byte) (*bitset.Bitset, error) {
211 211 // classifyDataModes classifies the raw data into unoptimised segments.
212 212 // e.g. "123ZZ#!#!" =>
213 213 // [numeric, 3, "123"] [alphanumeric, 2, "ZZ"] [byte, 4, "#!#!"].
214 -1 func (d *dataEncoder) classifyDataModes() {
-1 214 //
-1 215 // Returns the highest data mode needed to encode the data. e.g. for a mixed
-1 216 // numeric/alphanumeric input, the highest is alphanumeric.
-1 217 //
-1 218 // dataModeNone < dataModeNumeric < dataModeAlphanumeric < dataModeByte
-1 219 func (d *dataEncoder) classifyDataModes() dataMode {
215 220 var start int
216 221 mode := dataModeNone
-1 222 highestRequiredMode := mode
217 223
218 224 for i, v := range d.data {
219 225 newMode := dataModeNone
@@ -236,9 +242,15 @@ func (d *dataEncoder) classifyDataModes() {
236 242
237 243 mode = newMode
238 244 }
-1 245
-1 246 if newMode > highestRequiredMode {
-1 247 highestRequiredMode = newMode
-1 248 }
239 249 }
240 250
241 251 d.actual = append(d.actual, segment{dataMode: mode, data: d.data[start:len(d.data)]})
-1 252
-1 253 return highestRequiredMode
242 254 }
243 255
244 256 // optimiseDataModes optimises the list of segments to reduce the overall output
diff --git a/encoder_test.go b/encoder_test.go
@@ -267,6 +267,57 @@ func TestOptimiseEncoding(t *testing.T) {
267 267 {dataModeByte, 8},
268 268 },
269 269 },
-1 270 // HTTPS://ABC.DE/Q/393AABB6998877XYZ0518AUQCRVJN25
-1 271 // AAAAAAAAAAAAAAAAANNNAAAANNNNNNNAAANNNNAAAAAAAANN
-1 272 // different to below---------^--------------------
-1 273 {
-1 274 dataEncoderType1To9,
-1 275 []testModeSegment{
-1 276 {dataModeAlphanumeric, 17},
-1 277 {dataModeNumeric, 3},
-1 278 {dataModeAlphanumeric, 4},
-1 279 {dataModeNumeric, 7},
-1 280 {dataModeAlphanumeric, 3},
-1 281 {dataModeNumeric, 4},
-1 282 {dataModeAlphanumeric, 8},
-1 283 {dataModeNumeric, 2},
-1 284 },
-1 285 []testModeSegment{
-1 286 {dataModeAlphanumeric, 48},
-1 287 },
-1 288 },
-1 289 // HTTPS://ABC.DE/Q/393AABB699E877XYZ0518AUQCRVJN25
-1 290 // AAAAAAAAAAAAAAAAANNNAAAANNNANNNAAANNNNAAAAAAAANN
-1 291 // different to above---------^--------------------
-1 292 {
-1 293 dataEncoderType1To9,
-1 294 []testModeSegment{
-1 295 {dataModeAlphanumeric, 17},
-1 296 {dataModeNumeric, 3},
-1 297 {dataModeAlphanumeric, 4},
-1 298 {dataModeNumeric, 3},
-1 299 {dataModeAlphanumeric, 1},
-1 300 {dataModeNumeric, 3},
-1 301 {dataModeAlphanumeric, 3},
-1 302 {dataModeNumeric, 4},
-1 303 {dataModeAlphanumeric, 8},
-1 304 {dataModeNumeric, 2},
-1 305 },
-1 306 []testModeSegment{
-1 307 {dataModeAlphanumeric, 48},
-1 308 },
-1 309 },
-1 310 // 0123456789
-1 311 // NNNNNNNNNN
-1 312 {
-1 313 dataEncoderType1To9,
-1 314 []testModeSegment{
-1 315 {dataModeNumeric, 10},
-1 316 },
-1 317 []testModeSegment{
-1 318 {dataModeNumeric, 10},
-1 319 },
-1 320 },
270 321 }
271 322
272 323 for _, test := range tests {
diff --git a/qrcode.go b/qrcode.go
@@ -233,6 +233,13 @@ func NewWithForcedVersion(content string, version int, level RecoveryLevel) (*QR 233 233 return nil, errors.New("cannot find QR Code version") 234 234 } 235 235 -1 236 if encoded.Len() > chosenVersion.numDataBits() { -1 237 return nil, fmt.Errorf("Cannot encode QR code: content too large for fixed size QR Code version %d (encoded length is %d bits, maximum length is %d bits)", -1 238 version, -1 239 encoded.Len(), -1 240 chosenVersion.numDataBits()) -1 241 } -1 242 236 243 q := &QRCode{ 237 244 Content: content, 238 245