模組:EncoderUtil

本页使用了标题或全文手工转换
被永久保护的模块
维基百科,自由的百科全书
文档图示 模块文档[查看] [编辑] [历史] [清除缓存]

主要提供5種編碼解碼工具:

  • JSON編碼/解碼
    • 包含一個「非函數物件之深層複製」的方法
  • 簡易的YAML解碼
  • 二进制編碼
  • QR碼編碼({{QR}})
  • Base64編碼/解碼({{Base64}})

使用方法

JSON

編碼

本模組._jsonEncode

能將Lua編碼為JSON的函數。與mw.text.jsonEncode不同在於,mw.text.jsonEncode遇到函數物件會出錯,而本模組的_jsonEncode會將函數物件以替代符號表示而不會出錯,能正常轉換各種Lua物件。

不支援模板直接呼叫。

解碼

JSON解碼僅需要使用mw.text.jsonDecode即可,本模組無特別提供。

YAML

解碼

本模組.yamlDecode

能將YAML解碼為Lua物件。支援模板直接呼叫。

原始碼 輸出
{{#invoke:EncoderUtil|yamlDecode|
---
receipt:     Oz-Ware Purchase Invoice
date:        2012-08-06
customer:
    given:   Dorothy
    family:  Gale}}
{
  ["customer"] = {
    ["family"] = "Gale",
    ["given"] = "Dorothy"
  },
  ["date"] = 1344182400,
  ["receipt"] = "Oz-Ware Purchase Invoice"
}
本模組.yaml2json

將YAML轉換為JSON。支援模板直接呼叫。

原始碼 輸出
{{#invoke:EncoderUtil|yaml2json|
---
receipt:     Oz-Ware Purchase Invoice
date:        2012-08-06
customer:
    given:   Dorothy
    family:  Gale}}
{"customer":{"given":"Dorothy","family":"Gale"},"date":1344182400,"receipt":"Oz-Ware Purchase Invoice"}

二进制資料流

本函數的功能並非設計給數字進行进制轉換之用,而是資料流的編解碼。若需要將數字進行进制轉換,請參考Module:BaseConvertModule:BigNumber提供的convertBase函數

編碼

本模組._toBinary(x,digits)

能將一整數轉換成指定位數的二進制資料串。(供QR碼資料串編碼使用)

不支援模板直接呼叫。

本模組._binaryEncode(str)

能將一字串以UTF-8的格式編碼為二進制資料串。

