使用lua生成Code128条形码数据(用于微信、支付宝付款码)

这篇文章是紧接着上一篇文章的:简单解析微信、支付宝,付款码的条形码生成原理

本文中,会演示如何使用上篇文章所讲到的条形码数据生成方法,使用lua语言来生成相关的数据

本文为了方便描述,同样使用b代表一条黑色像素宽度的线,s代表一条白色像素宽度的线,当bs组合时,中间不留任何缝隙

首先我们先制作几个函数,来生成bs字符串,以便后期生成条形码

首先声明我们需要用到的数据,编码格式:

local codes = {}
local codeStartC = "bbsbssbbbss" --C
codes[0+1] = "bbsbbssbbss"
codes[1+1] = "bbssbbsbbss"
codes[2+1] = "bbssbbssbbs"
codes[3+1] = "bssbssbbsss"
codes[4+1] = "bssbsssbbss"
codes[5+1] = "bsssbssbbss"
codes[6+1] = "bssbbssbsss"
codes[7+1] = "bssbbsssbss"
codes[8+1] = "bsssbbssbss"
codes[9+1] = "bbssbssbsss"
codes[10+1] = "bbssbsssbss"
codes[11+1] = "bbsssbssbss"
codes[12+1] = "bsbbssbbbss"
codes[13+1] = "bssbbsbbbss"
codes[14+1] = "bssbbssbbbs"
codes[15+1] = "bsbbbssbbss"
codes[16+1] = "bssbbbsbbss"
codes[17+1] = "bssbbbssbbs"
codes[18+1] = "bbssbbbssbs"
codes[19+1] = "bbssbsbbbss"
codes[20+1] = "bbssbssbbbs"
codes[21+1] = "bbsbbbssbss"
codes[22+1] = "bbssbbbsbss"
codes[23+1] = "bbbsbbsbbbs"
codes[24+1] = "bbbsbssbbss"
codes[25+1] = "bbbssbsbbss"
codes[26+1] = "bbbssbssbbs"
codes[27+1] = "bbbsbbssbss"
codes[28+1] = "bbbssbbsbss"
codes[29+1] = "bbbssbbssbs"
codes[30+1] = "bbsbbsbbsss"
codes[31+1] = "bbsbbsssbbs"
codes[32+1] = "bbsssbbsbbs"
codes[33+1] = "bsbsssbbsss"
codes[34+1] = "bsssbsbbsss"
codes[35+1] = "bsssbsssbbs"
codes[36+1] = "bsbbsssbsss"
codes[37+1] = "bsssbbsbsss"
codes[38+1] = "bsssbbsssbs"
codes[39+1] = "bbsbsssbsss"
codes[40+1] = "bbsssbsbsss"
codes[41+1] = "bbsssbsssbs"
codes[42+1] = "bsbbsbbbsss"
codes[43+1] = "bsbbsssbbbs"
codes[44+1] = "bsssbbsbbbs"
codes[45+1] = "bsbbbsbbsss"
codes[46+1] = "bsbbbsssbbs"
codes[47+1] = "bsssbbbsbbs"
codes[48+1] = "bbbsbbbsbbs"
codes[49+1] = "bbsbsssbbbs"
codes[50+1] = "bbsssbsbbbs"
codes[51+1] = "bbsbbbsbsss"
codes[52+1] = "bbsbbbsssbs"
codes[53+1] = "bbsbbbsbbbs"
codes[54+1] = "bbbsbsbbsss"
codes[55+1] = "bbbsbsssbbs"
codes[56+1] = "bbbsssbsbbs"
codes[57+1] = "bbbsbbsbsss"
codes[58+1] = "bbbsbbsssbs"
codes[59+1] = "bbbsssbbsbs"
codes[60+1] = "bbbsbbbbsbs"
codes[61+1] = "bbssbssssbs"
codes[62+1] = "bbbbsssbsbs"
codes[63+1] = "bsbssbbssss"
codes[64+1] = "bsbssssbbss"
codes[65+1] = "bssbsbbssss"
codes[66+1] = "bssbssssbbs"
codes[67+1] = "bssssbsbbss"
codes[68+1] = "bssssbssbbs"
codes[69+1] = "bsbbssbssss"
codes[70+1] = "bsbbssssbss"
codes[71+1] = "bssbbsbssss"
codes[72+1] = "bssbbssssbs"
codes[73+1] = "bssssbbsbss"
codes[74+1] = "bssssbbssbs"
codes[75+1] = "bbssssbssbs"
codes[76+1] = "bbssbsbssss"
codes[77+1] = "bbbbsbbbsbs"
codes[78+1] = "bbssssbsbss"
codes[79+1] = "bsssbbbbsbs"
codes[80+1] = "bsbssbbbbss"
codes[81+1] = "bssbsbbbbss"
codes[82+1] = "bssbssbbbbs"
codes[83+1] = "bsbbbbssbss"
codes[84+1] = "bssbbbbsbss"
codes[85+1] = "bssbbbbssbs"
codes[86+1] = "bbbbsbssbss"
codes[87+1] = "bbbbssbsbss"
codes[88+1] = "bbbbssbssbs"
codes[89+1] = "bbsbbsbbbbs"
codes[90+1] = "bbsbbbbsbbs"
codes[91+1] = "bbbbsbbsbbs"
codes[92+1] = "bsbsbbbbsss"
codes[93+1] = "bsbsssbbbbs"
codes[94+1] = "bsssbsbbbbs"
codes[95+1] = "bsbbbbsbsss"
codes[96+1] = "bsbbbbsssbs"
codes[97+1] = "bbbbsbsbsss"
codes[98+1] = "bbbbsbsssbs"
codes[99+1] = "bsbbbsbbbbs"
codes[100+1] = "bsbbbbsbbbs"
codes[101+1] = "bbbsbsbbbbs"
codes[102+1] = "bbbbsbsbbbs"
codes[103+1] = "bbsbssssbss"--codeStartA
codes[104+1] = "bbsbssbssss"--codeStartB
codes[106+1] = "bbsssbbbsbsbb"  --end

