1 // This file is part of OpenCV project.
2 // It is subject to the license terms in the LICENSE file found in the top-level directory
3 // of this distribution and at http://opencv.org/license.html.
4 //
5 // Tencent is pleased to support the open source community by making WeChat QRCode available.
6 // Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved.
7 //
8 // Modified from ZXing. Copyright ZXing authors.
9 // Licensed under the Apache License, Version 2.0 (the "License").
10 #include "../../../precomp.hpp"
11 #include "decoder.hpp"
12 #include "../error_correction_level.hpp"
13 #include "../version.hpp"
14 #include "datablock.hpp"
15 #include "decoded_bit_stream_parser.hpp"
16 #include "qrcode_decoder_metadata.hpp"
17 
18 using zxing::DecoderResult;
19 using zxing::Ref;
20 using zxing::qrcode::Decoder;
21 
22 // VC++
23 // The main class which implements QR Code decoding -- as opposed to locating
24 // and extracting the QR Code from an image.
25 using zxing::ArrayRef;
26 using zxing::BitMatrix;
27 using zxing::DetectorResult;
28 using zxing::ErrorHandler;
29 
Decoder()30 Decoder::Decoder() : rsDecoder_(Ref<GenericGF>(GF_QR_CODE_FIELD_256)) {
31     possibleVersion_ = 0;
32     possibleFix_ = 0;
33     decoderState_ = NOTSTART;
34 }
35 
36 // Convenience method that can decode a QR Code represented as a 2D array of
37 // booleans. "true" is taken to mean a black module.
decode(Ref<BitMatrix> bits,ErrorHandler & err_handler)38 Ref<DecoderResult> Decoder::decode(Ref<BitMatrix> bits, ErrorHandler &err_handler) {
39     string errMsg = "";
40 
41     // Used for mirrored qrcode
42     int width = bits->getWidth();
43     int height = bits->getHeight();
44 
45     Ref<BitMatrix> bits2(new BitMatrix(width, height, bits->getPtr(), err_handler));
46     if (err_handler.ErrCode()) return Ref<DecoderResult>();
47     Ref<DecoderResult> rst = decode(bits, false, err_handler);
48     if (err_handler.ErrCode() || rst == NULL) {
49         errMsg = err_handler.ErrMsg();
50     } else {
51         return rst;
52     }
53 
54     err_handler.Reset();
55     Ref<DecoderResult> result = decode(bits2, true, err_handler);
56     if (err_handler.ErrCode()) {
57         return Ref<DecoderResult>();
58     } else {
59         // Success! Notify the caller that the code was mirrored.
60         result->setOther(Ref<QRCodeDecoderMetaData>(new QRCodeDecoderMetaData(true)));
61         return result;
62     }
63 };
64 
decode(Ref<BitMatrix> bits,bool isMirror,ErrorHandler & err_handler)65 Ref<DecoderResult> Decoder::decode(Ref<BitMatrix> bits, bool isMirror, ErrorHandler &err_handler) {
66     // Ref<DecoderResult> Decoder::decode(BitMatrixParser& parser) {
67     // Construct a parser and read version, error-correction level
68     BitMatrixParser parser(bits, err_handler);
69     if (err_handler.ErrCode()) return Ref<DecoderResult>();
70 
71     if (isMirror == true) {
72         // Revert the bit matrix
73         parser.remask();
74 
75         // Will be attempting a mirrored reading of the version and format info.
76         parser.setMirror(true);
77 
78         // Preemptively read the version.
79         parser.readVersion(err_handler);
80         if (err_handler.ErrCode()) {
81             err_handler = zxing::ReaderErrorHandler("Decoder::decode mirror & no mirror");
82             return Ref<DecoderResult>();
83         }
84 
85         // Preemptively read the format information.
86         parser.readFormatInformation(err_handler);
87         if (err_handler.ErrCode()) return Ref<DecoderResult>();
88 
89         /*
90          * Since we're here, this means we have successfully detected some kind
91          * of version and format information when mirrored. This is a good sign,
92          * that the QR code may be mirrored, and we should try once more with a
93          * mirrored content.
94          */
95         // Prepare for a mirrored reading.
96         parser.mirror();
97     }
98 
99     decoderState_ = START;
100     possibleFix_ = 0;
101     Version *version = parser.readVersion(err_handler);
102     if (err_handler.ErrCode() || version == NULL) {
103         err_handler = ReaderErrorHandler("Decoder::decode mirror & no mirror");
104         return Ref<DecoderResult>();
105     }
106     decoderState_ = READVERSION;
107     float fixedPatternScore = estimateFixedPattern(bits, version, err_handler);
108     if (err_handler.ErrCode()) return Ref<DecoderResult>();
109 
110     Ref<FormatInformation> formatInfo = parser.readFormatInformation(err_handler);
111     if (err_handler.ErrCode()) return Ref<DecoderResult>();
112     ErrorCorrectionLevel &ecLevel = formatInfo->getErrorCorrectionLevel();
113 
114     decoderState_ = READERRORCORRECTIONLEVEL;
115 
116     // Read codewords
117     ArrayRef<char> codewords(parser.readCodewords(err_handler));
118     if (err_handler.ErrCode()) {
119         err_handler = zxing::ReaderErrorHandler("Decoder::decode mirror & no mirror");
120         return Ref<DecoderResult>();
121     }
122 
123     decoderState_ = READCODEWORDSORRECTIONLEVEL;
124     possibleFix_ = fixedPatternScore;
125 
126     // Separate into data blocks
127     std::vector<Ref<DataBlock> > dataBlocks(
128         DataBlock::getDataBlocks(codewords, version, ecLevel, err_handler));
129     if (err_handler.ErrCode()) return Ref<DecoderResult>();
130 
131     // Count total number of data bytes
132     int totalBytes = 0;
133     for (size_t i = 0; i < dataBlocks.size(); i++) {
134         totalBytes += dataBlocks[i]->getNumDataCodewords();
135     }
136     ArrayRef<char> resultBytes(totalBytes);
137     int resultOffset = 0;
138 
139     // Error-correct and copy data blocks together into a stream of bytes
140     for (size_t j = 0; j < dataBlocks.size(); j++) {
141         err_handler.Reset();
142         Ref<DataBlock> dataBlock(dataBlocks[j]);
143         ArrayRef<char> codewordBytes = dataBlock->getCodewords();
144         int numDataCodewords = dataBlock->getNumDataCodewords();
145 
146         correctErrors(codewordBytes, numDataCodewords, err_handler);
147         if (err_handler.ErrCode()) return Ref<DecoderResult>();
148 
149         for (int i = 0; i < numDataCodewords; i++) {
150             resultBytes[resultOffset++] = codewordBytes[i];
151         }
152     }
153 
154     decoderState_ = FINISH;
155     // return DecodedBitStreamParser::decode(resultBytes,
156     DecodedBitStreamParser dbs_parser;
157     Ref<DecoderResult> rst =
158         dbs_parser.decode(resultBytes, version, ecLevel, err_handler, version->getVersionNumber());
159 
160     if (err_handler.ErrCode()) return Ref<DecoderResult>();
161     return rst;
162 }
163 
164 // Given data and error-correction codewords received, possibly corrupted by
165 // errors, attempts to correct the errors in-place using Reed-Solomon error
166 // correction.</p> codewordBytes: data and error correction codewords
167 // numDataCodewords: number of codewords that are data bytes
correctErrors(ArrayRef<char> codewordBytes,int numDataCodewords,ErrorHandler & err_handler)168 void Decoder::correctErrors(ArrayRef<char> codewordBytes, int numDataCodewords,
169                             ErrorHandler &err_handler) {
170     // First read into an arrya of ints
171     int numCodewords = codewordBytes->size();
172     ArrayRef<int> codewordInts(numCodewords);
173     for (int i = 0; i < numCodewords; i++) {
174         codewordInts[i] = codewordBytes[i] & 0xff;
175     }
176     int numECCodewords = numCodewords - numDataCodewords;
177     bool correctErrorsFinishished = false;
178 
179     rsDecoder_.decode(codewordInts, numECCodewords, err_handler);
180     if (err_handler.ErrCode()) {
181         return;
182     }
183 
184     correctErrorsFinishished = true;
185 
186     // Copy back into array of bytes -- only need to worry about the bytes that
187     // were data We don't care about errors in the error-correction codewords
188     if (correctErrorsFinishished) {
189         for (int i = 0; i < numDataCodewords; i++) {
190             codewordBytes[i] = (char)codewordInts[i];
191         }
192     }
193 }
194 
getPossibleVersion()195 unsigned int Decoder::getPossibleVersion() { return possibleVersion_; }
196 
estimateFixedPattern(Ref<BitMatrix> bits,zxing::qrcode::Version * version,ErrorHandler & err_handler)197 float Decoder::estimateFixedPattern(Ref<BitMatrix> bits, zxing::qrcode::Version *version,
198                                     ErrorHandler &err_handler) {
199     Ref<BitMatrix> fixedPatternValue = version->buildFixedPatternValue(err_handler);
200     if (err_handler.ErrCode()) {
201         err_handler = zxing::ReaderErrorHandler("Decoder::decode mirror & no mirror");
202         return -1.0;
203     }
204     Ref<BitMatrix> fixedPatternTemplate = version->buildFixedPatternTemplate(err_handler);
205     if (err_handler.ErrCode()) {
206         err_handler = zxing::ReaderErrorHandler("Decoder::decode mirror & no mirror");
207         return -1.0;
208     }
209 
210     int iSum = 0;
211     int iCount = 0;
212     for (int i = 0; i < bits->getHeight(); ++i) {
213         for (int j = 0; j < bits->getWidth(); ++j) {
214             if (fixedPatternTemplate->get(i, j)) {
215                 iSum++;
216                 if (bits->get(i, j) == fixedPatternValue->get(i, j)) iCount++;
217             }
218         }
219     }
220 
221     float possbielFix = 2.0 * iCount / iSum - 1;
222     return possbielFix > 0 ? possbielFix : 0;
223 }
224