Merge XFA to PDFium master at 4dc95e7 on 10/28/2014
[pdfium.git] / xfa / src / fxbarcode / src / BC_OneDReader.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_Reader.h"\r
9 #include "include/BC_OneDReader.h"\r
10 #include "include/BC_BinaryBitmap.h"\r
11 #include "include/BC_CommonBitArray.h"\r
12 const FX_INT32 CBC_OneDReader::INTEGER_MATH_SHIFT = 8;\r
13 const FX_INT32 CBC_OneDReader::PATTERN_MATCH_RESULT_SCALE_FACTOR = 1 << 8;\r
14 CBC_OneDReader::CBC_OneDReader()\r
15 {\r
16 }\r
17 CBC_OneDReader::~CBC_OneDReader()\r
18 {\r
19 }\r
20 CFX_ByteString CBC_OneDReader::Decode(CBC_BinaryBitmap *image, FX_INT32 &e)\r
21 {\r
22     CFX_ByteString strtemp = Decode(image, 0, e);\r
23     BC_EXCEPTION_CHECK_ReturnValue(e, "");\r
24     return strtemp;\r
25 }\r
26 CFX_ByteString CBC_OneDReader::Decode(CBC_BinaryBitmap *image, FX_INT32 hints, FX_INT32 &e)\r
27 {\r
28     CFX_ByteString strtemp = DeDecode(image, hints, e);\r
29     BC_EXCEPTION_CHECK_ReturnValue(e, "");\r
30     return strtemp;\r
31 }\r
32 CFX_ByteString CBC_OneDReader::DeDecode(CBC_BinaryBitmap *image, FX_INT32 hints, FX_INT32 &e)\r
33 {\r
34     FX_INT32 width = image->GetWidth();\r
35     FX_INT32 height = image->GetHeight();\r
36     CBC_CommonBitArray *row = NULL;\r
37     FX_INT32 middle = height >> 1;\r
38     FX_BOOL tryHarder = FALSE;\r
39     FX_INT32 rowStep = FX_MAX(1, height >> (tryHarder ? 8 : 5));\r
40     FX_INT32 maxLines;\r
41     if (tryHarder) {\r
42         maxLines = height;\r
43     } else {\r
44         maxLines = 15;\r
45     }\r
46     for (FX_INT32 x = 0; x < maxLines; x++) {\r
47         FX_INT32 rowStepsAboveOrBelow = (x + 1) >> 1;\r
48         FX_BOOL isAbove = (x & 0x01) == 0;\r
49         FX_INT32 rowNumber = middle + rowStep * (isAbove ? rowStepsAboveOrBelow : -rowStepsAboveOrBelow);\r
50         if (rowNumber < 0 || rowNumber >= height) {\r
51             break;\r
52         }\r
53         row = image->GetBlackRow(rowNumber, NULL, e);\r
54         if (e != BCExceptionNO) {\r
55             e = BCExceptionNO;\r
56             if(row != NULL) {\r
57                 delete row;\r
58                 row = NULL;\r
59             }\r
60             continue;\r
61         }\r
62         for (FX_INT32 attempt = 0; attempt < 2; attempt++) {\r
63             if (attempt == 1) {\r
64                 row->Reverse();\r
65             }\r
66             CFX_ByteString result = DecodeRow(rowNumber, row, hints, e);\r
67             if (e != BCExceptionNO) {\r
68                 e = BCExceptionNO;\r
69                 continue;\r
70             }\r
71             if(row != NULL) {\r
72                 delete row;\r
73                 row = NULL;\r
74             }\r
75             return result;\r
76         }\r
77         if(row != NULL) {\r
78             delete row;\r
79             row = NULL;\r
80         }\r
81     }\r
82     e = BCExceptionNotFound;\r
83     return "";\r
84 }\r
85 void CBC_OneDReader::RecordPattern(CBC_CommonBitArray *row, FX_INT32 start, CFX_Int32Array *counters, FX_INT32 &e)\r
86 {\r
87     FX_INT32 numCounters = counters->GetSize();\r
88     for (FX_INT32 i = 0; i < numCounters; i++) {\r
89         (*counters)[i] = 0;\r
90     }\r
91     FX_INT32 end = row->GetSize();\r
92     if (start >= end) {\r
93         e = BCExceptionNotFound;\r
94         return;\r
95     }\r
96     FX_BOOL isWhite = !row->Get(start);\r
97     FX_INT32 counterPosition = 0;\r
98     FX_INT32 j = start;\r
99     while (j < end) {\r
100         FX_BOOL pixel = row->Get(j);\r
101         if (pixel ^ isWhite) {\r
102             (*counters)[counterPosition]++;\r
103         } else {\r
104             counterPosition++;\r
105             if (counterPosition == numCounters) {\r
106                 break;\r
107             } else {\r
108                 (*counters)[counterPosition] = 1;\r
109                 isWhite = !isWhite;\r
110             }\r
111         }\r
112         j++;\r
113     }\r
114     if (!(counterPosition == numCounters || (counterPosition == numCounters - 1 && j == end))) {\r
115         e = BCExceptionNotFound;\r
116         return;\r
117     }\r
118 }\r
119 void CBC_OneDReader::RecordPatternInReverse(CBC_CommonBitArray *row, FX_INT32 start, CFX_Int32Array *counters, FX_INT32 &e)\r
120 {\r
121     FX_INT32 numTransitionsLeft = counters->GetSize();\r
122     FX_BOOL last = row->Get(start);\r
123     while (start > 0 && numTransitionsLeft >= 0) {\r
124         if (row->Get(--start) != last) {\r
125             numTransitionsLeft--;\r
126             last = !last;\r
127         }\r
128     }\r
129     if (numTransitionsLeft >= 0) {\r
130         e = BCExceptionNotFound;\r
131         return;\r
132     }\r
133     RecordPattern(row, start + 1, counters, e);\r
134     BC_EXCEPTION_CHECK_ReturnVoid(e);\r
135 }\r
136 FX_INT32 CBC_OneDReader::PatternMatchVariance(CFX_Int32Array *counters, const FX_INT32 *pattern, FX_INT32 maxIndividualVariance)\r
137 {\r
138     FX_INT32 numCounters = counters->GetSize();\r
139     FX_INT32 total = 0;\r
140     FX_INT32 patternLength = 0;\r
141     for (FX_INT32 i = 0; i < numCounters; i++) {\r
142         total += (*counters)[i];\r
143         patternLength += pattern[i];\r
144     }\r
145     if (total < patternLength) {\r
146 #undef max\r
147         return FXSYS_IntMax;\r
148     }\r
149     FX_INT32 unitBarWidth = (total << INTEGER_MATH_SHIFT) / patternLength;\r
150     maxIndividualVariance = (maxIndividualVariance * unitBarWidth) >> INTEGER_MATH_SHIFT;\r
151     FX_INT32 totalVariance = 0;\r
152     for (FX_INT32 x = 0; x < numCounters; x++) {\r
153         FX_INT32 counter = (*counters)[x] << INTEGER_MATH_SHIFT;\r
154         FX_INT32 scaledPattern = pattern[x] * unitBarWidth;\r
155         FX_INT32 variance = counter > scaledPattern ? counter - scaledPattern : scaledPattern - counter;\r
156         if (variance > maxIndividualVariance) {\r
157 #undef max\r
158             return FXSYS_IntMax;\r
159         }\r
160         totalVariance += variance;\r
161     }\r
162     return totalVariance / total;\r
163 }\r