1 // Copyright 2014 PDFium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6 // Original code is licensed as follows:
7 /*
8  * Copyright 2013 ZXing authors
9  *
10  * Licensed under the Apache License, Version 2.0 (the "License");
11  * you may not use this file except in compliance with the License.
12  * You may obtain a copy of the License at
13  *
14  *      http://www.apache.org/licenses/LICENSE-2.0
15  *
16  * Unless required by applicable law or agreed to in writing, software
17  * distributed under the License is distributed on an "AS IS" BASIS,
18  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19  * See the License for the specific language governing permissions and
20  * limitations under the License.
21  */
22 
23 #include "xfa/src/fxbarcode/barcode.h"
24 #include "BC_PDF417Common.h"
25 #include "BC_PDF417CodewordDecoder.h"
26 #define SYMBOL_TABLE_Length 2787
27 #define Float_MAX_VALUE 2147483647
28 FX_FLOAT CBC_PDF417CodewordDecoder::RATIOS_TABLE[2787][8] = {{0}};
CBC_PDF417CodewordDecoder()29 CBC_PDF417CodewordDecoder::CBC_PDF417CodewordDecoder() {}
~CBC_PDF417CodewordDecoder()30 CBC_PDF417CodewordDecoder::~CBC_PDF417CodewordDecoder() {}
Initialize()31 void CBC_PDF417CodewordDecoder::Initialize() {
32   for (int32_t i = 0; i < SYMBOL_TABLE_Length; i++) {
33     int32_t currentSymbol = CBC_PDF417Common::SYMBOL_TABLE[i];
34     int32_t currentBit = currentSymbol & 0x1;
35     for (int32_t j = 0; j < CBC_PDF417Common::BARS_IN_MODULE; j++) {
36       FX_FLOAT size = 0.0f;
37       while ((currentSymbol & 0x1) == currentBit) {
38         size += 1.0f;
39         currentSymbol >>= 1;
40       }
41       currentBit = currentSymbol & 0x1;
42       RATIOS_TABLE[i][CBC_PDF417Common::BARS_IN_MODULE - j - 1] =
43           size / CBC_PDF417Common::MODULES_IN_CODEWORD;
44     }
45   }
46 }
Finalize()47 void CBC_PDF417CodewordDecoder::Finalize() {}
getDecodedValue(CFX_Int32Array & moduleBitCount)48 int32_t CBC_PDF417CodewordDecoder::getDecodedValue(
49     CFX_Int32Array& moduleBitCount) {
50   CFX_Int32Array* array = sampleBitCounts(moduleBitCount);
51   int32_t decodedValue = getDecodedCodewordValue(*array);
52   delete array;
53   if (decodedValue != -1) {
54     return decodedValue;
55   }
56   return getClosestDecodedValue(moduleBitCount);
57 }
sampleBitCounts(CFX_Int32Array & moduleBitCount)58 CFX_Int32Array* CBC_PDF417CodewordDecoder::sampleBitCounts(
59     CFX_Int32Array& moduleBitCount) {
60   FX_FLOAT bitCountSum =
61       (FX_FLOAT)CBC_PDF417Common::getBitCountSum(moduleBitCount);
62   CFX_Int32Array* bitCount = new CFX_Int32Array();
63   bitCount->SetSize(CBC_PDF417Common::BARS_IN_MODULE);
64   int32_t bitCountIndex = 0;
65   int32_t sumPreviousBits = 0;
66   for (int32_t i = 0; i < CBC_PDF417Common::MODULES_IN_CODEWORD; i++) {
67     FX_FLOAT sampleIndex =
68         bitCountSum / (2 * CBC_PDF417Common::MODULES_IN_CODEWORD) +
69         (i * bitCountSum) / CBC_PDF417Common::MODULES_IN_CODEWORD;
70     if (sumPreviousBits + moduleBitCount.GetAt(bitCountIndex) <= sampleIndex) {
71       sumPreviousBits += moduleBitCount.GetAt(bitCountIndex);
72       bitCountIndex++;
73     }
74     bitCount->SetAt(bitCountIndex, bitCount->GetAt(bitCountIndex) + 1);
75   }
76   return bitCount;
77 }
getDecodedCodewordValue(CFX_Int32Array & moduleBitCount)78 int32_t CBC_PDF417CodewordDecoder::getDecodedCodewordValue(
79     CFX_Int32Array& moduleBitCount) {
80   int32_t decodedValue = getBitValue(moduleBitCount);
81   return CBC_PDF417Common::getCodeword(decodedValue) == -1 ? -1 : decodedValue;
82 }
getBitValue(CFX_Int32Array & moduleBitCount)83 int32_t CBC_PDF417CodewordDecoder::getBitValue(CFX_Int32Array& moduleBitCount) {
84   int64_t result = 0;
85   for (int32_t i = 0; i < moduleBitCount.GetSize(); i++) {
86     for (int32_t bit = 0; bit < moduleBitCount.GetAt(i); bit++) {
87       result = (result << 1) | (i % 2 == 0 ? 1 : 0);
88     }
89   }
90   return (int32_t)result;
91 }
getClosestDecodedValue(CFX_Int32Array & moduleBitCount)92 int32_t CBC_PDF417CodewordDecoder::getClosestDecodedValue(
93     CFX_Int32Array& moduleBitCount) {
94   int32_t bitCountSum = CBC_PDF417Common::getBitCountSum(moduleBitCount);
95   CFX_FloatArray bitCountRatios;
96   bitCountRatios.SetSize(CBC_PDF417Common::BARS_IN_MODULE);
97   for (int32_t i = 0; i < bitCountRatios.GetSize(); i++) {
98     bitCountRatios[i] = moduleBitCount.GetAt(i) / (FX_FLOAT)bitCountSum;
99   }
100   FX_FLOAT bestMatchError = (FX_FLOAT)Float_MAX_VALUE;
101   int32_t bestMatch = -1;
102   for (int32_t j = 0; j < SYMBOL_TABLE_Length; j++) {
103     FX_FLOAT error = 0.0f;
104     for (int32_t k = 0; k < CBC_PDF417Common::BARS_IN_MODULE; k++) {
105       FX_FLOAT diff = RATIOS_TABLE[j][k] - bitCountRatios[k];
106       error += diff * diff;
107     }
108     if (error < bestMatchError) {
109       bestMatchError = error;
110       bestMatch = CBC_PDF417Common::SYMBOL_TABLE[j];
111     }
112   }
113   return bestMatch;
114 }
115