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