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