Issue 489 update the port
[zxing.git] / cpp / core / src / zxing / qrcode / decoder / Decoder.cpp
1 /*
2  *  Decoder.cpp
3  *  zxing
4  *
5  *  Created by Christian Brunschen on 20/05/2008.
6  *  Copyright 2008 ZXing authors All rights reserved.
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  */
20
21 #include <zxing/qrcode/decoder/Decoder.h>
22 #include <zxing/qrcode/decoder/BitMatrixParser.h>
23 #include <zxing/qrcode/ErrorCorrectionLevel.h>
24 #include <zxing/qrcode/Version.h>
25 #include <zxing/qrcode/decoder/DataBlock.h>
26 #include <zxing/qrcode/decoder/DecodedBitStreamParser.h>
27 #include <zxing/ReaderException.h>
28 #include <zxing/common/reedsolomon/ReedSolomonException.h>
29
30 namespace zxing {
31 namespace qrcode {
32
33 using namespace std;
34
35 Decoder::Decoder() :
36     rsDecoder_(GF256::QR_CODE_FIELD) {
37 }
38
39 void Decoder::correctErrors(ArrayRef<unsigned char> codewordBytes, int numDataCodewords) {
40   int numCodewords = codewordBytes->size();
41   ArrayRef<int> codewordInts(numCodewords);
42   for (int i = 0; i < numCodewords; i++) {
43     codewordInts[i] = codewordBytes[i] & 0xff;
44   }
45   int numECCodewords = numCodewords - numDataCodewords;
46
47   try {
48     rsDecoder_.decode(codewordInts, numECCodewords);
49   } catch (ReedSolomonException ex) {
50     ReaderException rex(ex.what());
51     throw rex;
52   }
53
54   for (int i = 0; i < numDataCodewords; i++) {
55     codewordBytes[i] = (unsigned char)codewordInts[i];
56   }
57 }
58
59 Ref<DecoderResult> Decoder::decode(Ref<BitMatrix> bits) {
60   // Construct a parser and read version, error-correction level
61   BitMatrixParser parser(bits);
62
63   Version *version = parser.readVersion();
64   ErrorCorrectionLevel &ecLevel = parser.readFormatInformation()->getErrorCorrectionLevel();
65
66
67   // Read codewords
68   ArrayRef<unsigned char> codewords(parser.readCodewords());
69
70
71   // Separate into data blocks
72   std::vector<Ref<DataBlock> > dataBlocks(DataBlock::getDataBlocks(codewords, version, ecLevel));
73
74
75   // Count total number of data bytes
76   int totalBytes = 0;
77   for (size_t i = 0; i < dataBlocks.size(); i++) {
78     totalBytes += dataBlocks[i]->getNumDataCodewords();
79   }
80   ArrayRef<unsigned char> resultBytes(totalBytes);
81   int resultOffset = 0;
82
83
84   // Error-correct and copy data blocks together into a stream of bytes
85   for (size_t j = 0; j < dataBlocks.size(); j++) {
86     Ref<DataBlock> dataBlock(dataBlocks[j]);
87     ArrayRef<unsigned char> codewordBytes = dataBlock->getCodewords();
88     int numDataCodewords = dataBlock->getNumDataCodewords();
89     correctErrors(codewordBytes, numDataCodewords);
90     for (int i = 0; i < numDataCodewords; i++) {
91       resultBytes[resultOffset++] = codewordBytes[i];
92     }
93   }
94
95   // Decode the contents of that stream of bytes
96   Ref<String> text(new String(DecodedBitStreamParser::decode(resultBytes, version)));
97
98   Ref<DecoderResult> result(new DecoderResult(resultBytes, text));
99   return result;
100 }
101
102 }
103 }