123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166 |
- package qr
- import (
- "image"
- "image/color"
- "math"
- "github.com/boombuler/barcode"
- "github.com/boombuler/barcode/utils"
- )
- type qrcode struct {
- dimension int
- data *utils.BitList
- content string
- }
- func (qr *qrcode) Content() string {
- return qr.content
- }
- func (qr *qrcode) Metadata() barcode.Metadata {
- return barcode.Metadata{"QR Code", 2}
- }
- func (qr *qrcode) ColorModel() color.Model {
- return color.Gray16Model
- }
- func (qr *qrcode) Bounds() image.Rectangle {
- return image.Rect(0, 0, qr.dimension, qr.dimension)
- }
- func (qr *qrcode) At(x, y int) color.Color {
- if qr.Get(x, y) {
- return color.Black
- }
- return color.White
- }
- func (qr *qrcode) Get(x, y int) bool {
- return qr.data.GetBit(x*qr.dimension + y)
- }
- func (qr *qrcode) Set(x, y int, val bool) {
- qr.data.SetBit(x*qr.dimension+y, val)
- }
- func (qr *qrcode) calcPenalty() uint {
- return qr.calcPenaltyRule1() + qr.calcPenaltyRule2() + qr.calcPenaltyRule3() + qr.calcPenaltyRule4()
- }
- func (qr *qrcode) calcPenaltyRule1() uint {
- var result uint
- for x := 0; x < qr.dimension; x++ {
- checkForX := false
- var cntX uint
- checkForY := false
- var cntY uint
- for y := 0; y < qr.dimension; y++ {
- if qr.Get(x, y) == checkForX {
- cntX++
- } else {
- checkForX = !checkForX
- if cntX >= 5 {
- result += cntX - 2
- }
- cntX = 1
- }
- if qr.Get(y, x) == checkForY {
- cntY++
- } else {
- checkForY = !checkForY
- if cntY >= 5 {
- result += cntY - 2
- }
- cntY = 1
- }
- }
- if cntX >= 5 {
- result += cntX - 2
- }
- if cntY >= 5 {
- result += cntY - 2
- }
- }
- return result
- }
- func (qr *qrcode) calcPenaltyRule2() uint {
- var result uint
- for x := 0; x < qr.dimension-1; x++ {
- for y := 0; y < qr.dimension-1; y++ {
- check := qr.Get(x, y)
- if qr.Get(x, y+1) == check && qr.Get(x+1, y) == check && qr.Get(x+1, y+1) == check {
- result += 3
- }
- }
- }
- return result
- }
- func (qr *qrcode) calcPenaltyRule3() uint {
- pattern1 := []bool{true, false, true, true, true, false, true, false, false, false, false}
- pattern2 := []bool{false, false, false, false, true, false, true, true, true, false, true}
- var result uint
- for x := 0; x <= qr.dimension-len(pattern1); x++ {
- for y := 0; y < qr.dimension; y++ {
- pattern1XFound := true
- pattern2XFound := true
- pattern1YFound := true
- pattern2YFound := true
- for i := 0; i < len(pattern1); i++ {
- iv := qr.Get(x+i, y)
- if iv != pattern1[i] {
- pattern1XFound = false
- }
- if iv != pattern2[i] {
- pattern2XFound = false
- }
- iv = qr.Get(y, x+i)
- if iv != pattern1[i] {
- pattern1YFound = false
- }
- if iv != pattern2[i] {
- pattern2YFound = false
- }
- }
- if pattern1XFound || pattern2XFound {
- result += 40
- }
- if pattern1YFound || pattern2YFound {
- result += 40
- }
- }
- }
- return result
- }
- func (qr *qrcode) calcPenaltyRule4() uint {
- totalNum := qr.data.Len()
- trueCnt := 0
- for i := 0; i < totalNum; i++ {
- if qr.data.GetBit(i) {
- trueCnt++
- }
- }
- percDark := float64(trueCnt) * 100 / float64(totalNum)
- floor := math.Abs(math.Floor(percDark/5) - 10)
- ceil := math.Abs(math.Ceil(percDark/5) - 10)
- return uint(math.Min(floor, ceil) * 10)
- }
- func newBarcode(dim int) *qrcode {
- res := new(qrcode)
- res.dimension = dim
- res.data = utils.NewBitList(dim * dim)
- return res
- }
|