精华内容
下载资源
问答
  • 手绘二维码

    2019-03-22 13:37:12
    看到二维码,很容易猜到黑白相间的小方格就是二进制...你也可以先看看左耳朵耗子写的二维码的生成细节和原理。 版本 二维码一共有 40 个尺寸,官方叫作版本 Version。最小的 Version 1 是 21 × 21 的矩阵,Version...

    看到二维码,很容易猜到黑白相间的小方格就是二进制比特。那么这些比特是怎么得到的?小方格又是按照什么规则排布的?今天咱们就从零开始将一个 url 画成二维码。

    考虑到大多数人可能不太了解二维码,所以先讲下基础概念。你也可以先看看左耳朵耗子写的二维码的生成细节和原理

    版本

    二维码一共有 40 个尺寸,官方叫作版本 Version。最小的 Version 1 是 21 × 21 的矩阵,Version 2 是 25 × 25 的矩阵 … 每增加 1 version,就增加 4 的尺寸。最高是 177 × 177 的矩阵(Version 40)。

    纠错

    根据日常使用经验,无论是残缺、遮挡还是污损,二维码都能够被正确识别,这得益于二维码的纠错机制。

    纠错是通过纠错码实现的,当我们将源数据编码后,会采用一种纠错算法算出编码结果对应的纠错码,连同编码结果一起填充到二维码。

    规范里明确了四个纠错等级,不同等级的纠错比例不同。

    每个版本的纠错码个数都是固定的,比如 version 1-L 需要 7 个纠错码,version 1-M 需要 10 个纠错码,版本越大、数据越多、等级越高,需要的纠错码就越多。

    结构

    二维码可以简单划分为三个部分:固定的功能区(用于定位)、固定的格式信息区(比如二维码用的纠错等级和版本信息)、数据区。

    二进制数据都是严格按 8 位一组填入数据区的,每一组称为一个 codeword。如果数据区的格子数不是 8 的倍数,就会剩下留白(remainder)。每个版本的功能区、格式信息区和留白的位置及其占用的面积都是固定的。

    更详细的划分可以参考规范里的这张图:

    编码

    理论上凡是可以被编译为二进制的数据,都可以用二维码来表示,只要有相应的解码程序即可。规范里规定了几种国际通用的编码模式:

    比如 Numeric 仅支持 0 ~ 9 的数字,它的编码规则是:将数据字符串拆分为每三个一组,每组作为一个十进制的百位数,然后转化为 10 位二进制。为什么是 10 位呢,因为 2^10 = 1024,恰好能覆盖最大的百位数 999。如果最后一组只有两位,则转化为 7 位二进制,如果只有一位,则转化为 4 位二进制。

    Alphanumeric 支持 45 个字符,0 ~ 9、A ~ Z 和几个特殊字符。

    Alphanumeric 的编码规则是:根据上表查出每个 char 对应的 value,然后两两分组,按 A * 45 + B 算出一个值,并将这个值转化为 11 位二进制。如果最后一组只有一位,则将 value 转化为 6 位二进制。

    Byte 模式的编码规则最简单,就是针对单字节字符集(例如 ISO-8859-1)的编码,每个字符恰好用 8 个比特表示。

    我们还可以针对不同的数据片段采用不同的编码模式,这就是混合模式。

    Bit Stream

    二维码包含的二进制串具体是由以下几个部分组成的:

    最开头一定是编码模式,是固定的 4 位(见编码一节的表格)。

    接下来是原字符的长度,不同版本和不同编码模式用多少个比特表示长度是不一样的,具体是几个,规范里有明确的规定。毕竟二维码要在有限的空间里容纳更多的信息,就不能浪费比特,用过长的二进制去表示一个较小的值。

    然后就是对数据按照指定的编码模式编译出的二进制序列。如果以上三部分的数据长度不是 8 的倍数,那么必须添零凑整(terminator)。

    上述数据不见得能填满整个数据区,那么剩余的空间就用两个补齐码(11101100、00010001)交错填满。这两个补齐码是规范指定的。

    以上整个比特串作为输入,用纠错算法输出特定个数的纠错码,二者相接,就是整个二维码数据区的数据了。

    ------------------ 分割线 ------------------

    接下来,咱们就选用最小的版本,和最低的纠错等级,用 Alphanumeric 模式将 I.MEITUAN.COM 这个字符串画成一个二维码。

    Step 1 编码

    查表可以得到每个字符对应的码点,然后两两分组,刚好分成 10 组:(17, 29)(29, 25)(44, 43)(43, 18)(42, 22)(14, 18)(29, 30)(10, 23)(42, 12)(24, 22)。

    按照 A * 45 + B 算出:794, 1330, 2023, 1953, 1912, 648, 1335, 473, 1902, 1102。

    然后将每个数字依次转化为二进制(toString(2)):01100011010 10100110010 11111100111 11110100001 11101111000 01010001000 10100110111 00111011001 11101101110 10001001110。

    Alphanumeric 的 mode indicator 是 0010,在 version 1 里需要 9 个比特表示长度(20 => 000010100),将它们添加到头部:0010 000010100 01100011010 10100110010 11111100111 11110100001 11101111000 01010001000 10100110111 00111011001 11101101110 10001001110。

    按 8 位一组重排,添 0 凑整:00100000 10100011 00011010 10100110 01011111 10011111 11010000 11110111 10000101 00010001 01001101 11001110 11001111 01101110 10001001 11000000

    version 1-L 共有 26 个 codeword,其中有 7 个纠错码(error correction codeword),那么 data codeword 应该有 19 个,目前我们只有 16 个,因此剩下 3 个需要用补齐码凑足:00100000 10100011 00011010 10100110 01011111 10011111 11010000 11110111 10000101 00010001 01001101 11001110 11001111 01101110 10001001 11000000 11101100 00010001 11101100

    然后算出 7 个纠错码:11010100 01110000 01110111 10010001 00101110 10010101 11001111。(我是用 node-qrcode 反算出来的,搞不懂那个纠错算法)。

    最终我们得到了整个编码结果:

    Step 2 填充功能区

    这一步最简单,按照规范里的规定画即可。为了便于区分,用淡紫色表示功能区的白色区域。

    Step 3 填充数据区

    将数据按 8 位一组,从右下角开始蛇形往复填入 2 × 4 的矩形。具体怎么填规范里有明确规定,upwards 方向,将第一个数填入位置 7,第二个数填入位置 6 ... 这里是略有点坑的,因为不是从图中所示的 0 到 7,而是反过来的。方便起见,我们将数据倒过来,再按 0 ~ 7 的顺序依次填入。

    Step 4 Masking

    masking 的作用是使二维码的分布更加均匀。具体操作就是将数据区和 mask pattern 对应位置的比特做异或运算。比如数据区第 8 行第 10 列是白色 0,mask pattern 第 8 行第 10 列是黑色 1,异或运算的结果是黑色 1,那么就将数据区第 8 行第 10 列改成黑色。官方规定了八种 mask pattern(000 ~ 111),我们选用 000。

    Step 5 填充格式信息

    对所有的版本,格式信息都是固定的 15 位。其中两个是纠错等级,三个是 mask pattern,剩下十个是纠错码。

    可以想象,没有格式信息,根本无法进行解码。因此格式信息非常重要,会重复画两次(类似于双机房备份)。

    左下角那一列开头是永远固定的占位符。

    格式信息也需要经历纠错码 + masking 的处理。

    同样的,应该反过来,从位置 14 开始填。当然,也可以先把字符串倒过来。

    最终结果:

    展开全文
  • 用户画像愈清晰明显,那么产品服务对象更加聚焦,和更加专注,产品也更容易成功。 那么什么是用户画像呢? 用户画像,是品牌根据对客户了解、网站数据分析,所拟出一个半虚拟客户模型,代表品牌受众群中...

    对于企业而言,想要做好营销策略,首先必须非常详细地了解目标客户。也就是说,要知道目标客户群体到底是怎样的一群人,搞清楚与他们相关的标签,简而言之就是我们常说的”用户画像“。

    用户画像愈清晰明显,那么产品的服务对象更加聚焦,和更加专注,产品也更容易成功。

    那么什么是用户画像呢?
    用户画像,是品牌根据对客户的了解、网站数据的分析,所拟出的一个半虚拟的客户模型,代表品牌受众群中的“主要特征”,包括背景、喜欢的、不喜欢的、面对的困扰、如何作决定等,这些信息都能帮助品牌了解潜在客户的问题点以及习惯。
    一个品牌可能会有多个用户画像。这是为什么呢?

    公司有不同的产品如果公司有不同的产品或服务的话,应该就要针对不同产品、服务制作不同的用户画像。公司有不同的市场区隔品牌可能会根据客户的年龄、居住地或特定行为等进行市场区隔与细分。

    这时候,我们就必须针对每一个市场区隔中的客户群,做独立的用户画像。根据不同的用户画像,品牌才能准备与之相应的营销策略。

    建立用户画像,我们应该从下面几个方向入手:

    (1) 个人资讯:包含客户的基本资讯。
    专业资讯:包含客户与工作相关的专业资讯,行业、特殊技能、日常规划等。

    (2) 价值观/喜欢/不喜欢的:包含客户生活以及工作上的价值观,或是其他客户喜欢、不喜欢、影响购买的其他因素。

    (3) 目标以及挑战:包含客户的个人、工作的目标,客户现在所面临的问题,品牌如何替他们解决这些问题等。

    (4) 客户在哪里:包含取得资讯的来源,常使用的社群媒体,常读的新闻,参加的活动、会议、其他的相关爱好等。

    (5)是否有不想要的客户:包含太难搞的客户、预算不足的客户、不符合目标产业的客户或是维护关系过于昂贵的客户等。
    ……
    如此多的信息数据从何处收集是个难题。比方可以利用传统问卷调查,虽然有效,但比较而言是一种相当耗时耗力的方式。二维彩虹二维码可以帮助大家快速建立较为详细的用户画像。

    登陆二维彩虹系统后台,可以看到查看到二维码的扫码来源,包括扫码时间、次数、地点、渠道等信息,透过这些资讯与数据,我们可以去制定更符合效益的品牌策略。

    今天就讲到这里了,想要了解更多二维码信息,可以登录二维彩虹官网了解更多。

    相关阅读:

    如何生成一个会说话的二维码?

    如何生成引人关注的微信公众号二维码?

    展开全文
  • 首先这个3*3,水平方向上容易看出来,竖直方向上一是凭感觉猜,而是plot一下,根据坐标轴能看出来。 或者用程序跑出来,本文中便是这样方法,这张二维码长宽都是84,定位块最上面线是坐标是56,刚好2/3. ...

    codeplus 7 彩蛋题汇总:

    https://blog.csdn.net/weixin_42378324/article/details/106449375

    题面:

    初始二维码原图:https://github.com/dq116/codeplus-7/blob/master/QRcode.png

    思路:将图像分成3*3,把定位块放回原位,枚举剩余方块的排列。

    首先这个3*3,水平方向上容易看出来,竖直方向上一是凭感觉猜,而是plot画一下,根据坐标轴能看出来。

    或者用程序跑出来,本文中便是这样方法,这张二维码长宽都是84,定位块最上面的线是的坐标是56,刚好2/3.

    分成3*3后枚举剩余的6块全排列,调用zxing包,识别二维码。

    注意1:如果没有zxing需要先pip一下,且zxing会调用一些java文件,所以系统中应该有java的jre/jdk

    pip install zxing
    

    6个方块的全排列有6!=720种可能

    由于初始排列设置的问题,正确答案的位置是622,我82年的本子跑了774秒。。。

    代码:

    from PIL import Image
    import numpy as np
    import matplotlib.pyplot as plt
    from itertools import permutations
    import time
    import zxing
    
    #把b2放到b1
    def change(b1,b2):
        global img2
        for i in range(b1[0],b1[1]):
            begin=b1[2]
            end=b1[3]
            vertical_gap=b2[0]-b1[0]
            horizontal_gap=b2[2]-b1[2]
            for j in range(begin,end):
                img2[i,j,:]=img[i + vertical_gap, j +horizontal_gap, :]
    def decode_zxing(filename):
        zx = zxing.BarCodeReader()  # 调用条码读取包
        zxdata = zx.decode(filename)  # 图片解码
        if zxdata and zxdata.parsed:
             print(zxdata.parsed)
             return True
        return False
    if __name__ == '__main__':
        path=r'path\QRcode.png'
        img=np.array(Image.open(path))
        m,n,dims=img.shape
        # print(m,n)
        now=255#white
        counter=0
        num=3
        pos_block=0
        for i in range(m):
            if img[i][0][0]==0 and now==255:#white turns to black
                if counter == num:
                    pos_block=i
                    break
                counter+=1
                now=0
            elif  img[i][0][0]==255 and now==0:#black turns to white
                now=255
        # print(pos_block)
        for i in range(pos_block,m):
            begin=int(n*1/3)
            end=int(n*2/3)
            for j in range(begin,end):
                temp=img[i-pos_block,j-begin,:].copy()
                img[i - pos_block, j - begin, :]=img[i,j,:].copy()
                img[i,j,:]=temp.copy()
            begin=end
            end=n
            for j in range(begin, end):
                temp = img[i - pos_block, j , :].copy()
                img[i - pos_block, j , :] = img[i, j, :].copy()
                img[i, j, :] = temp.copy()
        # plt.imshow(img)
        # plt.show()
        # 两条竖线两条横线
        r1 = int(1 / 3 * m)
        r2 = int(2 / 3 * m)
        c1 = int(1 / 3 * n)
        c2 = int(2 / 3 * n)
        b1 = [0, r1, c1, c2]
        b2 = [r1, r2, 0, c1]
        b3 = [r1, r2, c1, c2]
        b4 = [r1, r2, c2, n]
        b5 = [r2, m, c1, c2]
        b6 = [r2, m, c2, n]
        bs = [b1, b2, b3, b4, b5, b6]
        img2=img.copy()
        #正确的排列
        # i = [5, 0, 4, 3, 1, 2]
        full_permutation=list(permutations([0,1, 2, 3,4,5]))
        counter=0
        a = time.perf_counter()
        for i in full_permutation:
            print(i)
            counter+=1
            for j in range(6):
                change(bs[j],bs[i[j]])
            photo=Image.fromarray(img2)
            save_path=r'path\QRcode2.png'
            photo.save(save_path)
            if decode_zxing(save_path):
                print(counter)
                print("time used:" + str(time.perf_counter()))
                break
    
    
    

    复原之后:

     

    展开全文
  • 前言 在使用canvas绘制海报...配置很简单,也容易上手,无论是矩形,还是将图片合成canvas;还是自己定义文字;都是很方便。 附上一个简单例子吧 // const _this=this; wx.getSystemInfo({ success (r
  • 小程序使用canvas画图保存至手机相册 在使用canvas绘制海报过程中不建议使用原生来进行画图,因为默认是...配置很简单,也容易上手,无论是矩形,还是将图片合成canvas;还是自己定义文字;都是很方便。 附上...

    小程序使用canvas画图保存至手机相册

    在使用canvas绘制海报的过程中不建议使用原生来进行画图,因为默认是不支持rpx像素的,px不会做到自适应。

    推荐使用插件 Painter

    github地址 https://github.com/Kujiale-Mobile/Painter

    配置很简单,也容易上手,无论是画矩形,还是将图片合成canvas;还是自己定义文字;都是很方便的。

    附上一个简单的例子吧

    1353044-20190712171351015-1039751385.png

     <painter :customStyle="customStyle" :palette="imgDraw" />
    //
      const _this=this;
          wx.getSystemInfo({
            success (res) {
              _this.drawCanvas(res.windowHeight);
            }
          })
          
    drawCanvas(height) {
    //这里的canvas的高是动态获取设备的高度,做到自适应
           const that = this;
          let heightVal=height*2+'rpx';
          this.imgDraw = {
            width: '750rpx',
            height: heightVal,
            background: '#fff',
            views: [
              {
                type: "rect",
                css: {
                  top: '20rpx',
                  left: '130rpx',
                  color: '#1A1A1A',
                  width: '660rpx',
                  height: '220rpx',
                  borderRadius: '32rpx'
                }
              },
              {
                type: 'image',
                url: './a.jpg',
                css: {
                  top: '36rpx',
                  left: '16rpx',
                  width: '188rpx',
                  height: '188rpx'
                }
              },
              {
                type: 'text',
                text: '',
                css: {
                  top: '54rpx',
                  left: '260rpx',
                  fontSize: '48rpx',
                  color: "#fff"
                }
              },
              {
                type: 'text',
                text: '文字部分',
                css: {
                  top: '134rpx',
                  left: '260rpx',
                  fontSize: '30rpx',
                  color: "#d1d1d1"
                }
              },
              {
                type: 'text',
                text: '1333333333',
                css: {
                  top: '196rpx',
                  left: '260rpx',
                  fontSize: '26rpx',
                  color: "#d1d1d1"
                }
              },
              {
                type: 'text',
                text: '李四',
                css: {
                  top: '304rpx',
                  left: '302rpx',
                  fontSize: '24rpx',
                  color: "#767676"
                }
              },
              {
                type: 'image',
                url: '/icon-localtion.png',
                css: {
                  top: '275rpx',
                  left: '260rpx',
                  width: '26rpx',
                  height: '168rpx'
                }
              },
              {
                type: 'image',
                url: '二维码.png',
                css: {
                  top: '646rpx',
                  left: '236rpx',
                  width: '278rpx',
                  height: '278rpx'
                }
              }
            ]
          }
    
        
          let { path: __path } = mpvue.getStorageSync('createImagePath')
          mpvue.saveImageToPhotosAlbum({
            filePath: __path,
            success(res) {
              // mpvue.showToast({
              //   title: '保存成功',
              //   icon: 'success',
              //   duration: 800,
              //   mask: true
              // });
          
            },
            fail(res) {
              // mpvue.showToast({
              //   title: '保存失败',
              //   icon: 'fail',
              //   duration: 800,
              //   mask: true
              // });
            }
          });
        },
        

    ## 这里涉及到画二维码, 如果你的二维码图片不是一个线上的链接的话,这时需要做一些小操作。

    我的项目中二维码的图片传过来是一个流,所以用img的src默认发送get请求,就能拿到这个图片了。
    所以url会直接发送get请求拿到图片。

    ## canvas的层级
    canvas的层级是最高的,底部的分享块会被遮住,这时你需要用两套方案,一个是纯展示用的,用正常的html来写,给用户看这个名片。
    下载或分享的时候再y用canvas生产你想要图片,接着调用微信的保存api,将图片下载或分享。

    let { path: __path } = mpvue.getStorageSync('createImagePath')
    mpvue.saveImageToPhotosAlbum({
      filePath: __path,
      success(res) {
        // mpvue.showToast({
        //   title: '保存成功',
        //   icon: 'success',
        //   duration: 800,
        //   mask: true
        // });
    
      },
      fail(res) {
        // mpvue.showToast({
        //   title: '保存失败',
        //   icon: 'fail',
        //   duration: 800,
        //   mask: true
        // });
      }
    });

    此时就能顺利完成保存名片的功能了。

    转载于:https://www.cnblogs.com/zhtian/p/11177286.html

    展开全文
  • 第7篇,怎样让用户容易找到你?

    千次阅读 2015-09-02 11:43:35
    当然,这两种方式都属于被动关注,要么是你的文章吸引了他(她),要么是你的二维码进入了他的视线。 还有一种主动关注,譬如:喜欢养花的朋友会主动搜索养花公众号,喜欢养生会搜索养生公众号,喜欢画画的...
  • 经常有这样的需求,就是需要在生成推广海报,包含指定的二维码,分享出去别人扫码之后就可以确定用户推荐关系。 仔细分析一下,推广海报必要的要素就是海报背景图和二维码,这两者都容易生成,但要两者结合到一起...
  • 经常有这样的需求,就是需要在生成推广海报,包含指定的二维码,分享出去别人扫码之后就可以确定用户推荐关系。 仔细分析一下,推广海报必要的要素就是海报背景图和二维码,这两者都容易生成,但要两者结合到一起...
  • 经常有这样的需求,就是需要在生成推广海报,包含指定的二维码,分享出去别人扫码之后就可以确定用户推荐关系。仔细分析一下,推广海报必要的要素就是海报背景图和二维码,这两者都容易生成,但要两者结合到一起组合...
  • 需要一款扫描商品动效,类似微信二维码扫描效果,本来觉得还是挺容易的,在一个框里面加一张图片,再加上 上下动画效果就可以实现了,但UI设计是一个圆形,里面有上下扫描效果,而且背景是透明,所以之前...
  • 兔展、易企秀、意派360等平台,大同小异,要做一个用户互动H5,传播起来更容易。——叫小番总体效果基本流程H5平台:意派360;大概耗时:一个小时;制作难点:参数变量、全局变量;过程概述:基本功能如:截屏、...
  • PHP实现生成推广海报

    千次阅读 热门讨论 2017-12-20 15:37:31
    推广海报必要要素就是海报背景图和二维码,这两者都容易生成,但要两者结合到一起组合成为一张图二维还要可以保存到本地便于分享出去,这就是难点了,在H5中可以借助canvas出来完成类似于截图功能,但放到小...
  • Python简单又好玩的项目推荐!【持续更新】

    千次阅读 多人点赞 2020-06-28 08:59:40
    最近在做Python项目开发时候愣是发现了好多好玩的小项目,并且都是代码量较少容易上手,所以今天就来和小伙伴分享一些Python从一行代码到三十行代码都有哪些好玩的项目。之后大灰狼也会在这里持续更新更多好玩的...
  • 天气APP包含自动定位、天气查询、天气预报、生活指数、每日一图...Google 在Android 6.0时提出了运行时权限管理机制,在Android 6.0之前,所申请权限只需要在AndroidManifest.xml列举就可以,从而容易导致一些安全隐
  • LGame-master游戏开发.zip

    2020-04-20 10:45:22
    jar),所以无论是XML或Json解析,TMX地图构建,物理引擎,游戏脚本,抑或二维码构建,都有自己完整实现(当然,肯定也允许使用第三方),并且能自然和游 戏组件绑定。所以学习难度低(很多事情后台都自动做了),...
  • 您也可以扫描下面的二维码,请作者喝杯咖啡 ☕ 关于我 Name: Jenly Email: jenly1314#gmail.com / jenly1314#vip.qq.com CSDN: jenly121 CNBlogs: jenly Github: jenly1314 加入QQ群: 20867961

空空如也

空空如也

1 2 3 4
收藏数 67
精华内容 26
关键字:

容易画的二维码