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