Merge to XFA: Use stdint.h types throughout PDFium.
[pdfium.git] / xfa / src / fxbarcode / oned / 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 // Original code is licensed as follows:\r
7 /*\r
8  * Copyright 2008 ZXing authors\r
9  *\r
10  * Licensed under the Apache License, Version 2.0 (the "License");\r
11  * you may not use this file except in compliance with the License.\r
12  * You may obtain a copy of the License at\r
13  *\r
14  *      http://www.apache.org/licenses/LICENSE-2.0\r
15  *\r
16  * Unless required by applicable law or agreed to in writing, software\r
17  * distributed under the License is distributed on an "AS IS" BASIS,\r
18  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
19  * See the License for the specific language governing permissions and\r
20  * limitations under the License.\r
21  */\r
22 \r
23 #include "../barcode.h"\r
24 #include "../BC_Reader.h"\r
25 #include "../BC_BinaryBitmap.h"\r
26 #include "../common/BC_CommonBitArray.h"\r
27 #include "BC_OneDReader.h"\r
28 const int32_t CBC_OneDReader::INTEGER_MATH_SHIFT = 8;\r
29 const int32_t CBC_OneDReader::PATTERN_MATCH_RESULT_SCALE_FACTOR = 1 << 8;\r
30 CBC_OneDReader::CBC_OneDReader()\r
31 {\r
32 }\r
33 CBC_OneDReader::~CBC_OneDReader()\r
34 {\r
35 }\r
36 CFX_ByteString CBC_OneDReader::Decode(CBC_BinaryBitmap *image, int32_t &e)\r
37 {\r
38     CFX_ByteString strtemp = Decode(image, 0, e);\r
39     BC_EXCEPTION_CHECK_ReturnValue(e, "");\r
40     return strtemp;\r
41 }\r
42 CFX_ByteString CBC_OneDReader::Decode(CBC_BinaryBitmap *image, int32_t hints, int32_t &e)\r
43 {\r
44     CFX_ByteString strtemp = DeDecode(image, hints, e);\r
45     BC_EXCEPTION_CHECK_ReturnValue(e, "");\r
46     return strtemp;\r
47 }\r
48 CFX_ByteString CBC_OneDReader::DeDecode(CBC_BinaryBitmap *image, int32_t hints, int32_t &e)\r
49 {\r
50     int32_t width = image->GetWidth();\r
51     int32_t height = image->GetHeight();\r
52     CBC_CommonBitArray *row = NULL;\r
53     int32_t middle = height >> 1;\r
54     FX_BOOL tryHarder = FALSE;\r
55     int32_t rowStep = FX_MAX(1, height >> (tryHarder ? 8 : 5));\r
56     int32_t maxLines;\r
57     if (tryHarder) {\r
58         maxLines = height;\r
59     } else {\r
60         maxLines = 15;\r
61     }\r
62     for (int32_t x = 0; x < maxLines; x++) {\r
63         int32_t rowStepsAboveOrBelow = (x + 1) >> 1;\r
64         FX_BOOL isAbove = (x & 0x01) == 0;\r
65         int32_t rowNumber = middle + rowStep * (isAbove ? rowStepsAboveOrBelow : -rowStepsAboveOrBelow);\r
66         if (rowNumber < 0 || rowNumber >= height) {\r
67             break;\r
68         }\r
69         row = image->GetBlackRow(rowNumber, NULL, e);\r
70         if (e != BCExceptionNO) {\r
71             e = BCExceptionNO;\r
72             if(row != NULL) {\r
73                 delete row;\r
74                 row = NULL;\r
75             }\r
76             continue;\r
77         }\r
78         for (int32_t attempt = 0; attempt < 2; attempt++) {\r
79             if (attempt == 1) {\r
80                 row->Reverse();\r
81             }\r
82             CFX_ByteString result = DecodeRow(rowNumber, row, hints, e);\r
83             if (e != BCExceptionNO) {\r
84                 e = BCExceptionNO;\r
85                 continue;\r
86             }\r
87             if(row != NULL) {\r
88                 delete row;\r
89                 row = NULL;\r
90             }\r
91             return result;\r
92         }\r
93         if(row != NULL) {\r
94             delete row;\r
95             row = NULL;\r
96         }\r
97     }\r
98     e = BCExceptionNotFound;\r
99     return "";\r
100 }\r
101 void CBC_OneDReader::RecordPattern(CBC_CommonBitArray *row, int32_t start, CFX_Int32Array *counters, int32_t &e)\r
102 {\r
103     int32_t numCounters = counters->GetSize();\r
104     for (int32_t i = 0; i < numCounters; i++) {\r
105         (*counters)[i] = 0;\r
106     }\r
107     int32_t end = row->GetSize();\r
108     if (start >= end) {\r
109         e = BCExceptionNotFound;\r
110         return;\r
111     }\r
112     FX_BOOL isWhite = !row->Get(start);\r
113     int32_t counterPosition = 0;\r
114     int32_t j = start;\r
115     while (j < end) {\r
116         FX_BOOL pixel = row->Get(j);\r
117         if (pixel ^ isWhite) {\r
118             (*counters)[counterPosition]++;\r
119         } else {\r
120             counterPosition++;\r
121             if (counterPosition == numCounters) {\r
122                 break;\r
123             } else {\r
124                 (*counters)[counterPosition] = 1;\r
125                 isWhite = !isWhite;\r
126             }\r
127         }\r
128         j++;\r
129     }\r
130     if (!(counterPosition == numCounters || (counterPosition == numCounters - 1 && j == end))) {\r
131         e = BCExceptionNotFound;\r
132         return;\r
133     }\r
134 }\r
135 void CBC_OneDReader::RecordPatternInReverse(CBC_CommonBitArray *row, int32_t start, CFX_Int32Array *counters, int32_t &e)\r
136 {\r
137     int32_t numTransitionsLeft = counters->GetSize();\r
138     FX_BOOL last = row->Get(start);\r
139     while (start > 0 && numTransitionsLeft >= 0) {\r
140         if (row->Get(--start) != last) {\r
141             numTransitionsLeft--;\r
142             last = !last;\r
143         }\r
144     }\r
145     if (numTransitionsLeft >= 0) {\r
146         e = BCExceptionNotFound;\r
147         return;\r
148     }\r
149     RecordPattern(row, start + 1, counters, e);\r
150     BC_EXCEPTION_CHECK_ReturnVoid(e);\r
151 }\r
152 int32_t CBC_OneDReader::PatternMatchVariance(CFX_Int32Array *counters, const int32_t *pattern, int32_t maxIndividualVariance)\r
153 {\r
154     int32_t numCounters = counters->GetSize();\r
155     int32_t total = 0;\r
156     int32_t patternLength = 0;\r
157     for (int32_t i = 0; i < numCounters; i++) {\r
158         total += (*counters)[i];\r
159         patternLength += pattern[i];\r
160     }\r
161     if (total < patternLength) {\r
162 #undef max\r
163         return FXSYS_IntMax;\r
164     }\r
165     int32_t unitBarWidth = (total << INTEGER_MATH_SHIFT) / patternLength;\r
166     maxIndividualVariance = (maxIndividualVariance * unitBarWidth) >> INTEGER_MATH_SHIFT;\r
167     int32_t totalVariance = 0;\r
168     for (int32_t x = 0; x < numCounters; x++) {\r
169         int32_t counter = (*counters)[x] << INTEGER_MATH_SHIFT;\r
170         int32_t scaledPattern = pattern[x] * unitBarWidth;\r
171         int32_t variance = counter > scaledPattern ? counter - scaledPattern : scaledPattern - counter;\r
172         if (variance > maxIndividualVariance) {\r
173 #undef max\r
174             return FXSYS_IntMax;\r
175         }\r
176         totalVariance += variance;\r
177     }\r
178     return totalVariance / total;\r
179 }\r