安卓系统下生成QR码(四)——强制设置掩膜

来源:互联网 发布:淘宝保证金能退吗 编辑:程序博客网 时间:2024/05/16 09:30

     为了增加QR码识别读取时的可靠性,应该防止编码时黑色块和白色块过于密集地集中在一片区域上,那就需要编码时均匀地在编码区上合理地摆放每一个黑白信息位,而且还要避免出现类似其它功能图形的黑白块,特别是行或者列的黑白块以1011101这种形式出现,那就与位置探测图形的行和列一致,这肯定会造成在解码识别时对位流的误判。

      先看看掩膜效果的过程以及评价方法:



掩膜过程:



评价标准:



     经过上表的规则计算处理后,掩模效果会得到一个具体的数值。这个数值代表着掩模结果的评价,它越大说明在进行的这次掩模过程中符合表中所述的特征数量多,总体表现为掩模的质量差。为了使QR码的阅读识别具有一定的可靠性,最后应采用得分最小的一个掩模条件用于QR码的最终掩模。虽然掩模操作仅对数据码块与纠错码块的编码区域有效,但是掩模的评价是采取了整个QR码的有效区域来计算的....(省略十万字)

     欣赏一下Zxing原生的掩膜评价函数:

  private static int chooseMaskPattern(BitArray bits,ErrorCorrectionLevel errLevel, Version version,ByteMatrix matrix) throws WriterException {    int minPenalty = Integer.MAX_VALUE;  // 掩模越低越好Integer.MAX_VALUE=2的31次方-1    int bestMaskPattern = -1;    int mask_penalty = 0;    // 尝试8种掩码模式来选择最好的掩模 ==8    for (int maskPattern = 0; maskPattern < 8; maskPattern++) {      MatrixUtil.buildMatrix(bits, errLevel, version, maskPattern, matrix);       mask_penalty = calculateMaskPenalty(matrix);      if (mask_penalty < minPenalty) {        minPenalty = mask_penalty;        bestMaskPattern = maskPattern;      }    }    Log.e("——————————————————", "掩模质量mask_penalty:"+mask_penalty);    return bestMaskPattern;  }
  static void buildMatrix(BitArray dataBits,                          ErrorCorrectionLevel ecLevel,                          Version version,                          int maskPattern,                          ByteMatrix matrix) throws WriterException {    clearMatrix(matrix);    embedBasicPatterns(version, matrix);    // 类型信息以任何版本出现    embedTypeInfo(ecLevel, maskPattern, matrix);    // 版本> = 7    maybeEmbedVersionInfo(version, matrix);    // 数据应该被嵌入到最后    embedDataBits(dataBits, maskPattern, matrix);  }
 // 计算掩模,4种评分规则相加,越低说明掩模质量越好  private static int calculateMaskPenalty(ByteMatrix matrix) {    return MaskUtil.applyMaskPenaltyRule1(matrix)        + MaskUtil.applyMaskPenaltyRule2(matrix)        + MaskUtil.applyMaskPenaltyRule3(matrix)        + MaskUtil.applyMaskPenaltyRule4(matrix);  }


    虽然说Zxing在生成QR码时是自动选择8种掩膜效果最好的一种,作为控制欲强的星座,喜欢折腾的我是有点不爽,完成了掩膜的强制设置。

    效果就是随心所需设置你想要的掩膜:




首先,为这8种掩膜的选择添加到一个Spinner:



布局代码:

<Spinner        android:id="@+id/user_set_mask_spinner"        android:layout_width="60dp"        android:layout_height="30dp"        android:background="@drawable/selector_bt_bg"        android:layout_alignTop="@+id/TextView03"        android:layout_toRightOf="@+id/TextView03"        android:layout_marginTop="-5dp"        android:layout_marginLeft="4dp"        android:paddingLeft="5dp"        android:entries="@array/user_set_mask" />

其中,user_set_mask是Spinner的array数据:

 <string-array name="user_set_mask">        <item>自 动</item>        <item>模板0</item>        <item>模板1</item>        <item>模板2</item>        <item>模板3</item>        <item>模板4</item>        <item>模板5</item>        <item>模板6</item>        <item>模板7</item>    </string-array>
点击Spinner后:



Spinner控件的监听处理:

user_set_mask_spinner.setOnItemSelectedListener(new OnItemSelectedListener() {@Overridepublic void onItemSelected(AdapterView<?> parent,View view, int pos, long id) {user_set_mask = pos - 1;}@Overridepublic void onNothingSelected(AdapterView<?> parent) {// Another interface callback}});

user_set_mask是具体的掩膜版本,注意:其数值要等于点击Spinner控件的pos位置减1。


接下来就像《安卓系统下生成QR码(二)——自定义二维码的纠错等级》一样的过程。

在EncodeHintType添加一个枚举(如果没有):

public enum EncodeHintType {// 矫错等级ERROR_CORRECTION, //掩模MASK}

处理user_set_mask,形成能让Zxing接收的哈希表形式,并向CodeWriter的encode方法传递哈希表:

Hashtable hints = new Hashtable();hints.put(EncodeHintType.MASK, user_set_mask);QRCodeWriter CodeWriter = new QRCodeWriter();matrix = CodeWriter.encode(content, CODE_WIDTH, CODE_WIDTH, hints);
encode方法接收哈希表种的user_set_mask的信息并处理:
public BitMatrix encode(String contents,                                                 int width,                           int height,                           Map<EncodeHintType,?> hints) throws WriterException {  int user_set_mask=-1;try {       user_set_mask=(Integer) hints.get(EncodeHintType.MASK); } catch (Exception e) {      // TODO Auto-generated catch block      e.printStackTrace();  }     code = Encoder.encode(contents, errorCorrectionLevel,user_set_mask,hints);     return renderResult(code, width, height, quietZone);   }  

最后,在Encoder类里的encode方法对应的地方做如下接收处理:

  public static QRCode encode(String content,ErrorCorrectionLevel errLevel,int user_set_mask,                              Map<EncodeHintType,?> hints) throws WriterException {if(user_set_mask<=7&&user_set_mask>=0)//强制设置掩模    maskPattern=user_set_mask;}
到此为止,QR码的强制设置掩膜已经完成。

原创粉丝点击