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 #include "precomp.hpp"
8 #include "decodermgr.hpp"
9 
10 
11 using zxing::ArrayRef;
12 using zxing::BinaryBitmap;
13 using zxing::DecodeHints;
14 using zxing::ErrorHandler;
15 using zxing::LuminanceSource;
16 using zxing::Ref;
17 using zxing::Result;
18 using zxing::UnicomBlock;
19 namespace cv {
20 namespace wechat_qrcode {
decodeImage(cv::Mat src,bool use_nn_detector,string & result)21 int DecoderMgr::decodeImage(cv::Mat src, bool use_nn_detector, string& result) {
22     int width = src.cols;
23     int height = src.rows;
24     if (width <= 20 || height <= 20)
25         return -1;  // image data is not enough for providing reliable results
26 
27     std::vector<uint8_t> scaled_img_data(src.data, src.data + width * height);
28     zxing::ArrayRef<uint8_t> scaled_img_zx =
29         zxing::ArrayRef<uint8_t>(new zxing::Array<uint8_t>(scaled_img_data));
30 
31     zxing::Ref<zxing::Result> zx_result;
32 
33     decode_hints_.setUseNNDetector(use_nn_detector);
34 
35     Ref<ImgSource> source;
36     qbarUicomBlock_ = new UnicomBlock(width, height);
37 
38     // Four Binarizers
39     int tryBinarizeTime = 4;
40     for (int tb = 0; tb < tryBinarizeTime; tb++) {
41         if (source == NULL || height * width > source->getMaxSize()) {
42             source = ImgSource::create(scaled_img_zx.data(), width, height);
43         } else {
44             source->reset(scaled_img_zx.data(), width, height);
45         }
46         int ret = TryDecode(source, zx_result);
47         if (!ret) {
48             result = zx_result->getText()->getText();
49             return ret;
50         }
51         // try different binarizers
52         binarizer_mgr_.SwitchBinarizer();
53     }
54     return -1;
55 }
56 
TryDecode(Ref<LuminanceSource> source,Ref<Result> & result)57 int DecoderMgr::TryDecode(Ref<LuminanceSource> source, Ref<Result>& result) {
58     int res = -1;
59     string cell_result;
60 
61     // get binarizer
62     zxing::Ref<zxing::Binarizer> binarizer = binarizer_mgr_.Binarize(source);
63     zxing::Ref<zxing::BinaryBitmap> binary_bitmap(new BinaryBitmap(binarizer));
64     binary_bitmap->m_poUnicomBlock = qbarUicomBlock_;
65 
66     result = Decode(binary_bitmap, decode_hints_);
67     res = (result == NULL) ? 1 : 0;
68 
69     if (res == 0) {
70         result->setBinaryMethod(int(binarizer_mgr_.GetCurBinarizer()));
71     }
72 
73     return res;
74 }
75 
Decode(Ref<BinaryBitmap> image,DecodeHints hints)76 Ref<Result> DecoderMgr::Decode(Ref<BinaryBitmap> image, DecodeHints hints) {
77     return reader_->decode(image, hints);
78 }
79 }  // namespace wechat_qrcode
80 }  // namespace cv