Home | History | Annotate | Download | only in pdf417
      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 2013 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/barcode.h"
     24 #include "BC_PDF417Common.h"
     25 #include "BC_PDF417CodewordDecoder.h"
     26 #define SYMBOL_TABLE_Length 2787
     27 #define Float_MAX_VALUE 2147483647
     28 FX_FLOAT CBC_PDF417CodewordDecoder::RATIOS_TABLE[2787][8] = {{0}};
     29 CBC_PDF417CodewordDecoder::CBC_PDF417CodewordDecoder() {}
     30 CBC_PDF417CodewordDecoder::~CBC_PDF417CodewordDecoder() {}
     31 void CBC_PDF417CodewordDecoder::Initialize() {
     32   for (int32_t i = 0; i < SYMBOL_TABLE_Length; i++) {
     33     int32_t currentSymbol = CBC_PDF417Common::SYMBOL_TABLE[i];
     34     int32_t currentBit = currentSymbol & 0x1;
     35     for (int32_t j = 0; j < CBC_PDF417Common::BARS_IN_MODULE; j++) {
     36       FX_FLOAT size = 0.0f;
     37       while ((currentSymbol & 0x1) == currentBit) {
     38         size += 1.0f;
     39         currentSymbol >>= 1;
     40       }
     41       currentBit = currentSymbol & 0x1;
     42       RATIOS_TABLE[i][CBC_PDF417Common::BARS_IN_MODULE - j - 1] =
     43           size / CBC_PDF417Common::MODULES_IN_CODEWORD;
     44     }
     45   }
     46 }
     47 void CBC_PDF417CodewordDecoder::Finalize() {}
     48 int32_t CBC_PDF417CodewordDecoder::getDecodedValue(
     49     CFX_Int32Array& moduleBitCount) {
     50   CFX_Int32Array* array = sampleBitCounts(moduleBitCount);
     51   int32_t decodedValue = getDecodedCodewordValue(*array);
     52   delete array;
     53   if (decodedValue != -1) {
     54     return decodedValue;
     55   }
     56   return getClosestDecodedValue(moduleBitCount);
     57 }
     58 CFX_Int32Array* CBC_PDF417CodewordDecoder::sampleBitCounts(
     59     CFX_Int32Array& moduleBitCount) {
     60   FX_FLOAT bitCountSum =
     61       (FX_FLOAT)CBC_PDF417Common::getBitCountSum(moduleBitCount);
     62   CFX_Int32Array* bitCount = new CFX_Int32Array();
     63   bitCount->SetSize(CBC_PDF417Common::BARS_IN_MODULE);
     64   int32_t bitCountIndex = 0;
     65   int32_t sumPreviousBits = 0;
     66   for (int32_t i = 0; i < CBC_PDF417Common::MODULES_IN_CODEWORD; i++) {
     67     FX_FLOAT sampleIndex =
     68         bitCountSum / (2 * CBC_PDF417Common::MODULES_IN_CODEWORD) +
     69         (i * bitCountSum) / CBC_PDF417Common::MODULES_IN_CODEWORD;
     70     if (sumPreviousBits + moduleBitCount.GetAt(bitCountIndex) <= sampleIndex) {
     71       sumPreviousBits += moduleBitCount.GetAt(bitCountIndex);
     72       bitCountIndex++;
     73     }
     74     bitCount->SetAt(bitCountIndex, bitCount->GetAt(bitCountIndex) + 1);
     75   }
     76   return bitCount;
     77 }
     78 int32_t CBC_PDF417CodewordDecoder::getDecodedCodewordValue(
     79     CFX_Int32Array& moduleBitCount) {
     80   int32_t decodedValue = getBitValue(moduleBitCount);
     81   return CBC_PDF417Common::getCodeword(decodedValue) == -1 ? -1 : decodedValue;
     82 }
     83 int32_t CBC_PDF417CodewordDecoder::getBitValue(CFX_Int32Array& moduleBitCount) {
     84   int64_t result = 0;
     85   for (int32_t i = 0; i < moduleBitCount.GetSize(); i++) {
     86     for (int32_t bit = 0; bit < moduleBitCount.GetAt(i); bit++) {
     87       result = (result << 1) | (i % 2 == 0 ? 1 : 0);
     88     }
     89   }
     90   return (int32_t)result;
     91 }
     92 int32_t CBC_PDF417CodewordDecoder::getClosestDecodedValue(
     93     CFX_Int32Array& moduleBitCount) {
     94   int32_t bitCountSum = CBC_PDF417Common::getBitCountSum(moduleBitCount);
     95   CFX_FloatArray bitCountRatios;
     96   bitCountRatios.SetSize(CBC_PDF417Common::BARS_IN_MODULE);
     97   for (int32_t i = 0; i < bitCountRatios.GetSize(); i++) {
     98     bitCountRatios[i] = moduleBitCount.GetAt(i) / (FX_FLOAT)bitCountSum;
     99   }
    100   FX_FLOAT bestMatchError = (FX_FLOAT)Float_MAX_VALUE;
    101   int32_t bestMatch = -1;
    102   for (int32_t j = 0; j < SYMBOL_TABLE_Length; j++) {
    103     FX_FLOAT error = 0.0f;
    104     for (int32_t k = 0; k < CBC_PDF417Common::BARS_IN_MODULE; k++) {
    105       FX_FLOAT diff = RATIOS_TABLE[j][k] - bitCountRatios[k];
    106       error += diff * diff;
    107     }
    108     if (error < bestMatchError) {
    109       bestMatchError = error;
    110       bestMatch = CBC_PDF417Common::SYMBOL_TABLE[j];
    111     }
    112   }
    113   return bestMatch;
    114 }
    115