国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

聊聊zxing的qrcode

cnTomato / 3053人閱讀

摘要:序本文主要研究下的的一些代碼。可以看到這里重新計算了輸出的寬度和高度,是取了的寬高兩邊的與輸入參數的目標寬高取最大值。也就是說如果的寬高大于目標的寬高,則以的寬高為準,這種情況下的基本跟輸出的一致。

本文主要研究下zxing的qrcode的一些代碼。

maven
        
            com.google.zxing
            core
            3.3.1
        
        
            com.google.zxing
            javase
            3.3.1
        
QRCodeWriter

core-3.3.1-sources.jar!/com/google/zxing/qrcode/QRCodeWriter.java
QRCodeWriter的encode方法進行編碼,轉換為BitMatrix

  @Override
  public BitMatrix encode(String contents,
                          BarcodeFormat format,
                          int width,
                          int height,
                          Map hints) throws WriterException {

    if (contents.isEmpty()) {
      throw new IllegalArgumentException("Found empty contents");
    }

    if (format != BarcodeFormat.QR_CODE) {
      throw new IllegalArgumentException("Can only encode QR_CODE, but got " + format);
    }

    if (width < 0 || height < 0) {
      throw new IllegalArgumentException("Requested dimensions are too small: " + width + "x" +
          height);
    }

    ErrorCorrectionLevel errorCorrectionLevel = ErrorCorrectionLevel.L;
    int quietZone = QUIET_ZONE_SIZE;
    if (hints != null) {
      if (hints.containsKey(EncodeHintType.ERROR_CORRECTION)) {
        errorCorrectionLevel = ErrorCorrectionLevel.valueOf(hints.get(EncodeHintType.ERROR_CORRECTION).toString());
      }
      if (hints.containsKey(EncodeHintType.MARGIN)) {
        quietZone = Integer.parseInt(hints.get(EncodeHintType.MARGIN).toString());
      }
    }

    QRCode code = Encoder.encode(contents, errorCorrectionLevel, hints);
    return renderResult(code, width, height, quietZone);
  }
QRCode

core-3.3.1-sources.jar!/com/google/zxing/qrcode/encoder/QRCode.java

public final class QRCode {

  public static final int NUM_MASK_PATTERNS = 8;

  private Mode mode;
  private ErrorCorrectionLevel ecLevel;
  private Version version;
  private int maskPattern;
  private ByteMatrix matrix;

  public QRCode() {
    maskPattern = -1;
  }

  public Mode getMode() {
    return mode;
  }

  public ErrorCorrectionLevel getECLevel() {
    return ecLevel;
  }

  public Version getVersion() {
    return version;
  }

  public int getMaskPattern() {
    return maskPattern;
  }

  public ByteMatrix getMatrix() {
    return matrix;
  }

