Merge XFA to PDFium master at 4dc95e7 on 10/28/2014
[pdfium.git] / xfa / src / fxbarcode / src / BC_PDF417CodewordDecoder.cpp
1 // Copyright 2014 PDFium Authors. All rights reserved.\r
2 // Use of this source code is governed by a BSD-style license that can be\r
3 // found in the LICENSE file.\r
4 \r
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com\r
6 \r
7 #include "barcode.h"\r
8 #include "include/BC_PDF417Common.h"\r
9 #include "include/BC_PDF417CodewordDecoder.h"\r
10 #define     SYMBOL_TABLE_Length       2787\r
11 #define     Float_MAX_VALUE           2147483647\r
12 FX_FLOAT CBC_PDF417CodewordDecoder::RATIOS_TABLE[2787][8] = {0};\r
13 CBC_PDF417CodewordDecoder::CBC_PDF417CodewordDecoder()\r
14 {\r
15 }\r
16 CBC_PDF417CodewordDecoder::~CBC_PDF417CodewordDecoder()\r
17 {\r
18 }\r
19 void CBC_PDF417CodewordDecoder::Initialize()\r
20 {\r
21     for (FX_INT32 i = 0; i < SYMBOL_TABLE_Length; i++) {\r
22         FX_INT32 currentSymbol = CBC_PDF417Common::SYMBOL_TABLE[i];\r
23         FX_INT32 currentBit = currentSymbol & 0x1;\r
24         for (FX_INT32 j = 0; j < CBC_PDF417Common::BARS_IN_MODULE; j++) {\r
25             FX_FLOAT size = 0.0f;\r
26             while ((currentSymbol & 0x1) == currentBit) {\r
27                 size += 1.0f;\r
28                 currentSymbol >>= 1;\r
29             }\r
30             currentBit = currentSymbol & 0x1;\r
31             RATIOS_TABLE[i][CBC_PDF417Common::BARS_IN_MODULE - j - 1] = size / CBC_PDF417Common::MODULES_IN_CODEWORD;\r
32         }\r
33     }\r
34 }\r
35 void CBC_PDF417CodewordDecoder::Finalize()\r
36 {\r
37 }\r
38 FX_INT32 CBC_PDF417CodewordDecoder::getDecodedValue(CFX_Int32Array& moduleBitCount)\r
39 {\r
40     CFX_Int32Array* array = sampleBitCounts(moduleBitCount);\r
41     FX_INT32 decodedValue = getDecodedCodewordValue(*array);\r
42     delete array;\r
43     if (decodedValue != -1) {\r
44         return decodedValue;\r
45     }\r
46     return getClosestDecodedValue(moduleBitCount);\r
47 }\r
48 CFX_Int32Array* CBC_PDF417CodewordDecoder::sampleBitCounts(CFX_Int32Array& moduleBitCount)\r
49 {\r
50     FX_FLOAT bitCountSum = (FX_FLOAT)CBC_PDF417Common::getBitCountSum(moduleBitCount);\r
51     CFX_Int32Array* bitCount = FX_NEW CFX_Int32Array();\r
52     bitCount->SetSize(CBC_PDF417Common::BARS_IN_MODULE);\r
53     FX_INT32 bitCountIndex = 0;\r
54     FX_INT32 sumPreviousBits = 0;\r
55     for (FX_INT32 i = 0; i < CBC_PDF417Common::MODULES_IN_CODEWORD; i++) {\r
56         FX_FLOAT sampleIndex = bitCountSum / (2 * CBC_PDF417Common::MODULES_IN_CODEWORD) + (i * bitCountSum) / CBC_PDF417Common::MODULES_IN_CODEWORD;\r
57         if (sumPreviousBits + moduleBitCount.GetAt(bitCountIndex) <= sampleIndex) {\r
58             sumPreviousBits += moduleBitCount.GetAt(bitCountIndex);\r
59             bitCountIndex++;\r
60         }\r
61         bitCount->SetAt(bitCountIndex, bitCount->GetAt(bitCountIndex) + 1);\r
62     }\r
63     return bitCount;\r
64 }\r
65 FX_INT32 CBC_PDF417CodewordDecoder::getDecodedCodewordValue(CFX_Int32Array& moduleBitCount)\r
66 {\r
67     FX_INT32 decodedValue = getBitValue(moduleBitCount);\r
68     return CBC_PDF417Common::getCodeword(decodedValue) == -1 ? -1 : decodedValue;\r
69 }\r
70 FX_INT32 CBC_PDF417CodewordDecoder::getBitValue(CFX_Int32Array& moduleBitCount)\r
71 {\r
72     FX_INT64 result = 0;\r
73     for (FX_INT32 i = 0; i < moduleBitCount.GetSize(); i++) {\r
74         for (FX_INT32 bit = 0; bit < moduleBitCount.GetAt(i); bit++) {\r
75             result = (result << 1) | (i % 2 == 0 ? 1 : 0);\r
76         }\r
77     }\r
78     return (FX_INT32) result;\r
79 }\r
80 FX_INT32 CBC_PDF417CodewordDecoder::getClosestDecodedValue(CFX_Int32Array& moduleBitCount)\r
81 {\r
82     FX_INT32 bitCountSum = CBC_PDF417Common::getBitCountSum(moduleBitCount);\r
83     CFX_FloatArray bitCountRatios;\r
84     bitCountRatios.SetSize(CBC_PDF417Common::BARS_IN_MODULE);\r
85     for (FX_INT32 i = 0; i < bitCountRatios.GetSize(); i++) {\r
86         bitCountRatios[i] = moduleBitCount.GetAt(i) / (FX_FLOAT) bitCountSum;\r
87     }\r
88     FX_FLOAT bestMatchError = (FX_FLOAT)Float_MAX_VALUE;\r
89     FX_INT32 bestMatch = -1;\r
90     for (FX_INT32 j = 0; j < SYMBOL_TABLE_Length; j++) {\r
91         FX_FLOAT error = 0.0f;\r
92         for (FX_INT32 k = 0; k < CBC_PDF417Common::BARS_IN_MODULE; k++) {\r
93             FX_FLOAT diff = RATIOS_TABLE[j][k] - bitCountRatios[k];\r
94             error += diff * diff;\r
95         }\r
96         if (error < bestMatchError) {\r
97             bestMatchError = error;\r
98             bestMatch = CBC_PDF417Common::SYMBOL_TABLE[j];\r
99         }\r
100     }\r
101     return bestMatch;\r
102 }\r