OLD | NEW |
| (Empty) |
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 2012 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 "barcode.h" | |
24 #include "include/BC_PDF417Common.h" | |
25 #include "include/BC_PDF417ECModulusPoly.h" | |
26 #include "include/BC_PDF417ECModulusGF.h" | |
27 #include "include/BC_PDF417ECErrorCorrection.h" | |
28 CBC_PDF417ECModulusGF* CBC_PDF417ECErrorCorrection::m_field = NULL; | |
29 void CBC_PDF417ECErrorCorrection::Initialize(FX_INT32 &e) | |
30 { | |
31 m_field = FX_NEW CBC_PDF417ECModulusGF(CBC_PDF417Common::NUMBER_OF_CODEWORDS
, 3, e); | |
32 } | |
33 void CBC_PDF417ECErrorCorrection::Finalize() | |
34 { | |
35 delete m_field; | |
36 } | |
37 CBC_PDF417ECErrorCorrection::CBC_PDF417ECErrorCorrection() | |
38 { | |
39 } | |
40 CBC_PDF417ECErrorCorrection::~CBC_PDF417ECErrorCorrection() | |
41 { | |
42 } | |
43 FX_INT32 CBC_PDF417ECErrorCorrection::decode(CFX_Int32Array &received, FX_INT32
numECCodewords, CFX_Int32Array &erasures, FX_INT32 &e) | |
44 { | |
45 CBC_PDF417ECModulusPoly poly(m_field, received, e); | |
46 BC_EXCEPTION_CHECK_ReturnValue(e, -1); | |
47 CFX_Int32Array S; | |
48 S.SetSize(numECCodewords); | |
49 FX_BOOL error = FALSE; | |
50 for (FX_INT32 l = numECCodewords; l > 0; l--) { | |
51 FX_INT32 eval = poly.evaluateAt(m_field->exp(l)); | |
52 S[numECCodewords - l] = eval; | |
53 if (eval != 0) { | |
54 error = TRUE; | |
55 } | |
56 } | |
57 if (!error) { | |
58 return 0; | |
59 } | |
60 CBC_PDF417ECModulusPoly* syndrome = FX_NEW CBC_PDF417ECModulusPoly(m_field,
S, e); | |
61 BC_EXCEPTION_CHECK_ReturnValue(e, -1); | |
62 CBC_PDF417ECModulusPoly* buildmonomial = m_field->buildMonomial(numECCodewor
ds, 1, e); | |
63 if (e != BCExceptionNO) { | |
64 delete syndrome; | |
65 return -1; | |
66 } | |
67 CFX_PtrArray* sigmaOmega = runEuclideanAlgorithm(buildmonomial, syndrome, nu
mECCodewords, e); | |
68 delete buildmonomial; | |
69 delete syndrome; | |
70 BC_EXCEPTION_CHECK_ReturnValue(e, -1); | |
71 CBC_PDF417ECModulusPoly* sigma = (CBC_PDF417ECModulusPoly*)sigmaOmega->GetAt
(0); | |
72 CBC_PDF417ECModulusPoly* omega = (CBC_PDF417ECModulusPoly*)sigmaOmega->GetAt
(1); | |
73 CFX_Int32Array* errorLocations = findErrorLocations(sigma, e); | |
74 if (e != BCExceptionNO) { | |
75 for (FX_INT32 i = 0; i < sigmaOmega->GetSize(); i++) { | |
76 delete (CBC_PDF417ECModulusPoly*)sigmaOmega->GetAt(i); | |
77 } | |
78 sigmaOmega->RemoveAll(); | |
79 delete sigmaOmega; | |
80 return -1; | |
81 } | |
82 CFX_Int32Array* errorMagnitudes = findErrorMagnitudes(omega, sigma, *errorLo
cations, e); | |
83 if (e != BCExceptionNO) { | |
84 delete errorLocations; | |
85 for (FX_INT32 i = 0; i < sigmaOmega->GetSize(); i++) { | |
86 delete (CBC_PDF417ECModulusPoly*)sigmaOmega->GetAt(i); | |
87 } | |
88 sigmaOmega->RemoveAll(); | |
89 delete sigmaOmega; | |
90 return -1; | |
91 } | |
92 for (FX_INT32 i = 0; i < errorLocations->GetSize(); i++) { | |
93 FX_INT32 log = m_field->log(errorLocations->GetAt(i), e);; | |
94 BC_EXCEPTION_CHECK_ReturnValue(e, -1); | |
95 FX_INT32 position = received.GetSize() - 1 - log; | |
96 if (position < 0) { | |
97 e = BCExceptionChecksumException; | |
98 delete errorLocations; | |
99 delete errorMagnitudes; | |
100 for (FX_INT32 j = 0; j < sigmaOmega->GetSize(); j++) { | |
101 delete (CBC_PDF417ECModulusPoly*)sigmaOmega->GetAt(j); | |
102 } | |
103 sigmaOmega->RemoveAll(); | |
104 delete sigmaOmega; | |
105 return -1; | |
106 } | |
107 received[position] = m_field->subtract(received[position], errorMagnitud
es->GetAt(i)); | |
108 } | |
109 FX_INT32 result = errorLocations->GetSize(); | |
110 delete errorLocations; | |
111 delete errorMagnitudes; | |
112 for (FX_INT32 k = 0; k < sigmaOmega->GetSize(); k++) { | |
113 delete (CBC_PDF417ECModulusPoly*)sigmaOmega->GetAt(k); | |
114 } | |
115 sigmaOmega->RemoveAll(); | |
116 delete sigmaOmega; | |
117 return result; | |
118 } | |
119 CFX_PtrArray* CBC_PDF417ECErrorCorrection::runEuclideanAlgorithm(CBC_PDF417ECMod
ulusPoly* a, CBC_PDF417ECModulusPoly* b, FX_INT32 R, FX_INT32 &e) | |
120 { | |
121 if (a->getDegree() < b->getDegree()) { | |
122 CBC_PDF417ECModulusPoly* temp = a; | |
123 a = b; | |
124 b = temp; | |
125 } | |
126 CBC_PDF417ECModulusPoly* rLast = a; | |
127 CBC_PDF417ECModulusPoly* r = b; | |
128 CBC_PDF417ECModulusPoly* tLast = m_field->getZero(); | |
129 CBC_PDF417ECModulusPoly* t = m_field->getOne(); | |
130 CBC_PDF417ECModulusPoly* qtemp = NULL; | |
131 CBC_PDF417ECModulusPoly* rtemp = NULL; | |
132 CBC_PDF417ECModulusPoly* ttemp = NULL; | |
133 FX_INT32 i = 0; | |
134 FX_INT32 j = 0; | |
135 FX_INT32 m = 0; | |
136 FX_INT32 n = 0; | |
137 while (r->getDegree() >= R / 2) { | |
138 CBC_PDF417ECModulusPoly* rLastLast = rLast; | |
139 CBC_PDF417ECModulusPoly* tLastLast = tLast; | |
140 rLast = r; | |
141 tLast = t; | |
142 m = i; | |
143 n = j; | |
144 if (rLast->isZero()) { | |
145 e = BCExceptionChecksumException; | |
146 if (qtemp) { | |
147 delete qtemp; | |
148 } | |
149 if (rtemp) { | |
150 delete rtemp; | |
151 } | |
152 if (ttemp) { | |
153 delete ttemp; | |
154 } | |
155 return NULL; | |
156 } | |
157 r = rLastLast; | |
158 CBC_PDF417ECModulusPoly* q = m_field->getZero(); | |
159 FX_INT32 denominatorLeadingTerm = rLast->getCoefficient(rLast->getDegree
()); | |
160 FX_INT32 dltInverse = m_field->inverse(denominatorLeadingTerm, e); | |
161 if (e != BCExceptionNO) { | |
162 if (qtemp) { | |
163 delete qtemp; | |
164 } | |
165 if (rtemp) { | |
166 delete rtemp; | |
167 } | |
168 if (ttemp) { | |
169 delete ttemp; | |
170 } | |
171 return NULL; | |
172 } | |
173 while (r->getDegree() >= rLast->getDegree() && !r->isZero()) { | |
174 FX_INT32 degreeDiff = r->getDegree() - rLast->getDegree(); | |
175 FX_INT32 scale = m_field->multiply(r->getCoefficient(r->getDegree())
, dltInverse); | |
176 CBC_PDF417ECModulusPoly* buildmonomial = m_field->buildMonomial(degr
eeDiff, scale, e); | |
177 if (e != BCExceptionNO) { | |
178 if (qtemp) { | |
179 delete qtemp; | |
180 } | |
181 if (rtemp) { | |
182 delete rtemp; | |
183 } | |
184 if (ttemp) { | |
185 delete ttemp; | |
186 } | |
187 return NULL; | |
188 } | |
189 q = q->add(buildmonomial, e); | |
190 delete buildmonomial; | |
191 if (qtemp) { | |
192 delete qtemp; | |
193 } | |
194 if (e != BCExceptionNO) { | |
195 if (rtemp) { | |
196 delete rtemp; | |
197 } | |
198 if (ttemp) { | |
199 delete ttemp; | |
200 } | |
201 return NULL; | |
202 } | |
203 qtemp = q; | |
204 CBC_PDF417ECModulusPoly* multiply = rLast->multiplyByMonomial(degre
eDiff, scale, e); | |
205 if (e != BCExceptionNO) { | |
206 if (qtemp) { | |
207 delete qtemp; | |
208 } | |
209 if (rtemp) { | |
210 delete rtemp; | |
211 } | |
212 if (ttemp) { | |
213 delete ttemp; | |
214 } | |
215 return NULL; | |
216 } | |
217 CBC_PDF417ECModulusPoly* temp = r; | |
218 r = temp->subtract(multiply, e); | |
219 delete multiply; | |
220 if (m > 1 && i > m) { | |
221 delete temp; | |
222 temp = NULL; | |
223 } | |
224 if (e != BCExceptionNO) { | |
225 if (qtemp) { | |
226 delete qtemp; | |
227 } | |
228 if (rtemp) { | |
229 delete rtemp; | |
230 } | |
231 if (ttemp) { | |
232 delete ttemp; | |
233 } | |
234 return NULL; | |
235 } | |
236 rtemp = r; | |
237 i = m + 1; | |
238 } | |
239 ttemp = q->multiply(tLast, e); | |
240 if (qtemp) { | |
241 delete qtemp; | |
242 qtemp = NULL; | |
243 } | |
244 if (e != BCExceptionNO) { | |
245 if (rtemp) { | |
246 delete rtemp; | |
247 } | |
248 if (ttemp) { | |
249 delete ttemp; | |
250 } | |
251 return NULL; | |
252 } | |
253 t = ttemp->subtract(tLastLast, e); | |
254 if (n > 1 && j > n) { | |
255 delete tLastLast; | |
256 } | |
257 delete ttemp; | |
258 if (e != BCExceptionNO) { | |
259 if (rtemp) { | |
260 delete rtemp; | |
261 } | |
262 return NULL; | |
263 } | |
264 ttemp = t; | |
265 t = ttemp->negative(e); | |
266 delete ttemp; | |
267 if (e != BCExceptionNO) { | |
268 if (rtemp) { | |
269 delete rtemp; | |
270 } | |
271 return NULL; | |
272 } | |
273 ttemp = t; | |
274 j++; | |
275 } | |
276 FX_INT32 aa = t->getCoefficient(1); | |
277 FX_INT32 sigmaTildeAtZero = t->getCoefficient(0); | |
278 if (sigmaTildeAtZero == 0) { | |
279 e = BCExceptionChecksumException; | |
280 if (rtemp) { | |
281 delete rtemp; | |
282 } | |
283 if (ttemp) { | |
284 delete ttemp; | |
285 } | |
286 return NULL; | |
287 } | |
288 FX_INT32 inverse = m_field->inverse(sigmaTildeAtZero, e); | |
289 if (e != BCExceptionNO) { | |
290 if (rtemp) { | |
291 delete rtemp; | |
292 } | |
293 if (ttemp) { | |
294 delete ttemp; | |
295 } | |
296 return NULL; | |
297 } | |
298 CBC_PDF417ECModulusPoly* sigma = t->multiply(inverse, e); | |
299 if (ttemp) { | |
300 delete ttemp; | |
301 } | |
302 if (e != BCExceptionNO) { | |
303 if (rtemp) { | |
304 delete rtemp; | |
305 } | |
306 return NULL; | |
307 } | |
308 CBC_PDF417ECModulusPoly* omega = r->multiply(inverse, e); | |
309 if (rtemp) { | |
310 delete rtemp; | |
311 } | |
312 BC_EXCEPTION_CHECK_ReturnValue(e, NULL); | |
313 CFX_PtrArray* modulusPoly = FX_NEW CFX_PtrArray; | |
314 modulusPoly->Add(sigma); | |
315 modulusPoly->Add(omega); | |
316 return modulusPoly; | |
317 } | |
318 CFX_Int32Array* CBC_PDF417ECErrorCorrection::findErrorLocations(CBC_PDF417ECModu
lusPoly* errorLocator, FX_INT32 &e) | |
319 { | |
320 FX_INT32 numErrors = errorLocator->getDegree(); | |
321 CFX_Int32Array* result = FX_NEW CFX_Int32Array; | |
322 result->SetSize(numErrors); | |
323 FX_INT32 ee = 0; | |
324 for (FX_INT32 i = 1; i < m_field->getSize() && ee < numErrors; i++) { | |
325 if (errorLocator->evaluateAt(i) == 0) { | |
326 result->SetAt(ee, m_field->inverse(i, e)); | |
327 if (e != BCExceptionNO) { | |
328 delete result; | |
329 return NULL; | |
330 } | |
331 ee++; | |
332 } | |
333 } | |
334 if (ee != numErrors) { | |
335 e = BCExceptionChecksumException; | |
336 delete result; | |
337 return NULL; | |
338 } | |
339 return result; | |
340 } | |
341 CFX_Int32Array* CBC_PDF417ECErrorCorrection::findErrorMagnitudes(CBC_PDF417ECMod
ulusPoly* errorEvaluator, CBC_PDF417ECModulusPoly* errorLocator, CFX_Int32Array
&errorLocations, FX_INT32 &e) | |
342 { | |
343 FX_INT32 errorLocatorDegree = errorLocator->getDegree(); | |
344 CFX_Int32Array formalDerivativeCoefficients; | |
345 formalDerivativeCoefficients.SetSize(errorLocatorDegree); | |
346 for (FX_INT32 l = 1; l <= errorLocatorDegree; l++) { | |
347 formalDerivativeCoefficients[errorLocatorDegree - l] = m_field->multiply
(l, errorLocator->getCoefficient(l)); | |
348 } | |
349 CBC_PDF417ECModulusPoly formalDerivative(m_field, formalDerivativeCoefficien
ts, e); | |
350 BC_EXCEPTION_CHECK_ReturnValue(e, NULL); | |
351 FX_INT32 s = errorLocations.GetSize(); | |
352 CFX_Int32Array* result = FX_NEW CFX_Int32Array; | |
353 result->SetSize(s); | |
354 for (FX_INT32 i = 0; i < s; i++) { | |
355 FX_INT32 xiInverse = m_field->inverse(errorLocations[i], e); | |
356 if (e != BCExceptionNO) { | |
357 delete result; | |
358 return NULL; | |
359 } | |
360 FX_INT32 numerator = m_field->subtract(0, errorEvaluator->evaluateAt(xiI
nverse)); | |
361 FX_INT32 denominator = m_field->inverse(formalDerivative.evaluateAt(xiIn
verse), e); | |
362 if (e != BCExceptionNO) { | |
363 delete result; | |
364 return NULL; | |
365 } | |
366 result->SetAt(i, m_field->multiply(numerator, denominator)); | |
367 } | |
368 return result; | |
369 } | |
OLD | NEW |