有支援模板直接呼叫的函數binaryEncode

  • 原始碼{{#invoke:EncoderUtil|binaryEncode|維基百科}}
    輸出→111001111011011010101101111001011001111110111010111001111001100110111110111001111010011110010001
本模組._hexadecimalEncode(str)

能將一字串以UTF-8的格式編碼為十六进制資料串。

有支援模板直接呼叫的函數hexadecimalEncode

  • 原始碼{{#invoke:EncoderUtil|hexadecimalEncode|維基百科,自由的百科全書}}
    輸出→e7b6ade59fbae799bee7a791efbc8ce887aae794b1e79a84e799bee7a791e585a8e69bb8

解碼

本模組._binaryDecode(bin)

一個二進制資料串解碼為UTF-8格式編碼的字串。

有支援模板直接呼叫的函數binaryDecode

  • 原始碼{{#invoke:EncoderUtil|binaryDecode|111001111011011010101101111001011001111110111010111001111001100110111110111001111010011110010001}}
    輸出→維基百科
本模組._hexadecimalDecode(hex)

一個十六进制資料串解碼為UTF-8格式編碼的字串。

有支援模板直接呼叫的函數hexadecimalDecode

  • 原始碼{{#invoke:EncoderUtil|hexadecimalDecode|e7b6ade59fbae799bee7a791efbc8ce887aae794b1e79a84e799bee7a791e585a8e69bb8}}
    輸出→維基百科,自由的百科全書

QR碼

本模組._get_libqrcode()

初始化QR碼編碼程式庫。此處所有函數皆不支援模板直接呼叫。若要讓模板直接呼叫,請改用Module:QRModule:RegularTiling提供的API(相依於本模組)。

初始化完的程式庫有以下成員:

  • license:記錄函式庫三句版BSD授權條款的詳細資料。
  • encode_string_numeric:將純數字字串編碼為QR碼格式的二进制資料流。
  • encode_string_ascii:將純ASCII字串編碼為QR碼格式的二进制資料流。
  • encode_string_binary:將UTF-8字串編碼為QR碼格式的二进制資料流。
  • encode_data:根據QR碼編碼模式將輸入的資料編碼為QR碼格式的二进制資料流。
  • qrcode:生成完整QR碼二維碼的二进制資料流。
  • get_mode:判斷輸入字串適合的QR碼編碼模式。
  • get_length:將資料長度資訊編碼為QR碼格式的二进制資料流。
  • add_pad_data:生成QR碼的padding bits。
  • get_generator_polynominal_adjusted
  • get_pixel_with_mask:取得QR碼特定位置的掩模。
  • get_version_eclevel_mode_bistringlength
  • get_version_eclevel
  • remainder:各Ver的QR碼編碼時需要補餘的位元數量。
  • arrange_codewords_and_calculate_ec
  • calculate_error_correction:計算糾錯碼
  • convert_bitstring_to_bytes:將長度為的二进制字串轉換為長度為的數字陣列。
  • get_matrix_and_penalty
  • get_matrix_with_lowest_penalty
  • bit_xor

Base64

本模組._get_libbase64()

初始化Base64編碼程式庫。此處所有函數皆不支援模板直接呼叫。

初始化完的程式庫有以下成員:

  • encode( str, encoder, usecaching ):將字串以指定編碼器編碼為Base64
  • decode( b64, decoder, usecaching ):將Base64資料流以指定解碼器進行解碼。
  • makeencoder( s62, s63, spad ):以給定的62、63字元和指定的spad生成編碼器。
  • makedecoder( s62, s63, spad ):以給定的62、63字元和指定的spad生成解碼器。

編碼

本模組.base64Encode(str)

將字串編碼為標準的Base64資料流。支援模板直接呼叫。

  • 原始碼{{#invoke:EncoderUtil|base64Encode|維基百科,自由的百科全書}}
    輸出→57at5Z+655m+56eR77yM6Ieq55Sx55qE55m+56eR5YWo5pu4

解碼

本模組.base64Decode(b64)

將給定的Base64資料流依照標準的Base64格式進行解碼。支援模板直接呼叫。

  • 原始碼{{#invoke:EncoderUtil|base64Decode|57at5Z+655m+56eR77yM6Ieq55Sx55qE55m+56eR5YWo5pu4}}
    輸出→維基百科,自由的百科全書

local p={}
local lib_arg={}
local yaml = require("Module:EncoderUtil/yaml")
local function _safejson_number(obj, flat_out)
	if type(obj) == type(0) then
  		if not not tostring(obj):lower():find('inf') then return tostring(obj) end
    	if not not tostring(obj):lower():find('nan') then return flat_out and tostring(obj) or '\127null\127'end
		return flat_out and tostring(obj) or obj
	else
		return obj
	end
end
local q={}
function q._safejson_clone(obj, deep)
	if type(obj) == type({'table'}) then
		local new_table = {}
		for key,val in pairs(obj) do
			if type(val) == type({'table'}) then
				if deep < 10 then
					new_table[key] = q._safejson_clone(val, deep + 1)
				else
					if xpcall(function()new_table[key] = mw.text.jsonDecode(mw.text.jsonEncode(val))end,function()end) then else new_table[key] = key end
				end
			elseif type(val) == type(function()end) then new_table[key] = key
			elseif type(val) == type(nil) then 
			elseif type(val) == type(0) then new_table[key] = _safejson_number(val)
			else new_table[key] = mw.clone(val) end
		end
		return new_table
	else
		return obj
	end
end
local function _check_table(obj)
	if type(obj) == type({'table'}) then
		local new_table = {}
		for key,val in pairs(obj) do
			if type(val) == type({'table'}) then new_table[key] = q._safejson_clone(val,0)
			elseif type(val) == type(function()end) then new_table[key] = key
			elseif type(val) == type(nil) then new_table[key] = '\127null\127'
			elseif type(val) == type(0) then new_table[key] = _safejson_number(val)
			else new_table[key] = mw.clone(val) end
		end
		return new_table
	else
		return obj
	end
end
local function _jsonEncode(obj)
	local result = ''
	if type(obj) == type({'table'}) then
		result = mw.text.jsonEncode(_check_table(obj))
	elseif type(obj) == type(function()end) then result = 'function'
	elseif type(obj) == type(nil) then result = 'null'
	elseif type(obj) == type(0) then 
		local can_encode = false
		can_encode,result = xpcall(function()return mw.text.jsonEncode(obj)end,function()end)
		if can_encode==false then result=_safejson_number(obj,true)end
	else result = mw.text.jsonEncode(obj) end
	return result
end
function p.yamlDecode(str)
	local input_str = str
	if type(str) == type({"table"}) then
		input_str = (str.args or {})[1] or str[1] or ''
	elseif type(str) ~= type("string") then
		input_str = tostring(str)
	end
	local result = yaml.eval(input_str)
	if str == mw.getCurrentFrame() or type(str.getParent)==type(function()end) then
		return yaml.to_string(result) or ''
	end
	return result
end
function p.yaml2json(str)
	local input_str = str
	if type(str) == type({"table"}) then
		input_str = (str.args or {})[1] or str[1] or ''
	elseif type(str) ~= type("string") then
		input_str = tostring(str)
	end
	local result = yaml.eval(input_str)
	return _jsonEncode(result)
end
function p._get_string_length( str )
	if type(str)==type("str")and str~='' then
		return #str
	elseif type(str)==type(nil)or str=='' then return 0
	elseif type(str)==type(0) then return #(''..str)
	else return #str
	end
	return 0
end

-- Return the binary representation of the number x with the width of `digits`.
function p._toBinary(x,digits)
	  local s=string.format("%o",x)
	  local a={["0"]="000",["1"]="001", ["2"]="010",["3"]="011",
			   ["4"]="100",["5"]="101", ["6"]="110",["7"]="111"}
	  s=string.gsub(s,"(.)",function (d) return a[d] end)
	  -- remove leading 0s
	  s = string.gsub(s,"^0*(.*)$","%1")
	  local fmtstring = string.format("%%%ds",digits)
	  local ret = string.format(fmtstring,s)
	  return string.gsub(ret," ","0")
end

function p._binaryEncode(str)
	local s = tostring(str)
	local bin = ''
	for i=1,s:len() do bin = bin .. p._toBinary(s:byte(i, i), 8) end
	return bin
end

function p._hexadecimalEncode(str)
	local s = tostring(str)
	local hex = ''
	for i=1,s:len() do hex = hex .. ("%%%ds"):format(2):format(("%x"):format(s:byte(i, i))):gsub(' ','0')end
	return hex
end

function p._binaryDecode(str)
	local s, result = tostring(str), ''
	local s_len = s:len()
	local lose = s_len % 8
	if lose > 0 then lose = 8 - lose end
	s_len = (s_len + lose) / 8
	s = ('0'):rep(lose)..s
	for i=0,s_len-1 do result = result .. string.char(tonumber(s:sub(i*8+1, i*8+8),2)) end
	return result
end

function p._hexadecimalDecode(str)
	local s, result = tostring(str), ''
	local s_len = s:len()
	local lose = s_len % 2
	if lose > 0 then lose = 2 - lose end
	s_len = (s_len + lose) / 2
	s = ('0'):rep(lose)..s
	for i=0,s_len-1 do result = result .. string.char(tonumber(s:sub(i*2+1, i*2+2),16)) end
	return result
end

function p.binaryEncode(str)
	local input_str = str
	if type(str) == type({"table"}) then
		input_str = (str.args or {})[1] or str[1] or ''
	elseif type(str) ~= type("string") then
		input_str = tostring(str)
	end
	return p._binaryEncode(input_str)
end

function p.hexadecimalEncode(str)
	local input_str = str
	if type(str) == type({"table"}) then
		input_str = (str.args or {})[1] or str[1] or ''
	elseif type(str) ~= type("string") then
		input_str = tostring(str)
	end
	return p._hexadecimalEncode(input_str)
end

function p.binaryDecode(str)
	local input_str = str
	if type(str) == type({"table"}) then
		input_str = (str.args or {})[1] or str[1] or ''
	elseif type(str) ~= type("string") then
		input_str = tostring(str)
	end
	return p._binaryDecode(input_str)
end

function p.hexadecimalDecode(str)
	local input_str = str
	if type(str) == type({"table"}) then
		input_str = (str.args or {})[1] or str[1] or ''
	elseif type(str) ~= type("string") then
		input_str = tostring(str)
	end
	return p._hexadecimalDecode(input_str)
end

function p._get_bytes( str,... )
		if #{...}<1 then return 0 end
		local result={}
		
		if type(str)==type("str")and str~='' then
			return str:byte(...)
		elseif type(str)==type(nil)or type(str)==type(0)or str=='' then 
			for i=1,#{...}do result[#result+1]=0 end
		elseif #{...}>2 or #{...}==1 then
			for key,value in pairs{...}do result[#result+1]=str[tonumber(value)or-1] end
		else
			local start,end_=unpack{...}
			for i=start,end_,(end_>=start and 1 or-1)do result[#result+1]=str[i] end
		end
		for i=1,#result do
			result[i] = (tonumber(result[i])or 0)%256
		end
		if #result > 0 then return unpack(result) end
		return 0
end

local function init_qrcode_library()
	local license =[[
	 The qrcode library is licensed under the 3-clause BSD license (aka "new BSD")
	 Copyright (c) 2012-2020, Patrick Gundlach and contributors, see https://github.com/speedata/luaqrcode , All rights reserved.

	 Redistribution and use in source and binary forms, with or without
	 modification, are permitted provided that the following conditions are met:
		 * Redistributions of source code must retain the above copyright
		   notice, this list of conditions and the following disclaimer.
		 * Redistributions in binary form must reproduce the above copyright
		   notice, this list of conditions and the following disclaimer in the
		   documentation and/or other materials provided with the distribution.
		 * Neither the name of the <organization> nor the
		   names of its contributors may be used to endorse or promote products
		   derived from this software without specific prior written permission.

	 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
	 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
	 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
	 DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
	 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
	 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
	 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
	 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
	 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
	 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
	]]
	-- To calculate xor we need to do that bitwise. This helper table speeds up the num-to-bit
	-- part a bit (no pun intended)
	local cclxvi = {[0] = {0,0,0,0,0,0,0,0}, {1,0,0,0,0,0,0,0}, {0,1,0,0,0,0,0,0}, {1,1,0,0,0,0,0,0},
	{0,0,1,0,0,0,0,0}, {1,0,1,0,0,0,0,0}, {0,1,1,0,0,0,0,0}, {1,1,1,0,0,0,0,0},
	{0,0,0,1,0,0,0,0}, {1,0,0,1,0,0,0,0}, {0,1,0,1,0,0,0,0}, {1,1,0,1,0,0,0,0},
	{0,0,1,1,0,0,0,0}, {1,0,1,1,0,0,0,0}, {0,1,1,1,0,0,0,0}, {1,1,1,1,0,0,0,0},
	{0,0,0,0,1,0,0,0}, {1,0,0,0,1,0,0,0}, {0,1,0,0,1,0,0,0}, {1,1,0,0,1,0,0,0},
	{0,0,1,0,1,0,0,0}, {1,0,1,0,1,0,0,0}, {0,1,1,0,1,0,0,0}, {1,1,1,0,1,0,0,0},
	{0,0,0,1,1,0,0,0}, {1,0,0,1,1,0,0,0}, {0,1,0,1,1,0,0,0}, {1,1,0,1,1,0,0,0},
	{0,0,1,1,1,0,0,0}, {1,0,1,1,1,0,0,0}, {0,1,1,1,1,0,0,0}, {1,1,1,1,1,0,0,0},
	{0,0,0,0,0,1,0,0}, {1,0,0,0,0,1,0,0}, {0,1,0,0,0,1,0,0}, {1,1,0,0,0,1,0,0},
	{0,0,1,0,0,1,0,0}, {1,0,1,0,0,1,0,0}, {0,1,1,0,0,1,0,0}, {1,1,1,0,0,1,0,0},
	{0,0,0,1,0,1,0,0}, {1,0,0,1,0,1,0,0}, {0,1,0,1,0,1,0,0}, {1,1,0,1,0,1,0,0},
	{0,0,1,1,0,1,0,0}, {1,0,1,1,0,1,0,0}, {0,1,1,1,0,1,0,0}, {1,1,1,1,0,1,0,0},
	{0,0,0,0,1,1,0,0}, {1,0,0,0,1,1,0,0}, {0,1,0,0,1,1,0,0}, {1,1,0,0,1,1,0,0},
	{0,0,1,0,1,1,0,0}, {1,0,1,0,1,1,0,0}, {0,1,1,0,1,1,0,0}, {1,1,1,0,1,1,0,0},
	{0,0,0,1,1,1,0,0}, {1,0,0,1,1,1,0,0}, {0,1,0,1,1,1,0,0}, {1,1,0,1,1,1,0,0},
	{0,0,1,1,1,1,0,0}, {1,0,1,1,1,1,0,0}, {0,1,1,1,1,1,0,0}, {1,1,1,1,1,1,0,0},
	{0,0,0,0,0,0,1,0}, {1,0,0,0,0,0,1,0}, {0,1,0,0,0,0,1,0}, {1,1,0,0,0,0,1,0},
	{0,0,1,0,0,0,1,0}, {1,0,1,0,0,0,1,0}, {0,1,1,0,0,0,1,0}, {1,1,1,0,0,0,1,0},
	{0,0,0,1,0,0,1,0}, {1,0,0,1,0,0,1,0}, {0,1,0,1,0,0,1,0}, {1,1,0,1,0,0,1,0},
	{0,0,1,1,0,0,1,0}, {1,0,1,1,0,0,1,0}, {0,1,1,1,0,0,1,0}, {1,1,1,1,0,0,1,0},
	{0,0,0,0,1,0,1,0}, {1,0,0,0,1,0,1,0}, {0,1,0,0,1,0,1,0}, {1,1,0,0,1,0,1,0},
	{0,0,1,0,1,0,1,0}, {1,0,1,0,1,0,1,0}, {0,1,1,0,1,0,1,0}, {1,1,1,0,1,0,1,0},
	{0,0,0,1,1,0,1,0}, {1,0,0,1,1,0,1,0}, {0,1,0,1,1,0,1,0}, {1,1,0,1,1,0,1,0},
	{0,0,1,1,1,0,1,0}, {1,0,1,1,1,0,1,0}, {0,1,1,1,1,0,1,0}, {1,1,1,1,1,0,1,0},
	{0,0,0,0,0,1,1,0}, {1,0,0,0,0,1,1,0}, {0,1,0,0,0,1,1,0}, {1,1,0,0,0,1,1,0},
	{0,0,1,0,0,1,1,0}, {1,0,1,0,0,1,1,0}, {0,1,1,0,0,1,1,0}, {1,1,1,0,0,1,1,0},
	{0,0,0,1,0,1,1,0}, {1,0,0,1,0,1,1,0}, {0,1,0,1,0,1,1,0}, {1,1,0,1,0,1,1,0},
	{0,0,1,1,0,1,1,0}, {1,0,1,1,0,1,1,0}, {0,1,1,1,0,1,1,0}, {1,1,1,1,0,1,1,0},
	{0,0,0,0,1,1,1,0}, {1,0,0,0,1,1,1,0}, {0,1,0,0,1,1,1,0}, {1,1,0,0,1,1,1,0},
	{0,0,1,0,1,1,1,0}, {1,0,1,0,1,1,1,0}, {0,1,1,0,1,1,1,0}, {1,1,1,0,1,1,1,0},
	{0,0,0,1,1,1,1,0}, {1,0,0,1,1,1,1,0}, {0,1,0,1,1,1,1,0}, {1,1,0,1,1,1,1,0},
	{0,0,1,1,1,1,1,0}, {1,0,1,1,1,1,1,0}, {0,1,1,1,1,1,1,0}, {1,1,1,1,1,1,1,0},
	{0,0,0,0,0,0,0,1}, {1,0,0,0,0,0,0,1}, {0,1,0,0,0,0,0,1}, {1,1,0,0,0,0,0,1},
	{0,0,1,0,0,0,0,1}, {1,0,1,0,0,0,0,1}, {0,1,1,0,0,0,0,1}, {1,1,1,0,0,0,0,1},
	{0,0,0,1,0,0,0,1}, {1,0,0,1,0,0,0,1}, {0,1,0,1,0,0,0,1}, {1,1,0,1,0,0,0,1},
	{0,0,1,1,0,0,0,1}, {1,0,1,1,0,0,0,1}, {0,1,1,1,0,0,0,1}, {1,1,1,1,0,0,0,1},
	{0,0,0,0,1,0,0,1}, {1,0,0,0,1,0,0,1}, {0,1,0,0,1,0,0,1}, {1,1,0,0,1,0,0,1},
	{0,0,1,0,1,0,0,1}, {1,0,1,0,1,0,0,1}, {0,1,1,0,1,0,0,1}, {1,1,1,0,1,0,0,1},
	{0,0,0,1,1,0,0,1}, {1,0,0,1,1,0,0,1}, {0,1,0,1,1,0,0,1}, {1,1,0,1,1,0,0,1},
	{0,0,1,1,1,0,0,1}, {1,0,1,1,1,0,0,1}, {0,1,1,1,1,0,0,1}, {1,1,1,1,1,0,0,1},
	{0,0,0,0,0,1,0,1}, {1,0,0,0,0,1,0,1}, {0,1,0,0,0,1,0,1}, {1,1,0,0,0,1,0,1},
	{0,0,1,0,0,1,0,1}, {1,0,1,0,0,1,0,1}, {0,1,1,0,0,1,0,1}, {1,1,1,0,0,1,0,1},
	{0,0,0,1,0,1,0,1}, {1,0,0,1,0,1,0,1}, {0,1,0,1,0,1,0,1}, {1,1,0,1,0,1,0,1},
	{0,0,1,1,0,1,0,1}, {1,0,1,1,0,1,0,1}, {0,1,1,1,0,1,0,1}, {1,1,1,1,0,1,0,1},
	{0,0,0,0,1,1,0,1}, {1,0,0,0,1,1,0,1}, {0,1,0,0,1,1,0,1}, {1,1,0,0,1,1,0,1},
	{0,0,1,0,1,1,0,1}, {1,0,1,0,1,1,0,1}, {0,1,1,0,1,1,0,1}, {1,1,1,0,1,1,0,1},
	{0,0,0,1,1,1,0,1}, {1,0,0,1,1,1,0,1}, {0,1,0,1,1,1,0,1}, {1,1,0,1,1,1,0,1},
	{0,0,1,1,1,1,0,1}, {1,0,1,1,1,1,0,1}, {0,1,1,1,1,1,0,1}, {1,1,1,1,1,1,0,1},
	{0,0,0,0,0,0,1,1}, {1,0,0,0,0,0,1,1}, {0,1,0,0,0,0,1,1}, {1,1,0,0,0,0,1,1},
	{0,0,1,0,0,0,1,1}, {1,0,1,0,0,0,1,1}, {0,1,1,0,0,0,1,1}, {1,1,1,0,0,0,1,1},
	{0,0,0,1,0,0,1,1}, {1,0,0,1,0,0,1,1}, {0,1,0,1,0,0,1,1}, {1,1,0,1,0,0,1,1},
	{0,0,1,1,0,0,1,1}, {1,0,1,1,0,0,1,1}, {0,1,1,1,0,0,1,1}, {1,1,1,1,0,0,1,1},
	{0,0,0,0,1,0,1,1}, {1,0,0,0,1,0,1,1}, {0,1,0,0,1,0,1,1}, {1,1,0,0,1,0,1,1},
	{0,0,1,0,1,0,1,1}, {1,0,1,0,1,0,1,1}, {0,1,1,0,1,0,1,1}, {1,1,1,0,1,0,1,1},
	{0,0,0,1,1,0,1,1}, {1,0,0,1,1,0,1,1}, {0,1,0,1,1,0,1,1}, {1,1,0,1,1,0,1,1},
	{0,0,1,1,1,0,1,1}, {1,0,1,1,1,0,1,1}, {0,1,1,1,1,0,1,1}, {1,1,1,1,1,0,1,1},
	{0,0,0,0,0,1,1,1}, {1,0,0,0,0,1,1,1}, {0,1,0,0,0,1,1,1}, {1,1,0,0,0,1,1,1},
	{0,0,1,0,0,1,1,1}, {1,0,1,0,0,1,1,1}, {0,1,1,0,0,1,1,1}, {1,1,1,0,0,1,1,1},
	{0,0,0,1,0,1,1,1}, {1,0,0,1,0,1,1,1}, {0,1,0,1,0,1,1,1}, {1,1,0,1,0,1,1,1},
	{0,0,1,1,0,1,1,1}, {1,0,1,1,0,1,1,1}, {0,1,1,1,0,1,1,1}, {1,1,1,1,0,1,1,1},
	{0,0,0,0,1,1,1,1}, {1,0,0,0,1,1,1,1}, {0,1,0,0,1,1,1,1}, {1,1,0,0,1,1,1,1},
	{0,0,1,0,1,1,1,1}, {1,0,1,0,1,1,1,1}, {0,1,1,0,1,1,1,1}, {1,1,1,0,1,1,1,1},
	{0,0,0,1,1,1,1,1}, {1,0,0,1,1,1,1,1}, {0,1,0,1,1,1,1,1}, {1,1,0,1,1,1,1,1},
	{0,0,1,1,1,1,1,1}, {1,0,1,1,1,1,1,1}, {0,1,1,1,1,1,1,1}, {1,1,1,1,1,1,1,1}}

	-- Return a number that is the result of interpreting the table tbl (msb first)
	local function tbl_to_number(tbl)
		local n, rslt, power = #tbl, 0, 1
		for i = 1, n do
			rslt = rslt + tbl[i]*power
			power = power*2
		end
		return rslt
	end

	-- Calculate bitwise xor of bytes m and n. 0 <= m,n <= 256.
	local function bit_xor(m, n)
		local tbl_m = cclxvi[m]
		local tbl_n = cclxvi[n]
		local tbl = {}
		for i = 1, 8 do
			if(tbl_m[i] ~= tbl_n[i]) then
				tbl[i] = 1
			else
				tbl[i] = 0
			end
		end
		return tbl_to_number(tbl)
	end

	local fill_matrix_position = function(matrix,bitstring,x,y) matrix[x][y] = (bitstring == "1") and 2 or -2 end

	-- Return the mode for the given string `str`.
	-- See table 2 of the spec. We only support mode 1, 2 and 4.
	-- That is: numeric, alaphnumeric and binary.
	local function get_mode( str )
		local mode
		if type(str)==type("str")and str~='' then
			if string.match(str,"^[0-9]+$") then
				return 1
			elseif string.match(str,"^[0-9A-Z $%%*./:+-]+$") then
				return 2
			else
				return 4
			end
		elseif type(str)==type(nil)or str=='' then return 4
		elseif type(str)==type(0) then return 1
		else return 4
		end
		assert(false,"never reached")
		return nil
	end


	-- The capacity (number of codewords) of each version (1-40) for error correction levels 1-4 (LMQH).
	-- The higher the ec level, the lower the capacity of the version. Taken from spec, tables 7-11.
	local capacity = {
	  {  19,   16,   13,	9},{  34,   28,   22,   16},{  55,   44,   34,   26},{  80,   64,   48,   36},
	  { 108,   86,   62,   46},{ 136,  108,   76,   60},{ 156,  124,   88,   66},{ 194,  154,  110,   86},
	  { 232,  182,  132,  100},{ 274,  216,  154,  122},{ 324,  254,  180,  140},{ 370,  290,  206,  158},
	  { 428,  334,  244,  180},{ 461,  365,  261,  197},{ 523,  415,  295,  223},{ 589,  453,  325,  253},
	  { 647,  507,  367,  283},{ 721,  563,  397,  313},{ 795,  627,  445,  341},{ 861,  669,  485,  385},
	  { 932,  714,  512,  406},{1006,  782,  568,  442},{1094,  860,  614,  464},{1174,  914,  664,  514},
	  {1276, 1000,  718,  538},{1370, 1062,  754,  596},{1468, 1128,  808,  628},{1531, 1193,  871,  661},
	  {1631, 1267,  911,  701},{1735, 1373,  985,  745},{1843, 1455, 1033,  793},{1955, 1541, 1115,  845},
	  {2071, 1631, 1171,  901},{2191, 1725, 1231,  961},{2306, 1812, 1286,  986},{2434, 1914, 1354, 1054},
	  {2566, 1992, 1426, 1096},{2702, 2102, 1502, 1142},{2812, 2216, 1582, 1222},{2956, 2334, 1666, 1276}}
	  
	-- mode = 1,2,4,8
	local function get_version_eclevel(len,mode,requested_ec_level)
		local local_mode = mode
		if mode == 4 then
			local_mode = 3
		elseif mode == 8 then
			local_mode = 4
		end
		assert( local_mode <= 4 )

		local bytes, bits, digits, modebits, c
		local tab = { {10,9,8,8},{12,11,16,10},{14,13,16,12} }
		local minversion = 40
		local maxec_level = requested_ec_level or 1
		local min,max = 1, 4
		if requested_ec_level and requested_ec_level >= 1 and requested_ec_level <= 4 then
			min = requested_ec_level
			max = requested_ec_level
		end
		for ec_level=min,max do
			for version=1,#capacity do
				bits = capacity[version][ec_level] * 8
				bits = bits - 4 -- the mode indicator
				if version < 10 then
					digits = tab[1][local_mode]
				elseif version < 27 then
					digits = tab[2][local_mode]
				elseif version <= 40 then
					digits = tab[3][local_mode]
				end
				modebits = bits - digits
				if local_mode == 1 then -- numeric
					c = math.floor(modebits * 3 / 10)
				elseif local_mode == 2 then -- alphanumeric
					c = math.floor(modebits * 2 / 11)
				elseif local_mode == 3 then -- binary
					c = math.floor(modebits * 1 / 8)
				else
					c = math.floor(modebits * 1 / 13)
				end
				if c >= len then
					if version <= minversion then
						minversion = version
						maxec_level = ec_level
					end
					break
				end
			end
		end
		return minversion, maxec_level
	end

	-- Return a bit string of 0s and 1s that includes the length of the code string.
	-- The modes are numeric = 1, alphanumeric = 2, binary = 4, and japanese = 8
	local function get_length(str,version,mode)
		local i = mode
		if mode == 4 then
			i = 3
		elseif mode == 8 then
			i = 4
		end
		assert( i <= 4 )
		local tab = { {10,9,8,8},{12,11,16,10},{14,13,16,12} }
		local digits
		if version < 10 then
			digits = tab[1][i]
		elseif version < 27 then
			digits = tab[2][i]
		elseif version <= 40 then
			digits = tab[3][i]
		else
			assert(false, "get_length, version > 40 not supported")
		end
		local len = p._toBinary(p._get_string_length(str),digits)
		return len
	end

	local function get_version_eclevel_mode_bistringlength(str,requested_ec_level,mode)
		local local_mode
		if mode then
			assert(false,"not implemented")
			-- check if the mode is OK for the string
			local_mode = mode
		else
			local_mode = get_mode(str)
		end
		local version, ec_level
		version, ec_level = get_version_eclevel(p._get_string_length(str),local_mode,requested_ec_level)
		local length_string = get_length(str,version,local_mode)
		return version,ec_level,p._toBinary((type(str)==type(nil))and 0 or local_mode,4),local_mode,length_string
	end

	local asciitbl = {
			-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  -- 0x01-0x0f
		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  -- 0x10-0x1f
		36, -1, -1, -1, 37, 38, -1, -1, -1, -1, 39, 40, -1, 41, 42, 43,  -- 0x20-0x2f
		 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 44, -1, -1, -1, -1, -1,  -- 0x30-0x3f
		-1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,  -- 0x40-0x4f
		25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1,  -- 0x50-0x5f
	  }

	-- Return a binary representation of the numeric string `str`. This must contain only digits 0-9.
	local function encode_string_numeric(str)
		local bitstring = ""
		local int
		string.gsub(str,"..?.?",function(a)
			int = tonumber(a)
			if #a == 3 then
				bitstring = bitstring .. p._toBinary(int,10)
			elseif #a == 2 then
				bitstring = bitstring .. p._toBinary(int,7)
			else
				bitstring = bitstring .. p._toBinary(int,4)
			end
		end)
		return bitstring
	end

	-- Return a binary representation of the alphanumeric string `str`. This must contain only
	-- digits 0-9, uppercase letters A-Z, space and the following chars: $%*./:+-.
	local function encode_string_ascii(str)
		local bitstring = ""
		local int
		local b1, b2
		string.gsub(str,"..?",function(a)
			if #a == 2 then
				b1 = asciitbl[string.byte(string.sub(a,1,1))]
				b2 = asciitbl[string.byte(string.sub(a,2,2))]
				int = b1 * 45 + b2
				bitstring = bitstring .. p._toBinary(int,11)
			else
				int = asciitbl[string.byte(a)]
				bitstring = bitstring .. p._toBinary(int,6)
			end
		  end)
		return bitstring
	end

	-- Return a bitstring representing string str in binary mode.
	-- We don't handle UTF-8 in any special way because we assume the
	-- scanner recognizes UTF-8 and displays it correctly.
	local function encode_string_binary(str)
		local ret = {}
		if type(str)==type("str")and str~='' then
			string.gsub(str,".",function(x)
				ret[#ret + 1] = p._toBinary(string.byte(x),8)
			end)
		elseif type(str)==type(nil)or str==''then
			return ''
		else
			for it=1,#str do
				assert((type(str[it])==type('0'))or(type(str[it])==type(0)),"data not support")
				local bytedata = tonumber(str[it])or 0
				assert(bytedata<=255 and bytedata>=0,"data overflow")
				bytedata=bytedata%255
				ret[#ret + 1] = p._toBinary(bytedata,8)
			end
		end
		return table.concat(ret)
	end

	-- Return a bitstring representing string str in the given mode.
	local function encode_data(str,mode)
		if mode == 1 then
			return encode_string_numeric(str)
		elseif mode == 2 then
			return encode_string_ascii(str)
		elseif mode == 4 then
			return encode_string_binary(str)
		else
			assert(false,"not implemented yet")
		end
	end

	-- Encoding the codeword is not enough. We need to make sure that
	-- the length of the binary string is equal to the number of codewords of the version.
	local function add_pad_data(version,ec_level,data)
		local count_to_pad, missing_digits
		local cpty = capacity[version][ec_level] * 8
		count_to_pad = math.min(4,cpty - #data)
		if count_to_pad > 0 then
			data = data .. string.rep("0",count_to_pad)
		end
		if math.fmod(#data,8) ~= 0 then
			missing_digits = 8 - math.fmod(#data,8)
			data = data .. string.rep("0",missing_digits)
		end
		assert(math.fmod(#data,8) == 0)
		-- add "11101100" and "00010001" until enough data
		while #data < cpty do
			data = data .. "11101100"
			if #data < cpty then
				data = data .. "00010001"
			end
		end
		return data
	end

	-- https://codyplanteen.com/assets/rs/gf256_log_antilog.pdf
	local alpha_int = {
		[0] = 1,
		  2,   4,   8,  16,  32,  64, 128,  29,  58, 116, 232, 205, 135,  19,  38,  76,
		152,  45,  90, 180, 117, 234, 201, 143,   3,   6,  12,  24,  48,  96, 192, 157,
		 39,  78, 156,  37,  74, 148,  53, 106, 212, 181, 119, 238, 193, 159,  35,  70,
		140,   5,  10,  20,  40,  80, 160,  93, 186, 105, 210, 185, 111, 222, 161,  95,
		190,  97, 194, 153,  47,  94, 188, 101, 202, 137,  15,  30,  60, 120, 240, 253,
		231, 211, 187, 107, 214, 177, 127, 254, 225, 223, 163,  91, 182, 113, 226, 217,
		175,  67, 134,  17,  34,  68, 136,  13,  26,  52, 104, 208, 189, 103, 206, 129,
		 31,  62, 124, 248, 237, 199, 147,  59, 118, 236, 197, 151,  51, 102, 204, 133,
		 23,  46,  92, 184, 109, 218, 169,  79, 158,  33,  66, 132,  21,  42,  84, 168,
		 77, 154,  41,  82, 164,  85, 170,  73, 146,  57, 114, 228, 213, 183, 115, 230,
		209, 191,  99, 198, 145,  63, 126, 252, 229, 215, 179, 123, 246, 241, 255, 227,
		219, 171,  75, 150,  49,  98, 196, 149,  55, 110, 220, 165,  87, 174,  65, 130,
		 25,  50, 100, 200, 141,   7,  14,  28,  56, 112, 224, 221, 167,  83, 166,  81,
		162,  89, 178, 121, 242, 249, 239, 195, 155,  43,  86, 172,  69, 138,   9,  18,
		 36,  72, 144,  61, 122, 244, 245, 247, 243, 251, 235, 203, 139,  11,  22,  44,
		 88, 176, 125, 250, 233, 207, 131,  27,  54, 108, 216, 173,  71, 142,   0,   0
	}

	local int_alpha = {
		[0] = 256, -- special value
		0,   1,  25,   2,  50,  26, 198,   3, 223,  51, 238,  27, 104, 199,  75,   4,
		100, 224,  14,  52, 141, 239, 129,  28, 193, 105, 248, 200,   8,  76, 113,   5,
		138, 101,  47, 225,  36,  15,  33,  53, 147, 142, 218, 240,  18, 130,  69,  29,
		181, 194, 125, 106,  39, 249, 185, 201, 154,   9, 120,  77, 228, 114, 166,   6,
		191, 139,  98, 102, 221,  48, 253, 226, 152,  37, 179,  16, 145,  34, 136,  54,
		208, 148, 206, 143, 150, 219, 189, 241, 210,  19,  92, 131,  56,  70,  64,  30,
		 66, 182, 163, 195,  72, 126, 110, 107,  58,  40,  84, 250, 133, 186,  61, 202,
		 94, 155, 159,  10,  21, 121,  43,  78, 212, 229, 172, 115, 243, 167,  87,   7,
		112, 192, 247, 140, 128,  99,  13, 103,  74, 222, 237,  49, 197, 254,  24, 227,
		165, 153, 119,  38, 184, 180, 124,  17,  68, 146, 217,  35,  32, 137,  46,  55,
		 63, 209,  91, 149, 188, 207, 205, 144, 135, 151, 178, 220, 252, 190,  97, 242,
		 86, 211, 171,  20,  42,  93, 158, 132,  60,  57,  83,  71, 109,  65, 162,  31,
		 45,  67, 216, 183, 123, 164, 118, 196,  23,  73, 236, 127,  12, 111, 246, 108,
		161,  59,  82,  41, 157,  85, 170, 251,  96, 134, 177, 187, 204,  62,  90, 203,
		 89,  95, 176, 156, 169, 160,  81,  11, 245,  22, 235, 122, 117,  44, 215,  79,
		174, 213, 233, 230, 231, 173, 232, 116, 214, 244, 234, 168,  80,  88, 175
	}

	-- We only need the polynomial generators for block sizes 7, 10, 13, 15, 16, 17, 18, 20, 22, 24, 26, 28, and 30. Version
	-- 2 of the qr codes don't need larger ones (as opposed to version 1). The table has the format x^1*ɑ^21 + x^2*a^102 ...
	local generator_polynomial = {
		 [7] = { 21, 102, 238, 149, 146, 229,  87,   0},
		[10] = { 45,  32,  94,  64,  70, 118,  61,  46,  67, 251,   0 },
		[13] = { 78, 140, 206, 218, 130, 104, 106, 100,  86, 100, 176, 152,  74,   0 },
		[15] = {105,  99,   5, 124, 140, 237,  58,  58,  51,  37, 202,  91,  61, 183,   8,   0},
		[16] = {120, 225, 194, 182, 169, 147, 191,  91,   3,  76, 161, 102, 109, 107, 104, 120,   0},
		[17] = {136, 163, 243,  39, 150,  99,  24, 147, 214, 206, 123, 239,  43,  78, 206, 139,  43,   0},
		[18] = {153,  96,  98,   5, 179, 252, 148, 152, 187,  79, 170, 118,  97, 184,  94, 158, 234, 215,   0},
		[20] = {190, 188, 212, 212, 164, 156, 239,  83, 225, 221, 180, 202, 187,  26, 163,  61,  50,  79,  60,  17,   0},
		[22] = {231, 165, 105, 160, 134, 219,  80,  98, 172,   8,  74, 200,  53, 221, 109,  14, 230,  93, 242, 247, 171, 210,   0},
		[24] = { 21, 227,  96,  87, 232, 117,   0, 111, 218, 228, 226, 192, 152, 169, 180, 159, 126, 251, 117, 211,  48, 135, 121, 229,   0},
		[26] = { 70, 218, 145, 153, 227,  48, 102,  13, 142, 245,  21, 161,  53, 165,  28, 111, 201, 145,  17, 118, 182, 103,   2, 158, 125, 173,   0},
		[28] = {123,   9,  37, 242, 119, 212, 195,  42,  87, 245,  43,  21, 201, 232,  27, 205, 147, 195, 190, 110, 180, 108, 234, 224, 104, 200, 223, 168,   0},
		[30] = {180, 192,  40, 238, 216, 251,  37, 156, 130, 224, 193, 226, 173,  42, 125, 222,  96, 239,  86, 110,  48,  50, 182, 179,  31, 216, 152, 145, 173, 41, 0}}


	-- Turn a binary string of length 8*x into a table size x of numbers.
	local function convert_bitstring_to_bytes(data)
		local msg = {}
		local tab = string.gsub(data,"(........)",function(x)
			msg[#msg+1] = tonumber(x,2)
			end)
		return msg
	end

	-- Return a table that has 0's in the first entries and then the alpha
	-- representation of the generator polynominal
	local function get_generator_polynominal_adjusted(num_ec_codewords,highest_exponent)
		local gp_alpha = {[0]=0}
		for i=0,highest_exponent - num_ec_codewords - 1 do
			gp_alpha[i] = 0
		end
		local gp = generator_polynomial[num_ec_codewords]
		for i=1,num_ec_codewords + 1 do
			gp_alpha[highest_exponent - num_ec_codewords + i - 1] = gp[i]
		end
		return gp_alpha
	end

	-- Convert polynominal in int notation to alpha notation.
	local function convert_to_alpha( tab )
		local new_tab = {}
		for i=0,#tab do
			new_tab[i] = int_alpha[tab[i]]
		end
		return new_tab
	end

	-- Convert polynominal in alpha notation to int notation.
	local function convert_to_int(tab,len_message)
		local new_tab = {}
		for i=0,#tab do
			new_tab[i] = alpha_int[tab[i]]
		end
		return new_tab
	end

	-- That's the heart of the error correction calculation.
	local function calculate_error_correction(data,num_ec_codewords)
		local mp
		if type(data)=="string" then
			mp = convert_bitstring_to_bytes(data)
		elseif type(data)=="table" then
			mp = data
		else
			assert(false,"Unknown type for data: %s",type(data))
		end
		local len_message = #mp

		local highest_exponent = len_message + num_ec_codewords - 1
		local gp_alpha,tmp
		local he
		local gp_int = {}
		local mp_int,mp_alpha = {},{}
		-- create message shifted to left (highest exponent)
		for i=1,len_message do
			mp_int[highest_exponent - i + 1] = mp[i]
		end
		for i=1,highest_exponent - len_message do
			mp_int[i] = 0
		end
		mp_int[0] = 0

		mp_alpha = convert_to_alpha(mp_int)

		while highest_exponent >= num_ec_codewords do
			gp_alpha = get_generator_polynominal_adjusted(num_ec_codewords,highest_exponent)

			-- Multiply generator polynomial by first coefficient of the above polynomial

			-- take the highest exponent from the message polynom (alpha) and add
			-- it to the generator polynom
			local exp = mp_alpha[highest_exponent]
			for i=highest_exponent,highest_exponent - num_ec_codewords,-1 do
				if exp ~= 256 then
					if gp_alpha[i] + exp >= 255 then
						gp_alpha[i] = math.fmod(gp_alpha[i] + exp,255)
					else
						gp_alpha[i] = gp_alpha[i] + exp
					end
				else
					gp_alpha[i] = 256
				end
			end
			for i=highest_exponent - num_ec_codewords - 1,0,-1 do
				gp_alpha[i] = 256
			end

			gp_int = convert_to_int(gp_alpha)
			mp_int = convert_to_int(mp_alpha)

			tmp = {}
			for i=highest_exponent,0,-1 do
				tmp[i] = bit_xor(gp_int[i],mp_int[i])
			end
			-- remove leading 0's
			he = highest_exponent
			for i=he,0,-1 do
				-- We need to stop if the length of the codeword is matched
				if i < num_ec_codewords then break end
				if tmp[i] == 0 then
					tmp[i] = nil
					highest_exponent = highest_exponent - 1
				else
					break
				end
			end
			mp_int = tmp
			mp_alpha = convert_to_alpha(mp_int)
		end
		local ret = {}

		-- reverse data
		for i=#mp_int,0,-1 do
			ret[#ret + 1] = mp_int[i]
		end
		return ret
	end

	local ecblocks = {
	  {{  1,{ 26, 19, 2}                 },   {  1,{26,16, 4}},                  {  1,{26,13, 6}},                  {  1, {26, 9, 8}               }},
	  {{  1,{ 44, 34, 4}                 },   {  1,{44,28, 8}},                  {  1,{44,22,11}},                  {  1, {44,16,14}               }},
	  {{  1,{ 70, 55, 7}                 },   {  1,{70,44,13}},                  {  2,{35,17, 9}},                  {  2, {35,13,11}               }},
	  {{  1,{100, 80,10}                 },   {  2,{50,32, 9}},                  {  2,{50,24,13}},                  {  4, {25, 9, 8}               }},
	  {{  1,{134,108,13}                 },   {  2,{67,43,12}},                  {  2,{33,15, 9},  2,{34,16, 9}},   {  2, {33,11,11},  2,{34,12,11}}},
	  {{  2,{ 86, 68, 9}                 },   {  4,{43,27, 8}},                  {  4,{43,19,12}},                  {  4, {43,15,14}               }},
	  {{  2,{ 98, 78,10}                 },   {  4,{49,31, 9}},                  {  2,{32,14, 9},  4,{33,15, 9}},   {  4, {39,13,13},  1,{40,14,13}}},
	  {{  2,{121, 97,12}                 },   {  2,{60,38,11},  2,{61,39,11}},   {  4,{40,18,11},  2,{41,19,11}},   {  4, {40,14,13},  2,{41,15,13}}},
	  {{  2,{146,116,15}                 },   {  3,{58,36,11},  2,{59,37,11}},   {  4,{36,16,10},  4,{37,17,10}},   {  4, {36,12,12},  4,{37,13,12}}},
	  {{  2,{ 86, 68, 9},  2,{ 87, 69, 9}},   {  4,{69,43,13},  1,{70,44,13}},   {  6,{43,19,12},  2,{44,20,12}},   {  6, {43,15,14},  2,{44,16,14}}},
	  {{  4,{101, 81,10}                 },   {  1,{80,50,15},  4,{81,51,15}},   {  4,{50,22,14},  4,{51,23,14}},   {  3, {36,12,12},  8,{37,13,12}}},
	  {{  2,{116, 92,12},  2,{117, 93,12}},   {  6,{58,36,11},  2,{59,37,11}},   {  4,{46,20,13},  6,{47,21,13}},   {  7, {42,14,14},  4,{43,15,14}}},
	  {{  4,{133,107,13}                 },   {  8,{59,37,11},  1,{60,38,11}},   {  8,{44,20,12},  4,{45,21,12}},   { 12, {33,11,11},  4,{34,12,11}}},
	  {{  3,{145,115,15},  1,{146,116,15}},   {  4,{64,40,12},  5,{65,41,12}},   { 11,{36,16,10},  5,{37,17,10}},   { 11, {36,12,12},  5,{37,13,12}}},
	  {{  5,{109, 87,11},  1,{110, 88,11}},   {  5,{65,41,12},  5,{66,42,12}},   {  5,{54,24,15},  7,{55,25,15}},   { 11, {36,12,12},  7,{37,13,12}}},
	  {{  5,{122, 98,12},  1,{123, 99,12}},   {  7,{73,45,14},  3,{74,46,14}},   { 15,{43,19,12},  2,{44,20,12}},   {  3, {45,15,15}, 13,{46,16,15}}},
	  {{  1,{135,107,14},  5,{136,108,14}},   { 10,{74,46,14},  1,{75,47,14}},   {  1,{50,22,14}, 15,{51,23,14}},   {  2, {42,14,14}, 17,{43,15,14}}},
	  {{  5,{150,120,15},  1,{151,121,15}},   {  9,{69,43,13},  4,{70,44,13}},   { 17,{50,22,14},  1,{51,23,14}},   {  2, {42,14,14}, 19,{43,15,14}}},
	  {{  3,{141,113,14},  4,{142,114,14}},   {  3,{70,44,13}, 11,{71,45,13}},   { 17,{47,21,13},  4,{48,22,13}},   {  9, {39,13,13}, 16,{40,14,13}}},
	  {{  3,{135,107,14},  5,{136,108,14}},   {  3,{67,41,13}, 13,{68,42,13}},   { 15,{54,24,15},  5,{55,25,15}},   { 15, {43,15,14}, 10,{44,16,14}}},
	  {{  4,{144,116,14},  4,{145,117,14}},   { 17,{68,42,13}},                  { 17,{50,22,14},  6,{51,23,14}},   { 19, {46,16,15},  6,{47,17,15}}},
	  {{  2,{139,111,14},  7,{140,112,14}},   { 17,{74,46,14}},                  {  7,{54,24,15}, 16,{55,25,15}},   { 34, {37,13,12}               }},
	  {{  4,{151,121,15},  5,{152,122,15}},   {  4,{75,47,14}, 14,{76,48,14}},   { 11,{54,24,15}, 14,{55,25,15}},   { 16, {45,15,15}, 14,{46,16,15}}},
	  {{  6,{147,117,15},  4,{148,118,15}},   {  6,{73,45,14}, 14,{74,46,14}},   { 11,{54,24,15}, 16,{55,25,15}},   { 30, {46,16,15},  2,{47,17,15}}},
	  {{  8,{132,106,13},  4,{133,107,13}},   {  8,{75,47,14}, 13,{76,48,14}},   {  7,{54,24,15}, 22,{55,25,15}},   { 22, {45,15,15}, 13,{46,16,15}}},
	  {{ 10,{142,114,14},  2,{143,115,14}},   { 19,{74,46,14},  4,{75,47,14}},   { 28,{50,22,14},  6,{51,23,14}},   { 33, {46,16,15},  4,{47,17,15}}},
	  {{  8,{152,122,15},  4,{153,123,15}},   { 22,{73,45,14},  3,{74,46,14}},   {  8,{53,23,15}, 26,{54,24,15}},   { 12, {45,15,15}, 28,{46,16,15}}},
	  {{  3,{147,117,15}, 10,{148,118,15}},   {  3,{73,45,14}, 23,{74,46,14}},   {  4,{54,24,15}, 31,{55,25,15}},   { 11, {45,15,15}, 31,{46,16,15}}},
	  {{  7,{146,116,15},  7,{147,117,15}},   { 21,{73,45,14},  7,{74,46,14}},   {  1,{53,23,15}, 37,{54,24,15}},   { 19, {45,15,15}, 26,{46,16,15}}},
	  {{  5,{145,115,15}, 10,{146,116,15}},   { 19,{75,47,14}, 10,{76,48,14}},   { 15,{54,24,15}, 25,{55,25,15}},   { 23, {45,15,15}, 25,{46,16,15}}},
	  {{ 13,{145,115,15},  3,{146,116,15}},   {  2,{74,46,14}, 29,{75,47,14}},   { 42,{54,24,15},  1,{55,25,15}},   { 23, {45,15,15}, 28,{46,16,15}}},
	  {{ 17,{145,115,15}            	 },   { 10,{74,46,14}, 23,{75,47,14}},   { 10,{54,24,15}, 35,{55,25,15}},   { 19, {45,15,15}, 35,{46,16,15}}},
	  {{ 17,{145,115,15},  1,{146,116,15}},   { 14,{74,46,14}, 21,{75,47,14}},   { 29,{54,24,15}, 19,{55,25,15}},   { 11, {45,15,15}, 46,{46,16,15}}},
	  {{ 13,{145,115,15},  6,{146,116,15}},   { 14,{74,46,14}, 23,{75,47,14}},   { 44,{54,24,15},  7,{55,25,15}},   { 59, {46,16,15},  1,{47,17,15}}},
	  {{ 12,{151,121,15},  7,{152,122,15}},   { 12,{75,47,14}, 26,{76,48,14}},   { 39,{54,24,15}, 14,{55,25,15}},   { 22, {45,15,15}, 41,{46,16,15}}},
	  {{  6,{151,121,15}, 14,{152,122,15}},   {  6,{75,47,14}, 34,{76,48,14}},   { 46,{54,24,15}, 10,{55,25,15}},   {  2, {45,15,15}, 64,{46,16,15}}},
	  {{ 17,{152,122,15},  4,{153,123,15}},   { 29,{74,46,14}, 14,{75,47,14}},   { 49,{54,24,15}, 10,{55,25,15}},   { 24, {45,15,15}, 46,{46,16,15}}},
	  {{  4,{152,122,15}, 18,{153,123,15}},   { 13,{74,46,14}, 32,{75,47,14}},   { 48,{54,24,15}, 14,{55,25,15}},   { 42, {45,15,15}, 32,{46,16,15}}},
	  {{ 20,{147,117,15},  4,{148,118,15}},   { 40,{75,47,14},  7,{76,48,14}},   { 43,{54,24,15}, 22,{55,25,15}},   { 10, {45,15,15}, 67,{46,16,15}}},
	  {{ 19,{148,118,15},  6,{149,119,15}},   { 18,{75,47,14}, 31,{76,48,14}},   { 34,{54,24,15}, 34,{55,25,15}},   { 20, {45,15,15}, 61,{46,16,15}}}
	}

	-- The bits that must be 0 if the version does fill the complete matrix.
	-- Example: for version 1, no bits need to be added after arranging the data, for version 2 we need to add 7 bits at the end.
	local remainder = {0, 7, 7, 7, 7, 7, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0}

	-- This is the formula for table 1 in the spec:
	-- function get_capacity_remainder( version )
	-- 	local len = version * 4 + 17
	-- 	local size = len^2
	-- 	local function_pattern_modules = 192 + 2 * len - 32 -- Position Adjustment pattern + timing pattern
	-- 	local count_alignemnt_pattern = #alignment_pattern[version]
	-- 	if count_alignemnt_pattern > 0 then
	-- 		-- add 25 for each aligment pattern
	-- 		function_pattern_modules = function_pattern_modules + 25 * ( count_alignemnt_pattern^2 - 3 )
	-- 		-- but substract the timing pattern occupied by the aligment pattern on the top and left
	-- 		function_pattern_modules = function_pattern_modules - ( count_alignemnt_pattern - 2) * 10
	-- 	end
	-- 	size = size - function_pattern_modules
	-- 	if version > 6 then
	-- 		size = size - 67
	-- 	else
	-- 		size = size - 31
	-- 	end
	-- 	return math.floor(size/8),math.fmod(size,8)
	-- end

	-- The given data can be a string of 0's and 1' (with #string mod 8 == 0).
	-- Alternatively the data can be a table of codewords. The number of codewords
	-- must match the capacity of the qr code.
	local function arrange_codewords_and_calculate_ec( version,ec_level,data )
		if type(data)=="table" then
			local tmp = ""
			for i=1,#data do
				tmp = tmp .. p._toBinary(data[i],8)
			end
			data = tmp
		end
		-- If the size of the data is not enough for the codeword, we add 0's and two special bytes until finished.
		local blocks = ecblocks[version][ec_level]
		local size_datablock_bytes, size_ecblock_bytes
		local datablocks = {}
		local ecblocks = {}
		local count = 1
		local pos = 0
		local cpty_ec_bits = 0
		for i=1,#blocks/2 do
			for j=1,blocks[2*i - 1] do
				size_datablock_bytes = blocks[2*i][2]
				size_ecblock_bytes   = blocks[2*i][1] - blocks[2*i][2]
				cpty_ec_bits = cpty_ec_bits + size_ecblock_bytes * 8
				datablocks[#datablocks + 1] = string.sub(data, pos * 8 + 1,( pos + size_datablock_bytes)*8)
				tmp_tab = calculate_error_correction(datablocks[#datablocks],size_ecblock_bytes)
				tmp_str = ""
				for x=1,#tmp_tab do
					tmp_str = tmp_str .. p._toBinary(tmp_tab[x],8)
				end
				ecblocks[#ecblocks + 1] = tmp_str
				pos = pos + size_datablock_bytes
				count = count + 1
			end
		end
		local arranged_data = ""
		pos = 1
		repeat
			for i=1,#datablocks do
				if pos < #datablocks[i] then
					arranged_data = arranged_data .. string.sub(datablocks[i],pos, pos + 7)
				end
			end
			pos = pos + 8
		until #arranged_data == #data
		-- ec
		local arranged_ec = ""
		pos = 1
		repeat
			for i=1,#ecblocks do
				if pos < #ecblocks[i] then
					arranged_ec = arranged_ec .. string.sub(ecblocks[i],pos, pos + 7)
				end
			end
			pos = pos + 8
		until #arranged_ec == cpty_ec_bits
		return arranged_data .. arranged_ec
	end

	local function add_position_detection_patterns(tab_x)
		local size = #tab_x
		-- allocate quite zone in the matrix area
		for i=1,8 do
			for j=1,8 do
				tab_x[i][j] = -2
				tab_x[size - 8 + i][j] = -2
				tab_x[i][size - 8 + j] = -2
			end
		end
		-- draw the detection pattern (outer)
		for i=1,7 do
			-- top left
			tab_x[1][i]=2
			tab_x[7][i]=2
			tab_x[i][1]=2
			tab_x[i][7]=2

			-- top right
			tab_x[size][i]=2
			tab_x[size - 6][i]=2
			tab_x[size - i + 1][1]=2
			tab_x[size - i + 1][7]=2

			-- bottom left
			tab_x[1][size - i + 1]=2
			tab_x[7][size - i + 1]=2
			tab_x[i][size - 6]=2
			tab_x[i][size]=2
		end
		-- draw the detection pattern (inner)
		for i=1,3 do
			for j=1,3 do
				-- top left
				tab_x[2+j][i+2]=2
				-- top right
				tab_x[size - j - 1][i+2]=2
				-- bottom left
				tab_x[2 + j][size - i - 1]=2
			end
		end
	end

	-- The timing patterns (two) are the dashed lines between two adjacent positioning patterns on row/column 7.
	local function add_timing_pattern(tab_x)
		local line,col
		line = 7
		col = 9
		for i=col,#tab_x - 8 do
			if math.fmod(i,2) == 1 then
				tab_x[i][line] = 2
			else
				tab_x[i][line] = -2
			end
		end
		for i=col,#tab_x - 8 do
			if math.fmod(i,2) == 1 then
				tab_x[line][i] = 2
			else
				tab_x[line][i] = -2
			end
		end
	end

	-- For each version, where should we place the alignment patterns? See table E.1 of the spec
	local alignment_pattern = {
	  {},{6,18},{6,22},{6,26},{6,30},{6,34}, -- 1-6
	  {6,22,38},{6,24,42},{6,26,46},{6,28,50},{6,30,54},{6,32,58},{6,34,62}, -- 7-13
	  {6,26,46,66},{6,26,48,70},{6,26,50,74},{6,30,54,78},{6,30,56,82},{6,30,58,86},{6,34,62,90}, -- 14-20
	  {6,28,50,72,94},{6,26,50,74,98},{6,30,54,78,102},{6,28,54,80,106},{6,32,58,84,110},{6,30,58,86,114},{6,34,62,90,118}, -- 21-27
	  {6,26,50,74,98 ,122},{6,30,54,78,102,126},{6,26,52,78,104,130},{6,30,56,82,108,134},{6,34,60,86,112,138},{6,30,58,86,114,142},{6,34,62,90,118,146}, -- 28-34
	  {6,30,54,78,102,126,150}, {6,24,50,76,102,128,154},{6,28,54,80,106,132,158},{6,32,58,84,110,136,162},{6,26,54,82,110,138,166},{6,30,58,86,114,142,170} -- 35 - 40
	}

	local function add_alignment_pattern( tab_x )
		local version = (#tab_x - 17) / 4
		local ap = alignment_pattern[version]
		local pos_x, pos_y
		for x=1,#ap do
			for y=1,#ap do
				-- we must not put an alignment pattern on top of the positioning pattern
				if not (x == 1 and y == 1 or x == #ap and y == 1 or x == 1 and y == #ap ) then
					pos_x = ap[x] + 1
					pos_y = ap[y] + 1
					tab_x[pos_x][pos_y] = 2
					tab_x[pos_x+1][pos_y] = -2
					tab_x[pos_x-1][pos_y] = -2
					tab_x[pos_x+2][pos_y] =  2
					tab_x[pos_x-2][pos_y] =  2
					tab_x[pos_x  ][pos_y - 2] = 2
					tab_x[pos_x+1][pos_y - 2] = 2
					tab_x[pos_x-1][pos_y - 2] = 2
					tab_x[pos_x+2][pos_y - 2] = 2
					tab_x[pos_x-2][pos_y - 2] = 2
					tab_x[pos_x  ][pos_y + 2] = 2
					tab_x[pos_x+1][pos_y + 2] = 2
					tab_x[pos_x-1][pos_y + 2] = 2
					tab_x[pos_x+2][pos_y + 2] = 2
					tab_x[pos_x-2][pos_y + 2] = 2

					tab_x[pos_x  ][pos_y - 1] = -2
					tab_x[pos_x+1][pos_y - 1] = -2
					tab_x[pos_x-1][pos_y - 1] = -2
					tab_x[pos_x+2][pos_y - 1] =  2
					tab_x[pos_x-2][pos_y - 1] =  2
					tab_x[pos_x  ][pos_y + 1] = -2
					tab_x[pos_x+1][pos_y + 1] = -2
					tab_x[pos_x-1][pos_y + 1] = -2
					tab_x[pos_x+2][pos_y + 1] =  2
					tab_x[pos_x-2][pos_y + 1] =  2
				end
			end
		end
	end

	local typeinfo = {
		{ [-1]= "111111111111111", [0] = "111011111000100", "111001011110011", "111110110101010", "111100010011101", "110011000101111", "110001100011000", "110110001000001", "110100101110110" },
		{ [-1]= "111111111111111", [0] = "101010000010010", "101000100100101", "101111001111100", "101101101001011", "100010111111001", "100000011001110", "100111110010111", "100101010100000" },
		{ [-1]= "111111111111111", [0] = "011010101011111", "011000001101000", "011111100110001", "011101000000110", "010010010110100", "010000110000011", "010111011011010", "010101111101101" },
		{ [-1]= "111111111111111", [0] = "001011010001001", "001001110111110", "001110011100111", "001100111010000", "000011101100010", "000001001010101", "000110100001100", "000100000111011" }
	}

	local function add_typeinfo_to_matrix( matrix,ec_level,mask )
		local ec_mask_type = typeinfo[ec_level][mask]

		local bit
		-- vertical from bottom to top
		for i=1,7 do
			bit = string.sub(ec_mask_type,i,i)
			fill_matrix_position(matrix, bit, 9, #matrix - i + 1)
		end
		for i=8,9 do
			bit = string.sub(ec_mask_type,i,i)
			fill_matrix_position(matrix,bit,9,17-i)
		end
		for i=10,15 do
			bit = string.sub(ec_mask_type,i,i)
			fill_matrix_position(matrix,bit,9,16 - i)
		end
		-- horizontal, left to right
		for i=1,6 do
			bit = string.sub(ec_mask_type,i,i)
			fill_matrix_position(matrix,bit,i,9)
		end
		bit = string.sub(ec_mask_type,7,7)
		fill_matrix_position(matrix,bit,8,9)
		for i=8,15 do
			bit = string.sub(ec_mask_type,i,i)
			fill_matrix_position(matrix,bit,#matrix - 15 + i,9)
		end
	end

	-- Bits for version information 7-40
	-- The reversed strings from https://www.thonky.com/qr-code-tutorial/format-version-tables
	local version_information = {"001010010011111000", "001111011010000100", "100110010101100100", "110010110010010100",
	  "011011111101110100", "010001101110001100", "111000100001101100", "101100000110011100", "000101001001111100",
	  "000111101101000010", "101110100010100010", "111010000101010010", "010011001010110010", "011001011001001010",
	  "110000010110101010", "100100110001011010", "001101111110111010", "001000110111000110", "100001111000100110",
	  "110101011111010110", "011100010000110110", "010110000011001110", "111111001100101110", "101011101011011110",
	  "000010100100111110", "101010111001000001", "000011110110100001", "010111010001010001", "111110011110110001",
	  "110100001101001001", "011101000010101001", "001001100101011001", "100000101010111001", "100101100011000101" }

	-- Versions 7 and above need two bitfields with version information added to the code
	local function add_version_information(matrix,version)
		if version < 7 then return end
		local size = #matrix
		local bitstring = version_information[version - 6]
		local x,y, bit
		local start_x, start_y
		-- first top right
		start_x = #matrix - 10
		start_y = 1
		for i=1,#bitstring do
			bit = string.sub(bitstring,i,i)
			x = start_x + math.fmod(i - 1,3)
			y = start_y + math.floor( (i - 1) / 3 )
			fill_matrix_position(matrix,bit,x,y)
		end

		-- now bottom left
		start_x = 1
		start_y = #matrix - 10
		for i=1,#bitstring do
			bit = string.sub(bitstring,i,i)
			x = start_x + math.floor( (i - 1) / 3 )
			y = start_y + math.fmod(i - 1,3)
			fill_matrix_position(matrix,bit,x,y)
		end
	end

	local function prepare_matrix_with_mask( version,ec_level, mask )
		local size
		local tab_x = {}

		size = version * 4 + 17
		for i=1,size do
			tab_x[i]={}
			for j=1,size do
				tab_x[i][j] = 0
			end
		end
		add_position_detection_patterns(tab_x)
		add_timing_pattern(tab_x)
		add_version_information(tab_x,version)

		-- black pixel above lower left position detection pattern
		tab_x[9][size - 7] = 2
		add_alignment_pattern(tab_x)
		add_typeinfo_to_matrix(tab_x,ec_level, mask)
		return tab_x
	end

	-- Return 1 (black) or -1 (blank) depending on the mask, value and position.
	-- Parameter mask is 0-7 (-1 for 'no mask'). x and y are 1-based coordinates,
	-- 1,1 = upper left. tonumber(value) must be 0 or 1.
	local function get_pixel_with_mask( mask, x,y,value )
		x = x - 1
		y = y - 1
		local invert = false
		-- test purpose only:
		if mask == -1 then
			-- ignore, no masking applied
		elseif mask == 0 then
			if math.fmod(x + y,2) == 0 then invert = true end
		elseif mask == 1 then
			if math.fmod(y,2) == 0 then invert = true end
		elseif mask == 2 then
			if math.fmod(x,3) == 0 then invert = true end
		elseif mask == 3 then
			if math.fmod(x + y,3) == 0 then invert = true end
		elseif mask == 4 then
			if math.fmod(math.floor(y / 2) + math.floor(x / 3),2) == 0 then invert = true end
		elseif mask == 5 then
			if math.fmod(x * y,2) + math.fmod(x * y,3) == 0 then invert = true end
		elseif mask == 6 then
			if math.fmod(math.fmod(x * y,2) + math.fmod(x * y,3),2) == 0 then invert = true end
		elseif mask == 7 then
			if math.fmod(math.fmod(x * y,3) + math.fmod(x + y,2),2) == 0 then invert = true end
		else
			assert(false,"This can't happen (mask must be <= 7)")
		end
		if invert then
			-- value = 1? -> -1, value = 0? -> 1
			return 1 - 2 * tonumber(value)
		else
			-- value = 1? -> 1, value = 0? -> -1
			return -1 + 2*tonumber(value)
		end
	end

	-- We need up to 8 positions in the matrix. Only the last few bits may be less then 8.
	-- The function returns a table of (up to) 8 entries with subtables where
	-- the x coordinate is the first and the y coordinate is the second entry.
	local function get_next_free_positions(matrix,x,y,dir,byte)
		local ret = {}
		local count = 1
		local mode = "right"
		while count <= #byte do
			if mode == "right" and matrix[x][y] == 0 then
				ret[#ret + 1] = {x,y}
				mode = "left"
				count = count + 1
			elseif mode == "left" and matrix[x-1][y] == 0 then
				ret[#ret + 1] = {x-1,y}
				mode = "right"
				count = count + 1
				if dir == "up" then
					y = y - 1
				else
					y = y + 1
				end
			elseif mode == "right" and matrix[x-1][y] == 0 then
				ret[#ret + 1] = {x-1,y}
				count = count + 1
				if dir == "up" then
					y = y - 1
				else
					y = y + 1
				end
			else
				if dir == "up" then
					y = y - 1
				else
					y = y + 1
				end
			end
			if y < 1 or y > #matrix then
				x = x - 2
				-- don't overwrite the timing pattern
				if x == 7 then x = 6 end
				if dir == "up" then
					dir = "down"
					y = 1
				else
					dir = "up"
					y = #matrix
				end
			end
		end
		return ret,x,y,dir
	end

	-- Add the data string (0's and 1's) to the matrix for the given mask.
	local function add_data_to_matrix(matrix,data,mask)
		size = #matrix
		local x,y,positions
		local _x,_y,m
		local dir = "up"
		local byte_number = 0
		x,y = size,size
		string.gsub(data,".?.?.?.?.?.?.?.?",function ( byte )
			byte_number = byte_number + 1
			positions,x,y,dir = get_next_free_positions(matrix,x,y,dir,byte,mask)
			for i=1,#byte do
				_x = positions[i][1]
				_y = positions[i][2]
				m = get_pixel_with_mask(mask,_x,_y,string.sub(byte,i,i))
				if debugging then
					matrix[_x][_y] = m * (i + 10)
				else
					matrix[_x][_y] = m
				end
			end
		end)
	end

	-- Return the penalty for the given matrix
	local function calculate_penalty(matrix)
		local penalty1, penalty2, penalty3, penalty4 = 0,0,0,0
		local size = #matrix
		-- this is for penalty 4
		local number_of_dark_cells = 0

		-- 1: Adjacent modules in row/column in same color
		-- --------------------------------------------
		-- No. of modules = (5+i)  -> 3 + i
		local last_bit_blank -- < 0:  blank, > 0: black
		local is_blank
		local number_of_consecutive_bits
		-- first: vertical
		for x=1,size do
			number_of_consecutive_bits = 0
			last_bit_blank = nil
			for y = 1,size do
				if matrix[x][y] > 0 then
					-- small optimization: this is for penalty 4
					number_of_dark_cells = number_of_dark_cells + 1
					is_blank = false
				else
					is_blank = true
				end
				is_blank = matrix[x][y] < 0
				if last_bit_blank == is_blank then
					number_of_consecutive_bits = number_of_consecutive_bits + 1
				else
					if number_of_consecutive_bits >= 5 then
						penalty1 = penalty1 + number_of_consecutive_bits - 2
					end
					number_of_consecutive_bits = 1
				end
				last_bit_blank = is_blank
			end
			if number_of_consecutive_bits >= 5 then
				penalty1 = penalty1 + number_of_consecutive_bits - 2
			end
		end
		-- now horizontal
		for y=1,size do
			number_of_consecutive_bits = 0
			last_bit_blank = nil
			for x = 1,size do
				is_blank = matrix[x][y] < 0
				if last_bit_blank == is_blank then
					number_of_consecutive_bits = number_of_consecutive_bits + 1
				else
					if number_of_consecutive_bits >= 5 then
						penalty1 = penalty1 + number_of_consecutive_bits - 2
					end
					number_of_consecutive_bits = 1
				end
				last_bit_blank = is_blank
			end
			if number_of_consecutive_bits >= 5 then
				penalty1 = penalty1 + number_of_consecutive_bits - 2
			end
		end
		for x=1,size do
			for y=1,size do
				-- 2: Block of modules in same color
				-- -----------------------------------
				-- Blocksize = m × n  -> 3 × (m-1) × (n-1)
				if (y < size - 1) and ( x < size - 1) and ( (matrix[x][y] < 0 and matrix[x+1][y] < 0 and matrix[x][y+1] < 0 and matrix[x+1][y+1] < 0) or (matrix[x][y] > 0 and matrix[x+1][y] > 0 and matrix[x][y+1] > 0 and matrix[x+1][y+1] > 0) ) then
					penalty2 = penalty2 + 3
				end

				-- 3: 1:1:3:1:1 ratio (dark:light:dark:light:dark) pattern in row/column
				-- ------------------------------------------------------------------
				-- Gives 40 points each
				--
				-- I have no idea why we need the extra 0000 on left or right side. The spec doesn't mention it,
				-- other sources do mention it. This is heavily inspired by zxing.
				if (y + 6 < size and
					matrix[x][y] > 0 and
					matrix[x][y +  1] < 0 and
					matrix[x][y +  2] > 0 and
					matrix[x][y +  3] > 0 and
					matrix[x][y +  4] > 0 and
					matrix[x][y +  5] < 0 and
					matrix[x][y +  6] > 0 and
					((y + 10 < size and
						matrix[x][y +  7] < 0 and
						matrix[x][y +  8] < 0 and
						matrix[x][y +  9] < 0 and
						matrix[x][y + 10] < 0) or
					 (y - 4 >= 1 and
						matrix[x][y -  1] < 0 and
						matrix[x][y -  2] < 0 and
						matrix[x][y -  3] < 0 and
						matrix[x][y -  4] < 0))) then penalty3 = penalty3 + 40 end
				if (x + 6 <= size and
					matrix[x][y] > 0 and
					matrix[x +  1][y] < 0 and
					matrix[x +  2][y] > 0 and
					matrix[x +  3][y] > 0 and
					matrix[x +  4][y] > 0 and
					matrix[x +  5][y] < 0 and
					matrix[x +  6][y] > 0 and
					((x + 10 <= size and
						matrix[x +  7][y] < 0 and
						matrix[x +  8][y] < 0 and
						matrix[x +  9][y] < 0 and
						matrix[x + 10][y] < 0) or
					 (x - 4 >= 1 and
						matrix[x -  1][y] < 0 and
						matrix[x -  2][y] < 0 and
						matrix[x -  3][y] < 0 and
						matrix[x -  4][y] < 0))) then penalty3 = penalty3 + 40 end
			end
		end
		-- 4: Proportion of dark modules in entire symbol
		-- ----------------------------------------------
		-- 50 ± (5 × k)% to 50 ± (5 × (k + 1))% -> 10 × k
		local dark_ratio = number_of_dark_cells / ( size * size )
		penalty4 = math.floor(math.abs(dark_ratio * 100 - 50)) * 2
		return penalty1 + penalty2 + penalty3 + penalty4
	end

	-- Create a matrix for the given parameters and calculate the penalty score.
	-- Return both (matrix and penalty)
	local function get_matrix_and_penalty(version,ec_level,data,mask)
		local tab = prepare_matrix_with_mask(version,ec_level,mask)
		add_data_to_matrix(tab,data,mask)
		local penalty = calculate_penalty(tab)
		return tab, penalty
	end

	-- Return the matrix with the smallest penalty. To to this
	-- we try out the matrix for all 8 masks and determine the
	-- penalty (score) each.
	local function get_matrix_with_lowest_penalty(version,ec_level,data)
		local tab, penalty
		local tab_min_penalty, min_penalty

		-- try masks 0-7
		tab_min_penalty, min_penalty = get_matrix_and_penalty(version,ec_level,data,0)
		for i=1,7 do
			tab, penalty = get_matrix_and_penalty(version,ec_level,data,i)
			if penalty < min_penalty then
				tab_min_penalty = tab
				min_penalty = penalty
			end
		end
		return tab_min_penalty
	end

	-- If ec_level or mode is given, use the ones for generating the qrcode. (mode is not implemented yet)
	local function qrcode( str, ec_level, mode, version_input )
		local arranged_data, version, data_raw, mode, len_bitstring
		version, ec_level, data_raw, mode, len_bitstring = get_version_eclevel_mode_bistringlength(str,ec_level)
		version_in = tonumber(version_input or version)
		if version_in and version_in<version then mw.addWarning('資料'..mw.dumpObject(str)..'無法置入version為'..version_in..'的QR碼中。')end
		version = (version_in<40 and version_in>=version)and version_in or version
		data_raw = data_raw .. len_bitstring
		data_raw = data_raw .. encode_data(str,mode)
		data_raw = add_pad_data(version,ec_level,data_raw)
		arranged_data = arrange_codewords_and_calculate_ec(version,ec_level,data_raw)
		if math.fmod(#arranged_data,8) ~= 0 then
			return false, string.format("Arranged data %% 8 != 0: data length = %d, mod 8 = %d",#arranged_data, math.fmod(#arranged_data,8))
		end
		arranged_data = arranged_data .. string.rep("0",remainder[version])
		local tab = get_matrix_with_lowest_penalty(version,ec_level,arranged_data)
		return true, tab
	end

	return {
		license = license,
		encode_string_numeric = encode_string_numeric,
		encode_string_ascii = encode_string_ascii,
		encode_string_binary = encode_string_binary,
		encode_data = encode_data,
		qrcode = qrcode,
		get_mode = get_mode,
		get_length = get_length,
		add_pad_data = add_pad_data,
		get_generator_polynominal_adjusted = get_generator_polynominal_adjusted,
		get_pixel_with_mask = get_pixel_with_mask,
		get_version_eclevel_mode_bistringlength = get_version_eclevel_mode_bistringlength,
		get_version_eclevel = get_version_eclevel,
		remainder = remainder,
		--get_capacity_remainder = get_capacity_remainder,
		arrange_codewords_and_calculate_ec = arrange_codewords_and_calculate_ec,
		calculate_error_correction = calculate_error_correction,
		convert_bitstring_to_bytes = convert_bitstring_to_bytes,
		get_matrix_and_penalty = get_matrix_and_penalty,
		get_matrix_with_lowest_penalty=get_matrix_with_lowest_penalty,
		bit_xor = bit_xor,
	}
end
function p._get_libbase64()local a,b,c,d,e,f,g,h={},require('bit32').extract,'makeencoder','makedecoder',0x10000,0x40000,'[^%%w%%%s%%%s%%=]',p._get_string_length;a[c]=function(s62,s63,spad)local l={}for m,n in pairs{[0]='A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','0','1','2','3','4','5','6','7','8','9',s62 or'+',s63 or'/',spad or'='}do l[m]=n:byte()end;return l end;a[d]=function(s62,s63,spad)local o={}for m,q in pairs(a[c](s62,s63,spad))do o[q]=m end;return o end;local r=a[c]()local s=a[d]()local n,t,u=string.char,table.concat,p._get_bytes;function a.encode(v,l,w)l=l or r;local x,y,z={},1,h(v)local A=z%3;local B={}for C=1,z-A,3 do local D,E,F=u(v,C,C+2)local G=D*e+E*0x100+F;local H;if w then H=B[G]if not H then H=n(l[b(G,18,6)],l[b(G,12,6)],l[b(G,6,6)],l[b(G,0,6)])B[G]=H end else H=n(l[b(G,18,6)],l[b(G,12,6)],l[b(G,6,6)],l[b(G,0,6)])end;x[y]=H;y=y+1 end;if A==2 then local D,E=u(v,z-1,z)local G=D*e+E*0x100;x[y]=n(l[b(G,18,6)],l[b(G,12,6)],l[b(G,6,6)],l[64])elseif A==1 then local G=u(v,z)*e;x[y]=n(l[b(G,18,6)],l[b(G,12,6)],l[64],l[64])end;return t(x)end;function a.decode(I,o,w,J)o=o or s;local K='[^%w%+%/%=]'if o then local i,j;for q,m in pairs(o)do if m==62 then i=q elseif m==63 then j=q end end;K=g:format(n(i),n(j))end;I=I:gsub(K,'')local B=w and{}local x,y={},1;local z=#I;local L=I:sub(-2)=='=='and 2 or I:sub(-1)=='='and 1 or 0;for C=1,L>0 and z-4 or z,4 do local D,E,F,M=I:byte(C,C+3)local H;if w then local N=D*0x1000000+E*e+F*0x100+M;H=B[N]if not H then local G=o[D]*f+o[E]*0x1000+o[F]*0x40+o[M]H=n(b(G,16,8),b(G,8,8),b(G,0,8))B[N]=H end else local G=o[D]*f+o[E]*0x1000+o[F]*0x40+o[M]H=n(b(G,16,8),b(G,8,8),b(G,0,8))end;x[y]=H;y=y+1 end;if L==1 then local D,E,F=I:byte(z-3,z-1)local G=o[D]*f+o[E]*0x1000+o[F]*0x40;x[y]=n(b(G,16,8),b(G,8,8))elseif L==2 then local D,E=I:byte(z-3,z-2)local G=o[D]*f+o[E]*0x1000;x[y]=n(b(G,16,8))end;if J==true then local O={}for C=1,#x do for P=1,#x[C]do O[#O+1]=x[C]:byte(P)end end;return O end;return t(x)end;return a end
function p.jsonEncode(obj)
	local args, working_frame
    if obj == mw.getCurrentFrame() then
        -- We're being called via #invoke. The args are passed through to the module
        -- from the template page, so use the args that were passed into the template.
        if lib_arg.getArgs == nil then lib_arg = require('Module:Arguments') end
        args = lib_arg.getArgs(obj, {
        	parentFirst=true,
        	trim = false,
			removeBlanks = false
        })
        working_frame = obj
    else
        -- We're being called from another module or from the debug console, so assume
        -- the args are passed in directly.
        args = obj
        working_frame = mw.getCurrentFrame()
        if type(args) ~= type({}) then args = {obj} end
    end
    return _jsonEncode(args)
end
function p.jsonDecode(obj)
	local args, working_frame
    if obj == mw.getCurrentFrame() then
        -- We're being called via #invoke. The args are passed through to the module
        -- from the template page, so use the args that were passed into the template.
        if lib_arg.getArgs == nil then lib_arg = require('Module:Arguments') end
        args = lib_arg.getArgs(obj, {
        	parentFirst=true,
        	trim = false,
			removeBlanks = false
        })
        working_frame = obj
    else
        -- We're being called from another module or from the debug console, so assume
        -- the args are passed in directly.
        args = obj
        working_frame = mw.getCurrentFrame()
        if type(args) ~= type({}) then args = {obj} end
    end
    local var = args[1] or args['1']
    if type(var) ~= type({"table"}) then
    	if type(var) == type(nil) then return nil end
    	if type(var) ~= type("string") then return var end
    	return mw.text.jsonDecode(tostring(var))
    end
    return var
end
function p.jsonGet(obj)
	local args, working_frame
    if obj == mw.getCurrentFrame() then
        -- We're being called via #invoke. The args are passed through to the module
        -- from the template page, so use the args that were passed into the template.
        if lib_arg.getArgs == nil then lib_arg = require('Module:Arguments') end
        args = lib_arg.getArgs(obj, {
        	parentFirst=true,
        	trim = false,
			removeBlanks = false
        })
        working_frame = obj
    else
        -- We're being called from another module or from the debug console, so assume
        -- the args are passed in directly.
        args = obj
        working_frame = mw.getCurrentFrame()
        if type(args) ~= type({}) then args = {obj} end
    end
    local json = p.jsonDecode(obj)
    local key = args[2] or args["2"]
    if type(json) == type(0) or type(json) == type(true) then return nil end
    return (json or {})[key]
end
local yesno=require("Module:Yesno")
function p.base64Encode(obj)
	local args, working_frame
    if obj == mw.getCurrentFrame() then
        -- We're being called via #invoke. The args are passed through to the module
        -- from the template page, so use the args that were passed into the template.
        if lib_arg.getArgs == nil then lib_arg = require('Module:Arguments') end
        args = lib_arg.getArgs(obj, {
        	parentFirst=true,
        	trim = false,
			removeBlanks = false
        })
        working_frame = obj
    else
        -- We're being called from another module or from the debug console, so assume
        -- the args are passed in directly.
        args = obj
        working_frame = mw.getCurrentFrame()
        if type(args) ~= type({}) then args = {obj} end
    end
    local text = args[1]or args['1'] or args.text
    local bitstream = args.bitstream and mw.text.split(args.bitstream,',')
    if not(text or bitstream) then return '' end
    return p._get_libbase64().encode(text or bitstream)
end
function p.base64Decode(obj)
	local args, working_frame
    if obj == mw.getCurrentFrame() then
        -- We're being called via #invoke. The args are passed through to the module
        -- from the template page, so use the args that were passed into the template.
        if lib_arg.getArgs == nil then lib_arg = require('Module:Arguments') end
        args = lib_arg.getArgs(obj, {
        	parentFirst=true,
        	trim = false,
			removeBlanks = false
        })
        working_frame = obj
    else
        -- We're being called from another module or from the debug console, so assume
        -- the args are passed in directly.
        args = obj
        working_frame = mw.getCurrentFrame()
        if type(args) ~= type({}) then args = {obj} end
    end
    local text = args[1]or args['1'] or args.text
    local bitstream = yesno(args.bitstream or false)
    local body = p._get_libbase64().decode(text,nil,nil,bitstream)
    if type(body)==type({})then body=table.concat(body,',')end
    return body
end
p._jsonEncode=_jsonEncode
p._get_libqrcode=function()return init_qrcode_library()end
return p