fckeuspy-go/vendor/github.com/liyue201/goqr/qrcode.go
2025-09-22 19:42:23 +02:00

147 lines
3.0 KiB
Go

package goqr
// qrCode is used to return information about detected QR codes
// in the input image.
type qrCode struct {
// The four corners of the QR-code, from top left, clockwise
corners [4]point
// The number of cells across in the QR-code. The cell bitmap
// is a bitmask giving the actual values of cells. If the cell
// at (x, y) is black, then the following bit is set:
//
// cell_bitmap[i >> 3] & (1 << (i & 7))
//
// where i = (y * size) + x.
//
size int
cellBitmap [qrMaxBimap]uint8
}
// QRData holds the decoded QR-code data
type QRData struct {
// Various parameters of the QR-code. These can mostly be
// ignored if you only care about the data.
Version int
EccLevel int
Mask int
// This field is the highest-valued data type found in the QR code.
DataType int
// Data Payload. For the Kanji datatype, Payload is encoded as
// Shift-JIS. For all other datatypes, Payload is ASCII text.
Payload []uint8
// ECI assignment number
Eci uint32
}
func gridBit(code *qrCode, x, y int) int {
p := uint(y*code.size + x)
return int((code.cellBitmap[p>>3])>>(p&7)) & 1
}
func readFormat(code *qrCode, data *QRData, which int) error {
format := uint16(0)
if which != 0 {
for i := 0; i < 7; i++ {
format = (format << 1) | uint16(gridBit(code, 8, code.size-1-i))
}
for i := 0; i < 8; i++ {
format = (format << 1) | uint16(gridBit(code, code.size-8+i, 8))
}
} else {
xs := [15]int{8, 8, 8, 8, 8, 8, 8, 8, 7, 5, 4, 3, 2, 1, 0}
ys := [15]int{0, 1, 2, 3, 4, 5, 7, 8, 8, 8, 8, 8, 8, 8, 8}
for i := 14; i >= 0; i-- {
format = (format << 1) | uint16(gridBit(code, xs[i], ys[i]))
}
}
format ^= 0x5412
err := correctFormat(&format)
if err != nil {
return err
}
fdata := format >> 10
data.EccLevel = int(fdata) >> 3
data.Mask = int(fdata) & 7
return nil
}
func readBit(code *qrCode, data *QRData, ds *datastream, i, j int) {
bitpos := ds.dataBits & 7
bytepos := ds.dataBits >> 3
v := gridBit(code, j, i)
if maskBit(data.Mask, i, j) != 0 {
v ^= 1
}
if v != 0 {
ds.raw[bytepos] |= 0x80 >> uint32(bitpos)
}
ds.dataBits++
}
func readData(code *qrCode, data *QRData, ds *datastream) {
y := code.size - 1
x := code.size - 1
dir := -1
for x > 0 {
if x == 6 {
x--
}
if 0 == reservedCell(data.Version, y, x) {
readBit(code, data, ds, y, x)
}
if 0 == reservedCell(data.Version, y, x-1) {
readBit(code, data, ds, y, x-1)
}
y += dir
if y < 0 || y >= code.size {
dir = -dir
x -= 2
y += dir
}
}
}
func decode(code *qrCode, data *QRData) error {
var ds datastream
if (code.size-17)%4 != 0 {
return ErrInvalidGridSize
}
data.Version = (code.size - 17) / 4
if data.Version < 1 || data.Version > qrMaxVersion {
return ErrInvalidVersion
}
// Read format information -- try both locations
err := readFormat(code, data, 0)
if err != nil {
err = readFormat(code, data, 1)
}
if err != nil {
return err
}
readData(code, data, &ds)
err = codestreamEcc(data, &ds)
if err != nil {
return err
}
err = decodePayload(data, &ds)
if err != nil {
return err
}
return nil
}