/*\r
- * Copyright 2007 Google Inc.\r
+ * Copyright 2007 ZXing authors\r
*\r
* Licensed under the Apache License, Version 2.0 (the "License");\r
* you may not use this file except in compliance with the License.\r
package com.google.zxing.qrcode.decoder;\r
\r
/**\r
- * @author srowen@google.com (Sean Owen)\r
+ * <p>Encapsulates a block of data within a QR Code. QR Codes may split their data into\r
+ * multiple blocks, each of which is a unit of data and error-correction codewords. Each\r
+ * is represented by an instance of this class.</p>\r
+ *\r
+ * @author Sean Owen\r
*/\r
final class DataBlock {\r
\r
this.codewords = codewords;\r
}\r
\r
+ /**\r
+ * <p>When QR Codes use multiple data blocks, they are actually interleave the bytes of each of them.\r
+ * That is, the first byte of data block 1 to n is written, then the second bytes, and so on. This\r
+ * method will separate the data into original blocks.</p>\r
+ *\r
+ * @param rawCodewords bytes as read directly from the QR Code\r
+ * @param version version of the QR Code\r
+ * @param ecLevel error-correction level of the QR Code\r
+ * @return {@link DataBlock}s containing original bytes, "de-interleaved" from representation in the\r
+ * QR Code\r
+ */\r
static DataBlock[] getDataBlocks(byte[] rawCodewords,\r
Version version,\r
ErrorCorrectionLevel ecLevel) {\r
+ // Figure out the number and size of data blocks used by this version and\r
+ // error correction level\r
Version.ECBlocks ecBlocks = version.getECBlocksForLevel(ecLevel);\r
+\r
+ // First count the total number of data blocks\r
int totalBlocks = 0;\r
Version.ECB[] ecBlockArray = ecBlocks.getECBlocks();\r
for (int i = 0; i < ecBlockArray.length; i++) {\r
totalBlocks += ecBlockArray[i].getCount();\r
}\r
+\r
+ // Now establish DataBlocks of the appropriate size and number of data codewords\r
DataBlock[] result = new DataBlock[totalBlocks];\r
int numResultBlocks = 0;\r
for (int j = 0; j < ecBlockArray.length; j++) {\r
for (int i = 0; i < ecBlock.getCount(); i++) {\r
int numDataCodewords = ecBlock.getDataCodewords();\r
int numBlockCodewords = ecBlocks.getECCodewords() + numDataCodewords;\r
- result[numResultBlocks++] =\r
- new DataBlock(numDataCodewords, new byte[numBlockCodewords]);\r
+ result[numResultBlocks++] = new DataBlock(numDataCodewords, new byte[numBlockCodewords]);\r
}\r
}\r
\r
int shorterBlocksTotalCodewords = result[0].codewords.length;\r
int longerBlocksStartAt = result.length - 1;\r
while (longerBlocksStartAt >= 0) {\r
- int numCodewords =\r
- result[longerBlocksStartAt].codewords.length;\r
+ int numCodewords = result[longerBlocksStartAt].codewords.length;\r
if (numCodewords == shorterBlocksTotalCodewords) {\r
break;\r
}\r
if (numCodewords != shorterBlocksTotalCodewords + 1) {\r
- throw new IllegalStateException(\r
- "Data block sizes differ by more than 1");\r
+ throw new IllegalArgumentException("Data block sizes differ by more than 1");\r
}\r
longerBlocksStartAt--;\r
}\r
longerBlocksStartAt++;\r
\r
- int shorterBlocksNumDataCodewords =\r
- shorterBlocksTotalCodewords - ecBlocks.getECCodewords();\r
+ int shorterBlocksNumDataCodewords = shorterBlocksTotalCodewords - ecBlocks.getECCodewords();\r
// The last elements of result may be 1 element longer;\r
// first fill out as many elements as all of them have\r
int rawCodewordsOffset = 0;\r
}\r
// Fill out the last data block in the longer ones\r
for (int j = longerBlocksStartAt; j < numResultBlocks; j++) {\r
- result[j].codewords[shorterBlocksNumDataCodewords] =\r
- rawCodewords[rawCodewordsOffset++];\r
+ result[j].codewords[shorterBlocksNumDataCodewords] = rawCodewords[rawCodewordsOffset++];\r
}\r
// Now add in error correction blocks\r
int max = result[0].codewords.length;\r
}\r
\r
if (rawCodewordsOffset != rawCodewords.length) {\r
- throw new IllegalStateException();\r
+ throw new IllegalArgumentException();\r
}\r
\r
return result;\r