168 lines
3.2 KiB
Go
168 lines
3.2 KiB
Go
|
package qrcode
|
||
|
|
||
|
import (
|
||
|
"errors"
|
||
|
"fmt"
|
||
|
)
|
||
|
|
||
|
var (
|
||
|
// ErrorOutRangeOfW x out of range of Width
|
||
|
ErrorOutRangeOfW = errors.New("out of range of width")
|
||
|
|
||
|
// ErrorOutRangeOfH y out of range of Height
|
||
|
ErrorOutRangeOfH = errors.New("out of range of height")
|
||
|
)
|
||
|
|
||
|
// newMatrix generate a matrix with map[][]qrbool
|
||
|
func newMatrix(width, height int) *Matrix {
|
||
|
mat := make([][]qrvalue, width)
|
||
|
for w := 0; w < width; w++ {
|
||
|
mat[w] = make([]qrvalue, height)
|
||
|
}
|
||
|
|
||
|
m := &Matrix{
|
||
|
mat: mat,
|
||
|
width: width,
|
||
|
height: height,
|
||
|
}
|
||
|
|
||
|
m.init()
|
||
|
return m
|
||
|
}
|
||
|
|
||
|
// Matrix is a matrix data type
|
||
|
// width:3 height: 4 for [3][4]int
|
||
|
type Matrix struct {
|
||
|
mat [][]qrvalue
|
||
|
width int
|
||
|
height int
|
||
|
}
|
||
|
|
||
|
// do some init work
|
||
|
func (m *Matrix) init() {
|
||
|
for w := 0; w < m.width; w++ {
|
||
|
for h := 0; h < m.height; h++ {
|
||
|
m.mat[w][h] = QRValue_INIT_V0
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// print to stdout
|
||
|
func (m *Matrix) print() {
|
||
|
m.iter(IterDirection_ROW, func(x, y int, s qrvalue) {
|
||
|
fmt.Printf("%s ", s)
|
||
|
if (x + 1) == m.width {
|
||
|
fmt.Println()
|
||
|
}
|
||
|
})
|
||
|
}
|
||
|
|
||
|
// Copy matrix into a new Matrix
|
||
|
func (m *Matrix) Copy() *Matrix {
|
||
|
mat2 := make([][]qrvalue, m.width)
|
||
|
for w := 0; w < m.width; w++ {
|
||
|
mat2[w] = make([]qrvalue, m.height)
|
||
|
copy(mat2[w], m.mat[w])
|
||
|
}
|
||
|
|
||
|
m2 := &Matrix{
|
||
|
width: m.width,
|
||
|
height: m.height,
|
||
|
mat: mat2,
|
||
|
}
|
||
|
|
||
|
return m2
|
||
|
}
|
||
|
|
||
|
// Width ... width
|
||
|
func (m *Matrix) Width() int {
|
||
|
return m.width
|
||
|
}
|
||
|
|
||
|
// Height ... height
|
||
|
func (m *Matrix) Height() int {
|
||
|
return m.height
|
||
|
}
|
||
|
|
||
|
// set [w][h] as true
|
||
|
func (m *Matrix) set(w, h int, c qrvalue) error {
|
||
|
if w >= m.width || w < 0 {
|
||
|
return ErrorOutRangeOfW
|
||
|
}
|
||
|
if h >= m.height || h < 0 {
|
||
|
return ErrorOutRangeOfH
|
||
|
}
|
||
|
m.mat[w][h] = c
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
// at state qrvalue from matrix with position {x, y}
|
||
|
func (m *Matrix) at(w, h int) (qrvalue, error) {
|
||
|
if w >= m.width || w < 0 {
|
||
|
return QRValue_INIT_V0, ErrorOutRangeOfW
|
||
|
}
|
||
|
if h >= m.height || h < 0 {
|
||
|
return QRValue_INIT_V0, ErrorOutRangeOfH
|
||
|
}
|
||
|
return m.mat[w][h], nil
|
||
|
}
|
||
|
|
||
|
// iterDirection scan matrix direction
|
||
|
type iterDirection uint8
|
||
|
|
||
|
const (
|
||
|
// IterDirection_ROW for row first
|
||
|
IterDirection_ROW iterDirection = iota + 1
|
||
|
|
||
|
// IterDirection_COLUMN for column first
|
||
|
IterDirection_COLUMN
|
||
|
)
|
||
|
|
||
|
// Iterate the Matrix with loop direction IterDirection_ROW major or IterDirection_COLUMN major.
|
||
|
// IterDirection_COLUMN is recommended.
|
||
|
func (m *Matrix) Iterate(direction iterDirection, fn func(x, y int, s QRValue)) {
|
||
|
m.iter(direction, fn)
|
||
|
}
|
||
|
|
||
|
func (m *Matrix) iter(dir iterDirection, visitFn func(x int, y int, v qrvalue)) {
|
||
|
// row direction first
|
||
|
if dir == IterDirection_ROW {
|
||
|
for h := 0; h < m.height; h++ {
|
||
|
for w := 0; w < m.width; w++ {
|
||
|
visitFn(w, h, m.mat[w][h])
|
||
|
}
|
||
|
}
|
||
|
return
|
||
|
}
|
||
|
|
||
|
// column direction first
|
||
|
for w := 0; w < m.width; w++ {
|
||
|
for h := 0; h < m.height; h++ {
|
||
|
visitFn(w, h, m.mat[w][h])
|
||
|
}
|
||
|
}
|
||
|
return
|
||
|
}
|
||
|
|
||
|
// Row return a row of matrix, cur should be y dimension.
|
||
|
func (m *Matrix) Row(cur int) []qrvalue {
|
||
|
if cur >= m.height || cur < 0 {
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
col := make([]qrvalue, m.height)
|
||
|
for w := 0; w < m.width; w++ {
|
||
|
col[w] = m.mat[w][cur]
|
||
|
}
|
||
|
return col
|
||
|
}
|
||
|
|
||
|
// Col return a slice of column, cur should be x dimension.
|
||
|
func (m *Matrix) Col(cur int) []qrvalue {
|
||
|
if cur >= m.width || cur < 0 {
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
return m.mat[cur]
|
||
|
}
|