@@ -226,109 +226,147 @@ private static ECCLevel ValidateECCLevel(ECCLevel eccLevel)
226
226
/// <returns>A QRCodeData structure containing the full QR code matrix, which can be used for rendering or analysis.</returns>
227
227
private static QRCodeData GenerateQrCode ( BitArray bitArray , ECCLevel eccLevel , int version )
228
228
{
229
- //Fill up data code word
230
229
var eccInfo = capacityECCTable . Single ( x => x . Version == version && x . ErrorCorrectionLevel == eccLevel ) ;
231
- var dataLength = eccInfo . TotalDataCodewords * 8 ;
232
- var lengthDiff = dataLength - bitArray . Length ;
233
- if ( lengthDiff > 0 )
230
+
231
+ // Fill up data code word
232
+ PadData ( ) ;
233
+
234
+ // Calculate error correction blocks
235
+ var codeWordWithECC = CalculateECCBlocks ( ) ;
236
+
237
+ // Calculate interleaved code word lengths
238
+ var interleavedLength = CalculateInterleavedLength ( ) ;
239
+
240
+ // Interleave code words
241
+ var interleavedData = InterleaveData ( ) ;
242
+
243
+ // Place interleaved data on module matrix
244
+ var qrData = PlaceModules ( ) ;
245
+
246
+ return qrData ;
247
+
248
+
249
+ // fills the bit array with a repeating pattern to reach the required length
250
+ void PadData ( )
234
251
{
235
- // set 'write index' to end of existing bit array
236
- var index = bitArray . Length ;
237
- // extend bit array to required length
238
- bitArray . Length = dataLength ;
239
- // pad with 4 zeros (or less if lengthDiff < 4)
240
- index += Math . Min ( lengthDiff , 4 ) ;
241
- // pad to nearest 8 bit boundary
242
- if ( ( uint ) index % 8 != 0 )
243
- index += 8 - ( int ) ( ( uint ) index % 8 ) ;
244
- // pad with repeating pattern
245
- var repeatingPatternIndex = 0 ;
246
- while ( index < dataLength )
252
+ var dataLength = eccInfo . TotalDataCodewords * 8 ;
253
+ var lengthDiff = dataLength - bitArray . Length ;
254
+ if ( lengthDiff > 0 )
247
255
{
248
- bitArray [ index ++ ] = _repeatingPattern [ repeatingPatternIndex ++ ] ;
249
- if ( repeatingPatternIndex >= _repeatingPattern . Length )
250
- repeatingPatternIndex = 0 ;
256
+ // set 'write index' to end of existing bit array
257
+ var index = bitArray . Length ;
258
+ // extend bit array to required length
259
+ bitArray . Length = dataLength ;
260
+ // pad with 4 zeros (or less if lengthDiff < 4)
261
+ index += Math . Min ( lengthDiff , 4 ) ;
262
+ // pad to nearest 8 bit boundary
263
+ if ( ( uint ) index % 8 != 0 )
264
+ index += 8 - ( int ) ( ( uint ) index % 8 ) ;
265
+ // pad with repeating pattern
266
+ var repeatingPatternIndex = 0 ;
267
+ while ( index < dataLength )
268
+ {
269
+ bitArray [ index ++ ] = _repeatingPattern [ repeatingPatternIndex ++ ] ;
270
+ if ( repeatingPatternIndex >= _repeatingPattern . Length )
271
+ repeatingPatternIndex = 0 ;
272
+ }
251
273
}
252
274
}
253
275
254
- // Generate the generator polynomial using the number of ECC words.
255
- List < CodewordBlock > codeWordWithECC ;
256
- using ( var generatorPolynom = CalculateGeneratorPolynom ( eccInfo . ECCPerBlock ) )
276
+ List < CodewordBlock > CalculateECCBlocks ( )
257
277
{
258
- //Calculate error correction words
259
- codeWordWithECC = new List < CodewordBlock > ( eccInfo . BlocksInGroup1 + eccInfo . BlocksInGroup2 ) ;
260
- AddCodeWordBlocks ( 1 , eccInfo . BlocksInGroup1 , eccInfo . CodewordsInGroup1 , 0 , bitArray . Length , generatorPolynom ) ;
261
- int offset = eccInfo . BlocksInGroup1 * eccInfo . CodewordsInGroup1 * 8 ;
262
- AddCodeWordBlocks ( 2 , eccInfo . BlocksInGroup2 , eccInfo . CodewordsInGroup2 , offset , bitArray . Length - offset , generatorPolynom ) ;
263
- }
278
+ List < CodewordBlock > codewordBlocks ;
279
+ // Generate the generator polynomial using the number of ECC words.
280
+ using ( var generatorPolynom = CalculateGeneratorPolynom ( eccInfo . ECCPerBlock ) )
281
+ {
282
+ //Calculate error correction words
283
+ codewordBlocks = new List < CodewordBlock > ( eccInfo . BlocksInGroup1 + eccInfo . BlocksInGroup2 ) ;
284
+ AddCodeWordBlocks ( 1 , eccInfo . BlocksInGroup1 , eccInfo . CodewordsInGroup1 , 0 , bitArray . Length , generatorPolynom ) ;
285
+ int offset = eccInfo . BlocksInGroup1 * eccInfo . CodewordsInGroup1 * 8 ;
286
+ AddCodeWordBlocks ( 2 , eccInfo . BlocksInGroup2 , eccInfo . CodewordsInGroup2 , offset , bitArray . Length - offset , generatorPolynom ) ;
287
+ return codewordBlocks ;
288
+ }
264
289
265
- //Calculate interleaved code word lengths
266
- int interleavedLength = 0 ;
267
- for ( var i = 0 ; i < Math . Max ( eccInfo . CodewordsInGroup1 , eccInfo . CodewordsInGroup2 ) ; i ++ )
268
- {
269
- foreach ( var codeBlock in codeWordWithECC )
270
- if ( ( uint ) codeBlock . CodeWordsLength / 8 > i )
271
- interleavedLength += 8 ;
272
- }
273
- for ( var i = 0 ; i < eccInfo . ECCPerBlock ; i ++ )
274
- {
275
- foreach ( var codeBlock in codeWordWithECC )
276
- if ( codeBlock . ECCWords . Length > i )
277
- interleavedLength += 8 ;
290
+ void AddCodeWordBlocks ( int blockNum , int blocksInGroup , int codewordsInGroup , int offset2 , int count , Polynom generatorPolynom )
291
+ {
292
+ var groupLength = codewordsInGroup * 8 ;
293
+ for ( var i = 0 ; i < blocksInGroup ; i ++ )
294
+ {
295
+ var eccWordList = CalculateECCWords ( bitArray , offset2 , groupLength , eccInfo , generatorPolynom ) ;
296
+ codewordBlocks . Add ( new CodewordBlock ( offset2 , groupLength , eccWordList ) ) ;
297
+ offset2 += groupLength ;
298
+ }
299
+ }
278
300
}
279
- interleavedLength += remainderBits [ version - 1 ] ;
280
301
281
- //Interleave code words
282
- var interleavedData = new BitArray ( interleavedLength ) ;
283
- int pos = 0 ;
284
- for ( var i = 0 ; i < Math . Max ( eccInfo . CodewordsInGroup1 , eccInfo . CodewordsInGroup2 ) ; i ++ )
302
+ // Calculate the length of the interleaved data
303
+ int CalculateInterleavedLength ( )
285
304
{
286
- foreach ( var codeBlock in codeWordWithECC )
305
+ var length = 0 ;
306
+ for ( var i = 0 ; i < Math . Max ( eccInfo . CodewordsInGroup1 , eccInfo . CodewordsInGroup2 ) ; i ++ )
287
307
{
288
- if ( ( uint ) codeBlock . CodeWordsLength / 8 > i )
289
- pos = bitArray . CopyTo ( interleavedData , ( int ) ( ( uint ) i * 8 ) + codeBlock . CodeWordsOffset , pos , 8 ) ;
308
+ foreach ( var codeBlock in codeWordWithECC )
309
+ if ( ( uint ) codeBlock . CodeWordsLength / 8 > i )
310
+ length += 8 ;
290
311
}
291
- }
292
- for ( var i = 0 ; i < eccInfo . ECCPerBlock ; i ++ )
293
- {
294
- foreach ( var codeBlock in codeWordWithECC )
295
- if ( codeBlock . ECCWords . Length > i )
296
- pos = DecToBin ( codeBlock . ECCWords [ i ] , 8 , interleavedData , pos ) ;
312
+ for ( var i = 0 ; i < eccInfo . ECCPerBlock ; i ++ )
313
+ {
314
+ foreach ( var codeBlock in codeWordWithECC )
315
+ if ( codeBlock . ECCWords . Length > i )
316
+ length += 8 ;
317
+ }
318
+ length += remainderBits [ version - 1 ] ;
319
+ return length ;
297
320
}
298
321
299
- //Place interleaved data on module matrix
300
- var qr = new QRCodeData ( version ) ;
301
- var blockedModules = new List < Rectangle > ( 17 ) ;
302
- ModulePlacer . PlaceFinderPatterns ( qr , blockedModules ) ;
303
- ModulePlacer . ReserveSeperatorAreas ( qr . ModuleMatrix . Count , blockedModules ) ;
304
- ModulePlacer . PlaceAlignmentPatterns ( qr , alignmentPatternTable [ version ] . PatternPositions , blockedModules ) ;
305
- ModulePlacer . PlaceTimingPatterns ( qr , blockedModules ) ;
306
- ModulePlacer . PlaceDarkModule ( qr , version , blockedModules ) ;
307
- ModulePlacer . ReserveVersionAreas ( qr . ModuleMatrix . Count , version , blockedModules ) ;
308
- ModulePlacer . PlaceDataWords ( qr , interleavedData , blockedModules ) ;
309
- var maskVersion = ModulePlacer . MaskCode ( qr , version , blockedModules , eccLevel ) ;
310
- var formatStr = GetFormatString ( eccLevel , maskVersion ) ;
311
-
312
- ModulePlacer . PlaceFormat ( qr , formatStr ) ;
313
- if ( version >= 7 )
322
+ // Interleave the data
323
+ BitArray InterleaveData ( )
314
324
{
315
- var versionString = GetVersionString ( version ) ;
316
- ModulePlacer . PlaceVersion ( qr , versionString ) ;
317
- }
318
-
325
+ var data = new BitArray ( interleavedLength ) ;
326
+ int pos = 0 ;
327
+ for ( var i = 0 ; i < Math . Max ( eccInfo . CodewordsInGroup1 , eccInfo . CodewordsInGroup2 ) ; i ++ )
328
+ {
329
+ foreach ( var codeBlock in codeWordWithECC )
330
+ {
331
+ if ( ( uint ) codeBlock . CodeWordsLength / 8 > i )
332
+ pos = bitArray . CopyTo ( data , ( int ) ( ( uint ) i * 8 ) + codeBlock . CodeWordsOffset , pos , 8 ) ;
333
+ }
334
+ }
335
+ for ( var i = 0 ; i < eccInfo . ECCPerBlock ; i ++ )
336
+ {
337
+ foreach ( var codeBlock in codeWordWithECC )
338
+ if ( codeBlock . ECCWords . Length > i )
339
+ pos = DecToBin ( codeBlock . ECCWords [ i ] , 8 , data , pos ) ;
340
+ }
319
341
320
- ModulePlacer . AddQuietZone ( qr ) ;
321
- return qr ;
342
+ return data ;
343
+ }
322
344
323
- void AddCodeWordBlocks ( int blockNum , int blocksInGroup , int codewordsInGroup , int offset2 , int count , Polynom generatorPolynom )
345
+ // Place the modules on the QR code matrix
346
+ QRCodeData PlaceModules ( )
324
347
{
325
- var groupLength = codewordsInGroup * 8 ;
326
- for ( var i = 0 ; i < blocksInGroup ; i ++ )
348
+ var qr = new QRCodeData ( version ) ;
349
+ var blockedModules = new List < Rectangle > ( 17 ) ;
350
+ ModulePlacer . PlaceFinderPatterns ( qr , blockedModules ) ;
351
+ ModulePlacer . ReserveSeperatorAreas ( qr . ModuleMatrix . Count , blockedModules ) ;
352
+ ModulePlacer . PlaceAlignmentPatterns ( qr , alignmentPatternTable [ version ] . PatternPositions , blockedModules ) ;
353
+ ModulePlacer . PlaceTimingPatterns ( qr , blockedModules ) ;
354
+ ModulePlacer . PlaceDarkModule ( qr , version , blockedModules ) ;
355
+ ModulePlacer . ReserveVersionAreas ( qr . ModuleMatrix . Count , version , blockedModules ) ;
356
+ ModulePlacer . PlaceDataWords ( qr , interleavedData , blockedModules ) ;
357
+ var maskVersion = ModulePlacer . MaskCode ( qr , version , blockedModules , eccLevel ) ;
358
+ var formatStr = GetFormatString ( eccLevel , maskVersion ) ;
359
+
360
+ ModulePlacer . PlaceFormat ( qr , formatStr ) ;
361
+ if ( version >= 7 )
327
362
{
328
- var eccWordList = CalculateECCWords ( bitArray , offset2 , groupLength , eccInfo , generatorPolynom ) ;
329
- codeWordWithECC . Add ( new CodewordBlock ( offset2 , groupLength , eccWordList ) ) ;
330
- offset2 += groupLength ;
363
+ var versionString = GetVersionString ( version ) ;
364
+ ModulePlacer . PlaceVersion ( qr , versionString ) ;
331
365
}
366
+
367
+ ModulePlacer . AddQuietZone ( qr ) ;
368
+
369
+ return qr ;
332
370
}
333
371
}
334
372
0 commit comments