You've already forked KotlinQRCode
Upload
This commit is contained in:
@@ -23,6 +23,8 @@ kotlin {
|
|||||||
}
|
}
|
||||||
jvm { compilerOptions.jvmTarget = JvmTarget.JVM_1_8 }
|
jvm { compilerOptions.jvmTarget = JvmTarget.JVM_1_8 }
|
||||||
|
|
||||||
|
explicitApi()
|
||||||
|
|
||||||
sourceSets {
|
sourceSets {
|
||||||
commonMain.dependencies {
|
commonMain.dependencies {
|
||||||
|
|
||||||
|
|||||||
29
src/commonMain/kotlin/cn/rtast/kqrcode/QRMatrix.kt
Normal file
29
src/commonMain/kotlin/cn/rtast/kqrcode/QRMatrix.kt
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
/*
|
||||||
|
* Copyright © 2025 RTAkland
|
||||||
|
* Author: RTAkland
|
||||||
|
* Date: 2025/12/24
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
package cn.rtast.kqrcode
|
||||||
|
|
||||||
|
public class QRMatrix(
|
||||||
|
public val version: Int,
|
||||||
|
) {
|
||||||
|
private val size = 21 + (version - 1) * 4
|
||||||
|
private val finderTL = 0 to 0
|
||||||
|
private val finderTR = 0 to size - 7
|
||||||
|
private val finderBL = size - 7 to 0
|
||||||
|
|
||||||
|
private fun drawTimingPatterns(matrix: Array<IntArray>) {
|
||||||
|
val size = matrix.size
|
||||||
|
for (col in 8 until size - 8) {
|
||||||
|
matrix[6][col] = if (col % 2 == 0) 1 else 0
|
||||||
|
}
|
||||||
|
for (row in 8 until size - 8) {
|
||||||
|
matrix[row][6] = if (row % 2 == 0) 1 else 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public fun generate() {
|
||||||
|
}
|
||||||
|
}
|
||||||
20
src/commonMain/kotlin/cn/rtast/kqrcode/const.kt
Normal file
20
src/commonMain/kotlin/cn/rtast/kqrcode/const.kt
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
/*
|
||||||
|
* Copyright © 2025 RTAkland
|
||||||
|
* Author: RTAkland
|
||||||
|
* Date: 2025/12/24
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
package cn.rtast.kqrcode
|
||||||
|
|
||||||
|
internal val FINDER_MATRIX = arrayOf(
|
||||||
|
Array(9) { 0 },
|
||||||
|
arrayOf(0, 1, 1, 1, 1, 1, 1, 1, 0),
|
||||||
|
arrayOf(0, 1, 0, 0, 0, 0, 0, 1, 0),
|
||||||
|
arrayOf(0, 1, 0, 1, 1, 1, 0, 1, 0),
|
||||||
|
arrayOf(0, 1, 0, 1, 1, 1, 0, 1, 0),
|
||||||
|
arrayOf(0, 1, 0, 1, 1, 1, 0, 1, 0),
|
||||||
|
arrayOf(0, 1, 0, 0, 0, 0, 0, 1, 0),
|
||||||
|
arrayOf(0, 1, 1, 1, 1, 1, 1, 1, 0),
|
||||||
|
Array(9) { 0 },
|
||||||
|
)
|
||||||
12
src/commonMain/kotlin/cn/rtast/kqrcode/eclevel.kt
Normal file
12
src/commonMain/kotlin/cn/rtast/kqrcode/eclevel.kt
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
/*
|
||||||
|
* Copyright © 2025 RTAkland
|
||||||
|
* Author: RTAkland
|
||||||
|
* Date: 2025/12/24
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
package cn.rtast.kqrcode
|
||||||
|
|
||||||
|
public enum class ECLevel(public val ecPercent: Int) {
|
||||||
|
L(7), M(15), Q(25), H(30)
|
||||||
|
}
|
||||||
37
src/commonMain/kotlin/cn/rtast/kqrcode/encode.kt
Normal file
37
src/commonMain/kotlin/cn/rtast/kqrcode/encode.kt
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* Copyright © 2025 RTAkland
|
||||||
|
* Author: RTAkland
|
||||||
|
* Date: 2025/12/24
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
package cn.rtast.kqrcode
|
||||||
|
|
||||||
|
internal object QRCodeEncoder {
|
||||||
|
|
||||||
|
const val NumericModeIndicator = 0b0100
|
||||||
|
|
||||||
|
fun Int.toBits(bitCount: Int): List<Int> {
|
||||||
|
require(this >= 0)
|
||||||
|
val bits = ArrayList<Int>(bitCount)
|
||||||
|
for (i in bitCount - 1 downTo 0) bits.add((this shr i) and 1)
|
||||||
|
return bits
|
||||||
|
}
|
||||||
|
|
||||||
|
fun encodeNumeric(s: String): IntArray {
|
||||||
|
val bits = mutableListOf<Int>()
|
||||||
|
var i = 0
|
||||||
|
while (i < s.length) {
|
||||||
|
val chunk = minOf(3, s.length - i)
|
||||||
|
val num = s.substring(i, i + chunk).toInt()
|
||||||
|
val bitLen = when (chunk) {
|
||||||
|
3 -> 10
|
||||||
|
2 -> 7
|
||||||
|
else -> 4
|
||||||
|
}
|
||||||
|
bits.addAll(num.toBits(bitLen))
|
||||||
|
i += chunk
|
||||||
|
}
|
||||||
|
return bits.toIntArray()
|
||||||
|
}
|
||||||
|
}
|
||||||
51
src/commonMain/kotlin/cn/rtast/kqrcode/galoisfield.kt
Normal file
51
src/commonMain/kotlin/cn/rtast/kqrcode/galoisfield.kt
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
/*
|
||||||
|
* Copyright © 2025 RTAkland
|
||||||
|
* Author: RTAkland
|
||||||
|
* Date: 2025/12/24
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
package cn.rtast.kqrcode
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* https://en.wikipedia.org/wiki/Finite_field
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
internal fun gfAdd(a: Int, b: Int) = a xor b
|
||||||
|
|
||||||
|
/**
|
||||||
|
* eq 2 add
|
||||||
|
*/
|
||||||
|
internal fun gfMin(a: Int, b: Int) = gfAdd(a, b)
|
||||||
|
|
||||||
|
internal fun gfMul(a: Int, b: Int): Int {
|
||||||
|
if (a == 0 || b == 0) return 0
|
||||||
|
return EXP[LOG[a] + LOG[b]]
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun gfDiv(a: Int, b: Int): Int {
|
||||||
|
require(b != 0)
|
||||||
|
if (a == 0) return 0
|
||||||
|
return EXP[(LOG[a] + 255 - LOG[b]) % 255]
|
||||||
|
}
|
||||||
|
|
||||||
|
internal val EXP = IntArray(512)
|
||||||
|
internal val LOG = IntArray(256)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* init galois field matrix
|
||||||
|
*/
|
||||||
|
internal fun initGF() {
|
||||||
|
var x = 1
|
||||||
|
for (i in 0 until 255) {
|
||||||
|
EXP[i] = x
|
||||||
|
LOG[x] = i
|
||||||
|
x = x shl 1
|
||||||
|
if (x and 0x100 != 0) x = x xor 0x11D
|
||||||
|
}
|
||||||
|
for (i in 255 until 512) {
|
||||||
|
EXP[i] = EXP[i - 255]
|
||||||
|
}
|
||||||
|
}
|
||||||
25
src/commonMain/kotlin/cn/rtast/kqrcode/poly.kt
Normal file
25
src/commonMain/kotlin/cn/rtast/kqrcode/poly.kt
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
/*
|
||||||
|
* Copyright © 2025 RTAkland
|
||||||
|
* Author: RTAkland
|
||||||
|
* Date: 2025/12/24
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
package cn.rtast.kqrcode
|
||||||
|
|
||||||
|
internal typealias Poly = IntArray
|
||||||
|
|
||||||
|
internal fun polyMul(a: Poly, b: Poly): Poly {
|
||||||
|
val result = IntArray(a.size + b.size - 1)
|
||||||
|
a.indices.forEach { i -> b.forEach { j -> result[i + j] = result[i + j] xor gfMul(a[i], b[j]) } }
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun polyGenerator(ecLevel: ECLevel): Poly {
|
||||||
|
var r = intArrayOf(1)
|
||||||
|
for (i in 0 until ecLevel.ecPercent) {
|
||||||
|
val term = intArrayOf(1, EXP[i])
|
||||||
|
r = polyMul(r, term)
|
||||||
|
}
|
||||||
|
return r
|
||||||
|
}
|
||||||
25
src/commonMain/kotlin/cn/rtast/kqrcode/reedsolomon.kt
Normal file
25
src/commonMain/kotlin/cn/rtast/kqrcode/reedsolomon.kt
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
/*
|
||||||
|
* Copyright © 2025 RTAkland
|
||||||
|
* Author: RTAkland
|
||||||
|
* Date: 2025/12/24
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
package cn.rtast.kqrcode
|
||||||
|
|
||||||
|
/**
|
||||||
|
* https://en.wikipedia.org/wiki/Reed%E2%80%93Solomon_error_correction
|
||||||
|
*/
|
||||||
|
internal fun reedSolomonEncode(data: IntArray, ecLevel: ECLevel): IntArray {
|
||||||
|
val generator = polyGenerator(ecLevel)
|
||||||
|
val buffer = IntArray(data.size + ecLevel.ecPercent)
|
||||||
|
for (i in data.indices) buffer[i] = data[i]
|
||||||
|
for (i in data.indices) {
|
||||||
|
val factor = buffer[i]
|
||||||
|
if (factor != 0) for (j in generator.indices) buffer[i + j] = buffer[i + j] xor gfMul(generator[j], factor)
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* copy ec code part
|
||||||
|
*/
|
||||||
|
return buffer.copyOfRange(data.size, buffer.size)
|
||||||
|
}
|
||||||
15
src/commonMain/kotlin/cn/rtast/kqrcode/version.kt
Normal file
15
src/commonMain/kotlin/cn/rtast/kqrcode/version.kt
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
/*
|
||||||
|
* Copyright © 2025 RTAkland
|
||||||
|
* Author: RTAkland
|
||||||
|
* Date: 2025/12/24
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
package cn.rtast.kqrcode
|
||||||
|
|
||||||
|
public value class QRCodeVersion(public val size: Int)
|
||||||
|
|
||||||
|
public fun Int.asQRCodeVersion(): QRCodeVersion {
|
||||||
|
require(this in 1..40) { throw IllegalArgumentException("QRCode version must in range 1(included)..40(included)") }
|
||||||
|
return QRCodeVersion(21 + (this - 1) * 4)
|
||||||
|
}
|
||||||
20
src/commonTest/kotlin/test/TestAnchor.kt
Normal file
20
src/commonTest/kotlin/test/TestAnchor.kt
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
/*
|
||||||
|
* Copyright © 2025 RTAkland
|
||||||
|
* Author: RTAkland
|
||||||
|
* Date: 2025/12/24
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
package test
|
||||||
|
|
||||||
|
import cn.rtast.kqrcode.FINDER_MATRIX
|
||||||
|
import kotlin.test.Test
|
||||||
|
|
||||||
|
class TestAnchor {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `test anchor println`() {
|
||||||
|
println(FINDER_MATRIX.map { it.toList().apply { println(it.size) } })
|
||||||
|
println(FINDER_MATRIX.size)
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user