Standardize and update all copyright statements to name "ZXing authors" as suggested...
[zxing.git] / cpp / core / src / 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 "Decoder.h"
22 #include "BitMatrixParser.h"
23 #include "ErrorCorrectionLevel.h"
24 #include "Version.h"
25 #include "DataBlock.h"
26 #include "DecodedBitStreamParser.h"
27 #include "../../ReaderException.h"
28 #include "../../common/reedsolomon/ReedSolomonException.h"
29
30 namespace qrcode {
31   namespace decoder {
32     
33     using namespace common;
34     using namespace reedsolomon;
35     using namespace std;
36     
37     void Decoder::correctErrors(ArrayRef<unsigned char> codewordBytes,
38                                 int numDataCodewords) {
39       int numCodewords = codewordBytes->size();
40       ArrayRef<int> codewordInts(numCodewords);
41       for (int i = 0; i < numCodewords; i++) {
42         codewordInts[i] = codewordBytes[i] & 0xff;
43       }
44       int numECCodewords = numCodewords - numDataCodewords;
45       try {
46         rsDecoder_.decode(codewordInts, numECCodewords);
47       }
48       catch (ReedSolomonException *ex) {
49         ReaderException *rex = new ReaderException(ex->what());
50         delete ex;
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       Version *version = parser.readVersion();
63       ErrorCorrectionLevel &ecLevel = 
64       parser.readFormatInformation()->getErrorCorrectionLevel();
65       
66       // Read codewords
67       ArrayRef<unsigned char> codewords(parser.readCodewords());
68       // Separate into data blocks
69       ArrayRef<Ref<DataBlock> > dataBlocks (DataBlock::getDataBlocks(codewords, version, ecLevel));
70       
71       // Count total number of data bytes
72       int totalBytes = 0;
73       for (size_t i = 0; i < dataBlocks->size(); i++) {
74         totalBytes += dataBlocks[i]->getNumDataCodewords();
75       }
76       ArrayRef<unsigned char> resultBytes(totalBytes);
77       int resultOffset = 0;
78       
79       // Error-correct and copy data blocks together into a stream of bytes
80       for (size_t j = 0; j < dataBlocks->size(); j++) {
81         Ref<DataBlock> dataBlock (dataBlocks[j]);
82         ArrayRef<unsigned char> codewordBytes = dataBlock->getCodewords();
83         int numDataCodewords = dataBlock->getNumDataCodewords();
84         correctErrors(codewordBytes, numDataCodewords);
85         for (int i = 0; i < numDataCodewords; i++) {
86           resultBytes[resultOffset++] = codewordBytes[i];
87         }
88       }
89       
90       // Decode the contents of that stream of bytes
91       Ref<String> text(new String(DecodedBitStreamParser::decode(resultBytes, version)));
92       
93       Ref<DecoderResult> result(new DecoderResult(resultBytes, text));
94       return result;
95     }
96     
97   }
98 }