按C条形码生成规则,处理偶数长度的字符串:

--生成code128C字符串
local function makeCode128C(s)
    if s:len() % 2 == 1 then
        log.warn("barcode.makeCode128C","code not right")
        return
    end
    local codeTemp = {}
    for i=1,s:len()/2 do
        table.insert(codeTemp,s:sub(i*2-1,i*2))
    end
    local check = 105
    for i=1,#codeTemp do
        check = check + i * codeTemp[i]
    end
    check = check % 103
    local result = codeStartC
    for i=1,#codeTemp do
        result = result..codes[codeTemp[i]+1]
    end
    result = result..codes[check+1]..codes[106+1]
    log.info("barcode.makeCode128C",result)
    return result
end

当出现奇数长度字符串时,按C+A拼接生成条形码,并且加入判断,字符串长度为偶数时,使用上面的函数处理:

--生成code128C+A混合字符串,如长度为偶数,只生成C类型条码
local function makeCode128(s)
    if s:len() == 0 or s == nil then
        return
    end
    if s:len() % 2 == 0 then
        return makeCode128C(s)
    end
    local codeTemp = {}
    for i=1,s:len()/2 do
        table.insert(codeTemp,s:sub(i*2-1,i*2))
    end
    local other = tonumber(s:sub(s:len())) + 16
    table.insert(codeTemp,101)
    table.insert(codeTemp,other)
    local check = 105
    for i=1,#codeTemp do
        check = check + i * codeTemp[i]
    end
    check = check % 103

    local result = codeStartC
    for i=1,#codeTemp do
        result = result..codes[codeTemp[i]+1]
    end
    result = result..codes[check+1]..codes[106+1]
    log.info("barcode.makeCode128C+A",result)
    return result
end

这样,我们就可以得到类似于bsbbsbsbbbbbsbbbs...这样的一串字符串了,接下来要实现显示功能,这里用到了合宙luat的disp库:

--- code128 c型条形码显示函数,横向显示
-- @string s,需要显示的字符串,必须为数字,字符个数为偶数个
-- @number x,显示的初始x坐标
-- @number y,显示的初始y坐标
-- @number height,显示的二维码高度
-- @return nil
-- @usage
-- showCode128CX("12345678",0,0,20)
function showCode128CX(s,x,y,height)
    local codeTemp = makeCode128(s)
    if not codeTemp then return end
    for i=1,codeTemp:len() do
        if codeTemp:sub(i,i) == "b" then
            disp.drawrect(x+i-1,y,x+i-1,y+height,0x0000)
        elseif codeTemp:sub(i,i) == "s" then
            disp.drawrect(x+i-1,y,x+i-1,y+height,0xffff)
        end
    end
end

--- code128 c型条形码显示函数,竖向显示
-- @string s,需要显示的字符串,必须为数字,字符个数为偶数个
-- @number x,显示的初始x坐标
-- @number y,显示的初始y坐标
-- @number width,显示的二维码高度
-- @return nil
-- @usage
-- showCode128CY("12345678",0,0,20)
-- barcode.showCode128CY("123412341234123456",10,10,40)
function showCode128CY(s,x,y,width)
    local codeTemp = makeCode128(s)
    if not codeTemp then return end
    for i=1,codeTemp:len() do
        if codeTemp:sub(i,i) == "b" then
            disp.drawrect(x,y+i-1,x+width,y+i-1,0x0000)
        elseif codeTemp:sub(i,i) == "s" then
            disp.drawrect(x,y+i-1,x+width,y+i-1,0xffff)
        end
    end
end

为了方便,再加上一个显示数字的功能,字体需要按自己需求来准备:

--摆放横向数字
function placeNumber(s,x,y)
    local oldFont = disp.setfont(disp.font_12x6)
    for i=1,s:len() do
        disp.puttext(s:sub(i,i),x,y-(i-1)*6)
    end
    disp.setfont(oldFont)
end

最终效果如下:

1 Comment

发表评论

您的电子邮箱地址不会被公开。