Home | History | Annotate | Download | only in qrcode
      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 2008 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 "xfa/src/fxbarcode/common/BC_CommonByteMatrix.h"
     25 #include "BC_QRCoderErrorCorrectionLevel.h"
     26 #include "BC_QRCoder.h"
     27 #include "BC_QRCoderMaskUtil.h"
     28 CBC_QRCoderMaskUtil::CBC_QRCoderMaskUtil() {}
     29 CBC_QRCoderMaskUtil::~CBC_QRCoderMaskUtil() {}
     30 int32_t CBC_QRCoderMaskUtil::ApplyMaskPenaltyRule1(
     31     CBC_CommonByteMatrix* matrix) {
     32   return ApplyMaskPenaltyRule1Internal(matrix, TRUE) +
     33          ApplyMaskPenaltyRule1Internal(matrix, FALSE);
     34 }
     35 int32_t CBC_QRCoderMaskUtil::ApplyMaskPenaltyRule2(
     36     CBC_CommonByteMatrix* matrix) {
     37   int32_t penalty = 0;
     38   uint8_t* array = matrix->GetArray();
     39   int32_t width = matrix->GetWidth();
     40   int32_t height = matrix->GetHeight();
     41   for (int32_t y = 0; y < height - 1; y++) {
     42     for (int32_t x = 0; x < width - 1; x++) {
     43       int32_t value = array[y * width + x];
     44       if (value == array[y * width + x + 1] &&
     45           value == array[(y + 1) * width + x] &&
     46           value == array[(y + 1) * width + x + 1]) {
     47         penalty++;
     48       }
     49     }
     50   }
     51   return 3 * penalty;
     52 }
     53 int32_t CBC_QRCoderMaskUtil::ApplyMaskPenaltyRule3(
     54     CBC_CommonByteMatrix* matrix) {
     55   int32_t penalty = 0;
     56   uint8_t* array = matrix->GetArray();
     57   int32_t width = matrix->GetWidth();
     58   int32_t height = matrix->GetHeight();
     59   for (int32_t y = 0; y < height; ++y) {
     60     for (int32_t x = 0; x < width; ++x) {
     61       if (x == 0 &&
     62           ((y >= 0 && y <= 6) || (y >= height - 7 && y <= height - 1))) {
     63         continue;
     64       }
     65       if (x == width - 7 && (y >= 0 && y <= 6)) {
     66         continue;
     67       }
     68       if (y == 0 &&
     69           ((x >= 0 && x <= 6) || (x >= width - 7 && x <= width - 1))) {
     70         continue;
     71       }
     72       if (y == height - 7 && (x >= 0 && x <= 6)) {
     73         continue;
     74       }
     75       if (x + 6 < width && array[y * width + x] == 1 &&
     76           array[y * width + x + 1] == 0 && array[y * width + x + 2] == 1 &&
     77           array[y * width + x + 3] == 1 && array[y * width + x + 4] == 1 &&
     78           array[y * width + x + 5] == 0 && array[y * width + x + 6] == 1 &&
     79           ((x + 10 < width && array[y * width + x + 7] == 0 &&
     80             array[y * width + x + 8] == 0 && array[y * width + x + 9] == 0 &&
     81             array[y * width + x + 10] == 0) ||
     82            (x - 4 >= 0 && array[y * width + x - 1] == 0 &&
     83             array[y * width + x - 2] == 0 && array[y * width + x - 3] == 0 &&
     84             array[y * width + x - 4] == 0))) {
     85         penalty += 40;
     86       }
     87       if (y + 6 < height && array[y * width + x] == 1 &&
     88           array[(y + 1) * width + x] == 0 && array[(y + 2) * width + x] == 1 &&
     89           array[(y + 3) * width + x] == 1 && array[(y + 4) * width + x] == 1 &&
     90           array[(y + 5) * width + x] == 0 && array[(y + 6) * width + x] == 1 &&
     91           ((y + 10 < height && array[(y + 7) * width + x] == 0 &&
     92             array[(y + 8) * width + x] == 0 &&
     93             array[(y + 9) * width + x] == 0 &&
     94             array[(y + 10) * width + x] == 0) ||
     95            (y - 4 >= 0 && array[(y - 1) * width + x] == 0 &&
     96             array[(y - 2) * width + x] == 0 &&
     97             array[(y - 3) * width + x] == 0 &&
     98             array[(y - 4) * width + x] == 0))) {
     99         penalty += 40;
    100       }
    101     }
    102   }
    103   return penalty;
    104 }
    105 int32_t CBC_QRCoderMaskUtil::ApplyMaskPenaltyRule4(
    106     CBC_CommonByteMatrix* matrix) {
    107   int32_t numDarkCells = 0;
    108   uint8_t* array = matrix->GetArray();
    109   int32_t width = matrix->GetWidth();
    110   int32_t height = matrix->GetHeight();
    111   for (int32_t y = 0; y < height; ++y) {
    112     for (int32_t x = 0; x < width; ++x) {
    113       if (array[y * width + x] == 1) {
    114         numDarkCells += 1;
    115       }
    116     }
    117   }
    118   int32_t numTotalCells = matrix->GetHeight() * matrix->GetWidth();
    119   double darkRatio = (double)numDarkCells / numTotalCells;
    120   return abs((int32_t)(darkRatio * 100 - 50) / 5) * 5 * 10;
    121 }
    122 FX_BOOL CBC_QRCoderMaskUtil::GetDataMaskBit(int32_t maskPattern,
    123                                             int32_t x,
    124                                             int32_t y,
    125                                             int32_t& e) {
    126   if (!CBC_QRCoder::IsValidMaskPattern(maskPattern)) {
    127     e = (BCExceptionInvalidateMaskPattern);
    128     BC_EXCEPTION_CHECK_ReturnValue(e, FALSE);
    129   }
    130   int32_t intermediate = 0, temp = 0;
    131   switch (maskPattern) {
    132     case 0:
    133       intermediate = (y + x) & 0x1;
    134       break;
    135     case 1:
    136       intermediate = y & 0x1;
    137       break;
    138     case 2:
    139       intermediate = x % 3;
    140       break;
    141     case 3:
    142       intermediate = (y + x) % 3;
    143       break;
    144     case 4:
    145       intermediate = ((y >> 1) + (x / 3)) & 0x1;
    146       break;
    147     case 5:
    148       temp = y * x;
    149       intermediate = (temp & 0x1) + (temp % 3);
    150       break;
    151     case 6:
    152       temp = y * x;
    153       intermediate = (((temp & 0x1) + (temp % 3)) & 0x1);
    154       break;
    155     case 7:
    156       temp = y * x;
    157       intermediate = (((temp % 3) + ((y + x) & 0x1)) & 0x1);
    158       break;
    159     default: {
    160       e = BCExceptionInvalidateMaskPattern;
    161       BC_EXCEPTION_CHECK_ReturnValue(e, FALSE);
    162     }
    163   }
    164   return intermediate == 0;
    165 }
    166 int32_t CBC_QRCoderMaskUtil::ApplyMaskPenaltyRule1Internal(
    167     CBC_CommonByteMatrix* matrix,
    168     FX_BOOL isHorizontal) {
    169   int32_t penalty = 0;
    170   int32_t numSameBitCells = 0;
    171   int32_t prevBit = -1;
    172   int32_t width = matrix->GetWidth();
    173   int32_t height = matrix->GetHeight();
    174   int32_t iLimit = isHorizontal ? height : width;
    175   int32_t jLimit = isHorizontal ? width : height;
    176   uint8_t* array = matrix->GetArray();
    177   for (int32_t i = 0; i < iLimit; ++i) {
    178     for (int32_t j = 0; j < jLimit; ++j) {
    179       int32_t bit = isHorizontal ? array[i * width + j] : array[j * width + i];
    180       if (bit == prevBit) {
    181         numSameBitCells += 1;
    182         if (numSameBitCells == 5) {
    183           penalty += 3;
    184         } else if (numSameBitCells > 5) {
    185           penalty += 1;
    186         }
    187       } else {
    188         numSameBitCells = 1;
    189         prevBit = bit;
    190       }
    191     }
    192     numSameBitCells = 0;
    193   }
    194   return penalty;
    195 }
    196