  @Override
  public String toString() {
    StringBuilder result = new StringBuilder(200);
    result.append("<<
");
    result.append(" mode: ");
    result.append(mode);
    result.append("
 ecLevel: ");
    result.append(ecLevel);
    result.append("
 version: ");
    result.append(version);
    result.append("
 maskPattern: ");
    result.append(maskPattern);
    if (matrix == null) {
      result.append("
 matrix: null
");
    } else {
      result.append("
 matrix:
");
      result.append(matrix);
    }
    result.append(">>
");
    return result.toString();
  }

  public void setMode(Mode value) {
    mode = value;
  }

  public void setECLevel(ErrorCorrectionLevel value) {
    ecLevel = value;
  }

  public void setVersion(Version version) {
    this.version = version;
  }

  public void setMaskPattern(int value) {
    maskPattern = value;
  }

  public void setMatrix(ByteMatrix value) {
    matrix = value;
  }

  // Check if "mask_pattern" is valid.
  public static boolean isValidMaskPattern(int maskPattern) {
    return maskPattern >= 0 && maskPattern < NUM_MASK_PATTERNS;
  }

}

是由Encoder類encode而來

Encoder

core/3.3.1/core-3.3.1-sources.jar!/com/google/zxing/qrcode/encoder/Encoder.java

 public static QRCode encode(String content,
                              ErrorCorrectionLevel ecLevel,
                              Map hints) throws WriterException {

    // Determine what character encoding has been specified by the caller, if any
    String encoding = DEFAULT_BYTE_MODE_ENCODING;
    boolean hasEncodingHint = hints != null && hints.containsKey(EncodeHintType.CHARACTER_SET);
    if (hasEncodingHint) {
      encoding = hints.get(EncodeHintType.CHARACTER_SET).toString();
    }

    // Pick an encoding mode appropriate for the content. Note that this will not attempt to use
    // multiple modes / segments even if that were more efficient. Twould be nice.
    Mode mode = chooseMode(content, encoding);

    // This will store the header information, like mode and
    // length, as well as "header" segments like an ECI segment.
    BitArray headerBits = new BitArray();

    // Append ECI segment if applicable
    if (mode == Mode.BYTE && (hasEncodingHint || !DEFAULT_BYTE_MODE_ENCODING.equals(encoding))) {
      CharacterSetECI eci = CharacterSetECI.getCharacterSetECIByName(encoding);
      if (eci != null) {
        appendECI(eci, headerBits);
      }
    }

    // (With ECI in place,) Write the mode marker
    appendModeInfo(mode, headerBits);

    // Collect data within the main segment, separately, to count its size if needed. Don"t add it to
    // main payload yet.
    BitArray dataBits = new BitArray();
    appendBytes(content, mode, dataBits, encoding);

    Version version;
    if (hints != null && hints.containsKey(EncodeHintType.QR_VERSION)) {
      int versionNumber = Integer.parseInt(hints.get(EncodeHintType.QR_VERSION).toString());
      version = Version.getVersionForNumber(versionNumber);
      int bitsNeeded = calculateBitsNeeded(mode, headerBits, dataBits, version);
      if (!willFit(bitsNeeded, version, ecLevel)) {
        throw new WriterException("Data too big for requested version");
      }
    } else {
      version = recommendVersion(ecLevel, mode, headerBits, dataBits);
    }

    BitArray headerAndDataBits = new BitArray();
    headerAndDataBits.appendBitArray(headerBits);
    // Find "length" of main segment and write it
    int numLetters = mode == Mode.BYTE ? dataBits.getSizeInBytes() : content.length();
    appendLengthInfo(numLetters, version, mode, headerAndDataBits);
    // Put data together into the overall payload
    headerAndDataBits.appendBitArray(dataBits);

    Version.ECBlocks ecBlocks = version.getECBlocksForLevel(ecLevel);
    int numDataBytes = version.getTotalCodewords() - ecBlocks.getTotalECCodewords();

    // Terminate the bits properly.
    terminateBits(numDataBytes, headerAndDataBits);

    // Interleave data bits with error correction code.
    BitArray finalBits = interleaveWithECBytes(headerAndDataBits,
                                               version.getTotalCodewords(),
                                               numDataBytes,
                                               ecBlocks.getNumBlocks());

    QRCode qrCode = new QRCode();

    qrCode.setECLevel(ecLevel);
    qrCode.setMode(mode);
    qrCode.setVersion(version);

    //  Choose the mask pattern and set to "qrCode".
    int dimension = version.getDimensionForVersion();
    ByteMatrix matrix = new ByteMatrix(dimension, dimension);
    int maskPattern = chooseMaskPattern(finalBits, ecLevel, version, matrix);
    qrCode.setMaskPattern(maskPattern);

    // Build the matrix and set it to "qrCode".
    MatrixUtil.buildMatrix(finalBits, ecLevel, version, maskPattern, matrix);
    qrCode.setMatrix(matrix);

    return qrCode;
  }

這里重點看Version的這段

    Version version;
    if (hints != null && hints.containsKey(EncodeHintType.QR_VERSION)) {
      int versionNumber = Integer.parseInt(hints.get(EncodeHintType.QR_VERSION).toString());
      version = Version.getVersionForNumber(versionNumber);
      int bitsNeeded = calculateBitsNeeded(mode, headerBits, dataBits, version);
      if (!willFit(bitsNeeded, version, ecLevel)) {
        throw new WriterException("Data too big for requested version");
      }
    } else {
      version = recommendVersion(ecLevel, mode, headerBits, dataBits);
    }

這里計算version,同時判斷content的大小,是否超出qrcode的容量,超出的話,拋出WriterException("Data too big for requested version")

willFit計算方法

/**
   * @return true if the number of input bits will fit in a code with the specified version and
   * error correction level.
   */
  private static boolean willFit(int numInputBits, Version version, ErrorCorrectionLevel ecLevel) {
      // In the following comments, we use numbers of Version 7-H.
      // numBytes = 196
      int numBytes = version.getTotalCodewords();
      // getNumECBytes = 130
      Version.ECBlocks ecBlocks = version.getECBlocksForLevel(ecLevel);
      int numEcBytes = ecBlocks.getTotalECCodewords();
      // getNumDataBytes = 196 - 130 = 66
      int numDataBytes = numBytes - numEcBytes;
      int totalInputBytes = (numInputBits + 7) / 8;
      return numDataBytes >= totalInputBytes;
  }
QRCodeWriter.renderResult
// Note that the input matrix uses 0 == white, 1 == black, while the output matrix uses
  // 0 == black, 255 == white (i.e. an 8 bit greyscale bitmap).
  private static BitMatrix renderResult(QRCode code, int width, int height, int quietZone) {
    ByteMatrix input = code.getMatrix();
    if (input == null) {
      throw new IllegalStateException();
    }
    int inputWidth = input.getWidth();
    int inputHeight = input.getHeight();
    int qrWidth = inputWidth + (quietZone * 2);
    int qrHeight = inputHeight + (quietZone * 2);
    int outputWidth = Math.max(width, qrWidth);
    int outputHeight = Math.max(height, qrHeight);

    int multiple = Math.min(outputWidth / qrWidth, outputHeight / qrHeight);
    // Padding includes both the quiet zone and the extra white pixels to accommodate the requested
    // dimensions. For example, if input is 25x25 the QR will be 33x33 including the quiet zone.
    // If the requested size is 200x160, the multiple will be 4, for a QR of 132x132. These will
    // handle all the padding from 100x100 (the actual QR) up to 200x160.
    int leftPadding = (outputWidth - (inputWidth * multiple)) / 2;
    int topPadding = (outputHeight - (inputHeight * multiple)) / 2;

    BitMatrix output = new BitMatrix(outputWidth, outputHeight);

    for (int inputY = 0, outputY = topPadding; inputY < inputHeight; inputY++, outputY += multiple) {
      // Write the contents of this row of the barcode
      for (int inputX = 0, outputX = leftPadding; inputX < inputWidth; inputX++, outputX += multiple) {
        if (input.get(inputX, inputY) == 1) {
          output.setRegion(outputX, outputY, multiple, multiple);
        }
      }
    }

    return output;
  }

這個renderResult根據QRCode信息來構造BitMatrix。可以看到這里重新計算了輸出的寬度和高度,是取了qrcode的寬高+兩邊的quietZone與輸入參數的目標寬高取最大值。也就是說如果qrcode的寬高大于目標的寬高,則以qrcode的寬高為準,這種情況下的quietZone基本跟輸出的一致。

一般而言qrcode的寬高小于目標寬高的話,這種情況下quietZone就跟輸出的不一致,需要經過重新放大,得到的才是最后輸出的padding。

doc

二維碼最大能包含多少信息量?

使用zxing生成和識別二維碼

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/67897.html

相關文章

  • 聊聊qrcodedetect position

    摘要:序本文主要介紹下的,也就是定位圖案,用于定位一張圖片中二維碼所處的位置。分類分為三類是和的原型,從到共種尺寸。是的改良版本,添加了對齊標記,從到共種尺寸。這里默認有個的概念,不同的對應不同的尺寸大小。最高,,所以最高是的矩陣。 序 本文主要介紹下qrcode的detect position,也就是定位圖案,用于定位一張圖片中二維碼所處的位置。 qrcode分類 QRCode 分為 Mo...

    legendaryedu 評論0 收藏0
  • 慕課網_《Java生成二維碼》學習總結

    摘要:時間年月日星期五說明本文部分內容均來自慕課網。線性堆疊式二維碼示意圖矩陣式二維碼在一個矩形空間通過黑白像素在矩陣中的不同分布進行編碼。 時間:2017年06月23日星期五說明:本文部分內容均來自慕課網。@慕課網:http://www.imooc.com教學示例源碼:無個人學習源碼:https://github.com/zccodere/s... 第一章:二維碼的概念 1-1 二維碼概述...

    QLQ 評論0 收藏0
  • 前端vue、jquery/后臺java實現生成二維碼

    摘要:最近項目中需要開發生成二維碼的功能,便于宣傳和使用產品,于是便去研究一番,以下是研究的成果使用生成二維碼二維碼測試內容渲染方式有方式兼容和方式計算模式背景顏色二維碼顏色二維碼糾錯級別默認查看源碼可以看出生成的二維碼使用生成二維 最近項目中需要開發生成二維碼的功能,便于宣傳和使用產品,于是便去研究一番,以下是研究的成果 1.使用jquery生成二維碼 ...

    happyhuangjinjin 評論0 收藏0

發表評論

0條評論

最新活動
閱讀需要支付1元查看
<