From 8c0c3dbb4667636370e572d02f70d3e23944d817 Mon Sep 17 00:00:00 2001 From: Will Kang Date: Sat, 17 Sep 2022 19:20:39 +0800 Subject: [PATCH] Complete development of QR code in multiple colors. --- README.md | 16 +++-- core/cons/constant.go | 12 ++++ core/logger/logger.go | 12 ++-- core/mode/alphanumeric_test.go | 21 ++++--- core/mode/byte_mode.go | 2 +- core/mode/eci_mode.go | 3 +- core/mode/fnc1_mode.go | 3 +- core/mode/kanji_mode.go | 23 +++++--- core/mode/mixed_mode.go | 3 +- core/mode/mode.go | 74 ++++++++++++------------ core/mode/numeric_mode_test.go | 40 +++++++------ core/mode/qrcodestruct.go | 6 +- core/mode/structuredappend_mode.go | 3 +- core/model/separator.go | 3 - core/model/timingpattern.go | 24 ++++---- core/output/image_output.go | 28 +++++++-- core/output/output.go | 31 ++++++---- doc/images/qr/byte_colorful_200x200.png | Bin 0 -> 1256 bytes doc/images/qr/byte_colorful_400x400.png | Bin 0 -> 2193 bytes test/qrcode_test.go | 9 ++- util/datastream.go | 55 +++++++++--------- util/datastream_test.go | 12 ++-- util/util.go | 12 ++++ util/util_test.go | 25 ++++---- 24 files changed, 241 insertions(+), 176 deletions(-) create mode 100644 doc/images/qr/byte_colorful_200x200.png create mode 100644 doc/images/qr/byte_colorful_400x400.png diff --git a/README.md b/README.md index 6c2aca1..d898bea 100644 --- a/README.md +++ b/README.md @@ -75,6 +75,8 @@ Micro QRCode supports 4 character modes, and 4 versions with 4 Error correction qrcode, err := NewQRCode(data) outFileName := "/opt/temp/numeric.png" if err == nil{ + // set color for qrcode + // out := output.NewOutput(&output.BaseOutput{Type: output.PNG, Size: 400, CodeColor: output.ColorfulCodeColor}) out := output.NewPNGOutput0() qrcode.Encode(out,outFileName) } @@ -103,7 +105,11 @@ Micro QRCode supports 4 character modes, and 4 versions with 4 Error correction Create a new QRCode(Model2) by input data with auto-size Quiet Zone, default is 4x modules per side. e.g.: -![alphanumeric qrcode with auto quiet zone](doc/images/qr/alphanumeric_auto_quietzone.jpg) + ![alphanumeric qrcode with auto quiet zone](doc/images/qr/alphanumeric_auto_quietzone.jpg) + + QRCode with color: + + ![byte_colorful_200x200.png](doc/images/qr/byte_colorful_200x200.png) * [NewMicroQRCode(content string) (*mode.QRCodeStruct,error)](qrcode.go) @@ -111,7 +117,7 @@ Micro QRCode supports 4 character modes, and 4 versions with 4 Error correction Create a new Micro QRCode by input data. e.g.: -![numeric qrcode](doc/images/qr/numeric_micro_qrcode5.png) + ![numeric qrcode](doc/images/qr/numeric_micro_qrcode5.png) * [NewMicroQRCodeAutoQuiet(content string) (*mode.QRCodeStruct,error)](qrcode.go) @@ -119,7 +125,7 @@ Micro QRCode supports 4 character modes, and 4 versions with 4 Error correction Create a new Micro QRCode by input data with auto-size Quiet Zone, default is 2x modules per side. e.g.: -![byte_micro qrcode with auto quiet zone](doc/images/qr/byte_micro_qrcode15.png) + ![byte_micro qrcode with auto quiet zone](doc/images/qr/byte_micro_qrcode15.png) * [NewQRCode0(content string,format cons.Format,ec *mode.ErrorCorrection,m mode.Mode,quietZone *model.QuietZone) (qr *mode.QRCodeStruct,err error)](qrcode.go) @@ -248,8 +254,8 @@ All QRCode test in [qrcode_test.go](test/qrcode_test.go) and [micro_qrcode_test. Output - Image File - 2021-05-30 + Image File
(With Color) + 2021-05-30
(2022-09-17) Base64 String diff --git a/core/cons/constant.go b/core/cons/constant.go index d1eae42..47e099e 100644 --- a/core/cons/constant.go +++ b/core/cons/constant.go @@ -26,6 +26,9 @@ const ( NONE ErrorCorrectionLevel = -1 //-1 ) +// QRCodeStructPart For example: alignmentPattern, FinderPattern... +type QRCodeStructPart = int + type ModeType = string const ( @@ -38,6 +41,15 @@ const ( Fnc1ModeP2 ModeType = "FNC1_P2" KanjiMode ModeType = "Kanji" StructuredAppendMode ModeType = "Structured Append" + + // QRCodeStructPart + DataPart QRCodeStructPart = 0 + FinderPatternPart QRCodeStructPart = 1 + AlignmentPart QRCodeStructPart = 2 + QuietZonePart QRCodeStructPart = 3 + TimingPatternPart QRCodeStructPart = 4 + FormatPart QRCodeStructPart = 5 + VersionPart QRCodeStructPart = 6 ) type Format = string diff --git a/core/logger/logger.go b/core/logger/logger.go index 76f608a..3fe5056 100644 --- a/core/logger/logger.go +++ b/core/logger/logger.go @@ -7,7 +7,7 @@ import ( // Define log handle here -func Warn(msg interface{}){ +func Warn(msg interface{}) { fmt.Println("[WARN]", msg) } @@ -15,8 +15,8 @@ func Info(msg interface{}) { fmt.Println("[INFO]", msg) } -func Error(msg interface{}){ - if _,ok:= msg.(error); ok { +func Error(msg interface{}) { + if _, ok := msg.(error); ok { for i := 1; ; i++ { pc, file, line, ok := runtime.Caller(i) if !ok { @@ -24,10 +24,10 @@ func Error(msg interface{}){ } f := runtime.FuncForPC(pc) if f.Name() != "runtime.main" && f.Name() != "runtime.goexit" { - fmt.Printf("[ERROR] %s %s (%d) %s \n",file,f.Name(), line, msg) + fmt.Printf("[ERROR] %s %s (%d) %s \n", file, f.Name(), line, msg) } } - }else{ + } else { fmt.Println("[ERROR] ", msg) } -} \ No newline at end of file +} diff --git a/core/mode/alphanumeric_test.go b/core/mode/alphanumeric_test.go index 4d15a82..7366c9c 100644 --- a/core/mode/alphanumeric_test.go +++ b/core/mode/alphanumeric_test.go @@ -13,32 +13,31 @@ import ( func TestChar(t *testing.T) { data := "A" - fmt.Printf("data:%s,data[:1]:%s, data[0]:%s \n",data,data[:1],data[0:]) + fmt.Printf("data:%s,data[:1]:%s, data[0]:%s \n", data, data[:1], data[0:]) data = "AB" - fmt.Printf("data:%s,data[:1]:%s, data[0]:%s \n",data,data[:1],data[0:]) + fmt.Printf("data:%s,data[:1]:%s, data[0]:%s \n", data, data[:1], data[0:]) } func TestByte(t *testing.T) { data := "A" - fmt.Printf("data:%d \n",data[0]) - fmt.Println("data:" + string( data[0])) + fmt.Printf("data:%d \n", data[0]) + fmt.Println("data:" + string(data[0])) } func TestKanji(t *testing.T) { data := "0日月" - if a ,err:=ToShiftJIS(data);err!= nil{ + if a, err := ToShiftJIS(data); err != nil { t.Fatal(err) - }else{ + } else { //aaa,err:= FromShiftJIS(a) - aaa:=strconv.Quote(a) - for _,v:= range strings.Split(aaa[1:len(aaa)-1],"\\x"){ + aaa := strconv.Quote(a) + for _, v := range strings.Split(aaa[1:len(aaa)-1], "\\x") { fmt.Printf("aaa:%v\n", v) } } - } -func transformEncoding( rawReader io.Reader, trans transform.Transformer) (string, error) { +func transformEncoding(rawReader io.Reader, trans transform.Transformer) (string, error) { ret, err := ioutil.ReadAll(transform.NewReader(rawReader, trans)) if err == nil { return string(ret), nil @@ -55,4 +54,4 @@ func FromShiftJIS(str string) (string, error) { // Convert a string encoding from UTF-8 to ShiftJIS func ToShiftJIS(str string) (string, error) { return transformEncoding(strings.NewReader(str), japanese.ShiftJIS.NewEncoder()) -} \ No newline at end of file +} diff --git a/core/mode/byte_mode.go b/core/mode/byte_mode.go index f86ab8a..f4a2602 100644 --- a/core/mode/byte_mode.go +++ b/core/mode/byte_mode.go @@ -14,7 +14,7 @@ import ( // 1. Byte mode is not available in Version M1 or M2 Micro QR Code Symbol. // 2. Byte mode max capacity is 2953 -const ByteRegExpType = "^.*$" +const ByteRegExpType = ".*" type ByteMode struct { *AbstractMode diff --git a/core/mode/eci_mode.go b/core/mode/eci_mode.go index 96fefcf..f77200e 100644 --- a/core/mode/eci_mode.go +++ b/core/mode/eci_mode.go @@ -13,9 +13,8 @@ package mode // --- ECI Designator(8,16 or 24 bits) // - type ECI struct { *AbstractMode } -// TODO NOT IMPLEMENT \ No newline at end of file +// TODO NOT IMPLEMENT diff --git a/core/mode/fnc1_mode.go b/core/mode/fnc1_mode.go index e2912c3..7c15ee9 100644 --- a/core/mode/fnc1_mode.go +++ b/core/mode/fnc1_mode.go @@ -11,9 +11,8 @@ package mode // 1. FNC1 mode is not available for Micro QR Code Symbol. // - type FNC1 struct { *AbstractMode } -// TODO NOT IMPLEMENT \ No newline at end of file +// TODO NOT IMPLEMENT diff --git a/core/mode/kanji_mode.go b/core/mode/kanji_mode.go index d77fc21..4c41cc9 100644 --- a/core/mode/kanji_mode.go +++ b/core/mode/kanji_mode.go @@ -75,9 +75,9 @@ func (km *KanjiMode) IsSupport(data string) bool { } loop := dataLen / 2 for i := 0; i < loop; i++ { - twoByteInt := <-util.IteratorTwoByte(data) - if !(is8140To9FFC(twoByteInt)) && - !(isE040ToEBBF(twoByteInt)) { + char := <-util.IteratorStringByte(data) + if !(is8140To9FFCChar(char)) && + !(isE040ToEBBFChar(char)) { return false } @@ -85,9 +85,18 @@ func (km *KanjiMode) IsSupport(data string) bool { return true } -func is8140To9FFC(twoByteInt uint16) bool { - return hex8140 <= twoByteInt && twoByteInt <= 0x9FFC +func is8140To9FFC(char uint16) bool { + return hex8140 <= char && char <= 0x9FFC } -func isE040ToEBBF(twoByteInt uint16) bool { - return hexE040 <= twoByteInt && twoByteInt <= 0xEBBF + +func is8140To9FFCChar(char rune) bool { + return hex8140 <= char && char <= 0x9FFC +} + +func isE040ToEBBF(char uint16) bool { + return hexE040 <= char && char <= 0xEBBF +} + +func isE040ToEBBFChar(char rune) bool { + return hexE040 <= char && char <= 0xEBBF } diff --git a/core/mode/mixed_mode.go b/core/mode/mixed_mode.go index 2a02578..4f0722d 100644 --- a/core/mode/mixed_mode.go +++ b/core/mode/mixed_mode.go @@ -4,5 +4,4 @@ package mode // The QR Code symbol may contain sequences of data in a combination of any of the modes described in 7.3.2 to 7.3.9. // Micro QR Code symbols may contain sequences of data in a combination of any the modes available for the version of symbol and described in 7.3.3 to 7.3.7. - -// TODO NOT IMPLEMENT \ No newline at end of file +// TODO NOT IMPLEMENT diff --git a/core/mode/mode.go b/core/mode/mode.go index 617aeee..da192f1 100644 --- a/core/mode/mode.go +++ b/core/mode/mode.go @@ -373,7 +373,7 @@ func (m *AbstractMode) BuildModuleInMatrix(qr *QRCodeStruct, codewordsBits []uti maskOutputGroup := newQRCodeMaskOutputGroup(qr.GetMaskCount(), out) // output group with mask for common - outputGroupOutMask := func(x int, y int, val bool, hasMask bool) { + outputGroupOutMask := func(x int, y int, val bool, hasMask bool, part cons.QRCodeStructPart) { srcVal := val for i, out_ := range maskOutputGroup { newVal := srcVal @@ -384,17 +384,17 @@ func (m *AbstractMode) BuildModuleInMatrix(qr *QRCodeStruct, codewordsBits []uti newVal = getMircoQRCodeMaskVal(x, y, srcVal, i) } } - out_.WriteModule(x, y, newVal, pixelSize) + out_.WriteModule(x, y, newVal, pixelSize, part) } } // output group no mask for common - outputGroupOut := func(x int, y int, val bool) { - outputGroupOutMask(x, y, val, false) + outputGroupOut := func(x int, y int, val bool, part cons.QRCodeStructPart) { + outputGroupOutMask(x, y, val, false, part) } // output group with mask for format info - outputGroupFormatMaskOut := func(x int, y int, maskBits map[int][]util.Bit, maskBitIdx int) { + outputGroupFormatMaskOut := func(x int, y int, maskBits map[int][]util.Bit, maskBitIdx int, part cons.QRCodeStructPart) { for i, out_ := range maskOutputGroup { - out_.WriteModule(x, y, maskBits[i][maskBitIdx] == 1, pixelSize) + out_.WriteModule(x, y, maskBits[i][maskBitIdx] == 1, pixelSize, part) } } @@ -435,7 +435,7 @@ func (m *AbstractMode) BuildModuleInMatrixMicroQRCode(qr *QRCodeStruct, codeword maskOutputGroup := newQRCodeMaskOutputGroup(qr.GetMaskCount(), out) // output group with mask for common - outputGroupOutMask := func(x int, y int, val bool, hasMask bool) { + outputGroupOutMask := func(x int, y int, val bool, hasMask bool, part cons.QRCodeStructPart) { srcVal := val for i, out_ := range maskOutputGroup { newVal := srcVal @@ -446,17 +446,17 @@ func (m *AbstractMode) BuildModuleInMatrixMicroQRCode(qr *QRCodeStruct, codeword newVal = getMircoQRCodeMaskVal(x, y, srcVal, i) } } - out_.WriteModule(x, y, newVal, pixelSize) + out_.WriteModule(x, y, newVal, pixelSize, part) } } // output group no mask for common - outputGroupOut := func(x int, y int, val bool) { - outputGroupOutMask(x, y, val, false) + outputGroupOut := func(x int, y int, val bool, part cons.QRCodeStructPart) { + outputGroupOutMask(x, y, val, false, part) } // output group with mask for format info - outputGroupFormatMaskOut := func(x int, y int, maskBits map[int][]util.Bit, maskBitIdx int) { + outputGroupFormatMaskOut := func(x int, y int, maskBits map[int][]util.Bit, maskBitIdx int, part cons.QRCodeStructPart) { for i, out_ := range maskOutputGroup { - out_.WriteModule(x, y, maskBits[i][maskBitIdx] == 1, pixelSize) + out_.WriteModule(x, y, maskBits[i][maskBitIdx] == 1, pixelSize, part) } } @@ -479,12 +479,12 @@ func (m *AbstractMode) BuildModuleInMatrixMicroQRCode(qr *QRCodeStruct, codeword return out } -func drawDarkBlock(version model.VersionId, outputGroupOut func(x int, y int, val bool)) { +func drawDarkBlock(version model.VersionId, outputGroupOut func(x int, y int, val bool, part cons.QRCodeStructPart)) { // Dark Block: All QR codes have a dark module beside the bottom left finder pattern. More specifically, // the dark module is always located at the coordinate ([(4 * V) + 9], 8) where V is the version of the QR code. if version > 0 { //out.WriteModule(model.FINDER_PATTERN_MODULE_SIZE + 1, 4 * version + 9,true,pixelSize) - outputGroupOut(model.FINDER_PATTERN_MODULE_SIZE+1, 4*version+9, true) + outputGroupOut(model.FINDER_PATTERN_MODULE_SIZE+1, 4*version+9, true, cons.FinderPatternPart) } } @@ -494,7 +494,7 @@ func drawDarkBlock(version model.VersionId, outputGroupOut func(x int, y int, va // Near the top-left finder pattern, a one-module strip must be reserved below and to the right of the separator. // Near the top-right finder pattern, a one-module strip must be reserved below the separator. // Near the bottom-left finder pattern, a one-module strip must be reserved to the right of the separator. -func drawFinderPatternAndSeparator(version *model.Version, outputGroupOut func(x int, y int, val bool)) { +func drawFinderPatternAndSeparator(version *model.Version, outputGroupOut func(x int, y int, val bool, part cons.QRCodeStructPart)) { finderPatterns := version.GetFinderPattern() fpModules := finderPatterns.GetModules() separatorLen := model.FINDER_PATTERN_MODULE_SIZE + 1 @@ -503,7 +503,7 @@ func drawFinderPatternAndSeparator(version *model.Version, outputGroupOut func(x for row, bits := range fpModules { for col, bit := range bits { //out.WriteModule(pos.Axes.X+row, pos.Axes.Y + col,bit == 1,pixelSize) - outputGroupOut(pos.Axes.X+row, pos.Axes.Y+col, bit == 1) + outputGroupOut(pos.Axes.X+row, pos.Axes.Y+col, bit == 1, cons.FinderPatternPart) } } // draw separators @@ -523,16 +523,16 @@ func drawFinderPatternAndSeparator(version *model.Version, outputGroupOut func(x } // draw horizontal separators //out.WriteModule(separatorHX + lop,separatorHY ,false,pixelSize) - outputGroupOut(separatorHX+lop, separatorHY, false) + outputGroupOut(separatorHX+lop, separatorHY, false, cons.FinderPatternPart) // draw vertical separators //out.WriteModule(separatorVX ,separatorVY + lop,false,pixelSize) - outputGroupOut(separatorVX, separatorVY+lop, false) + outputGroupOut(separatorVX, separatorVY+lop, false, cons.FinderPatternPart) } } } // drawAlignmentPattern :draw alignment pattern,version 2 or larger must contain alignment pattern. -func drawAlignmentPattern(version *model.Version, pattern *model.AlignmentPattern, outputGroupOut func(x int, y int, val bool)) { +func drawAlignmentPattern(version *model.Version, pattern *model.AlignmentPattern, outputGroupOut func(x int, y int, val bool, part cons.QRCodeStructPart)) { if version.Id < 2 { return } @@ -543,13 +543,13 @@ func drawAlignmentPattern(version *model.Version, pattern *model.AlignmentPatter // pos is alignment center point axes,need transform to left_top point axes. //out.WriteModule(quietZoneSize + pos.X - 2 + row,quietZoneSize + pos.Y - 2+col,bit == 1,pixelSize) //out.WriteModule(pos.X - 2 + row, pos.Y - 2 + col,bit == 1,pixelSize) - outputGroupOut(pos.X-2+row, pos.Y-2+col, bit == 1) + outputGroupOut(pos.X-2+row, pos.Y-2+col, bit == 1, cons.AlignmentPart) } } } } -func drawTimingPattern(timingPattern *model.TimingPattern, moduleSize int, outputGroupOut func(x int, y int, val bool)) { +func drawTimingPattern(timingPattern *model.TimingPattern, moduleSize int, outputGroupOut func(x int, y int, val bool, part cons.QRCodeStructPart)) { //startPos := model.FINDER_PATTERN_MODULE_SIZE // max loop count is moduleSize - 16 //for i:=0; i< moduleSize - model.FINDER_PATTERN_MODULE_SIZE * 2 - 2; i++ { @@ -565,16 +565,16 @@ func drawTimingPattern(timingPattern *model.TimingPattern, moduleSize int, outpu loopLen := h.To.X - h.From.X for i := 0; i < loopLen; i++ { // draw horizontal timing pattern - outputGroupOut(h.From.X+i, h.From.Y, i%2 == 0) + outputGroupOut(h.From.X+i, h.From.Y, i%2 == 0, cons.TimingPatternPart) // draw vertical timing pattern - outputGroupOut(w.From.X, w.From.Y+i, i%2 == 0) + outputGroupOut(w.From.X, w.From.Y+i, i%2 == 0, cons.TimingPatternPart) } } // drawFormatInformation : // Page 63,7.9 Format information. // The format information is a 15-bit sequence containing 5 data bits,with 10 error correction bits calculated using the (15,5) BHC code. -func drawFormatInformation(qr *QRCodeStruct, outputGroupMaskOut func(x int, y int, maskBits map[int][]util.Bit, maskBitIdx int)) { +func drawFormatInformation(qr *QRCodeStruct, outputGroupMaskOut func(x int, y int, maskBits map[int][]util.Bit, maskBitIdx int, part cons.QRCodeStructPart)) { moduleSize := qr.Version.GetModuleSize() version := qr.Version.Id level := qr.ErrorCorrection.Level @@ -586,7 +586,7 @@ func drawFormatInformation(qr *QRCodeStruct, outputGroupMaskOut func(x int, y in } // Draw QRCode format information -func drawQRCodeFormatInformation(level int, moduleSize int, outputGroupMaskOut func(x int, y int, maskBits map[int][]util.Bit, maskBitIdx int)) { +func drawQRCodeFormatInformation(level int, moduleSize int, outputGroupMaskOut func(x int, y int, maskBits map[int][]util.Bit, maskBitIdx int, part cons.QRCodeStructPart)) { formatInfoBits := cons.FormatInformationBitsMap[level] for i := 0; i < 15; i++ { // 0 - 6 @@ -596,21 +596,21 @@ func drawQRCodeFormatInformation(level int, moduleSize int, outputGroupMaskOut f x++ } //out.WriteModule(x, 8 , formatInfoBits[i] == 1 ,pixelSize) - outputGroupMaskOut(x, 8, formatInfoBits, i) + outputGroupMaskOut(x, 8, formatInfoBits, i, cons.FormatPart) if i <= 6 { //out.WriteModule(8, moduleSize - i - 1, formatInfoBits[i] == 1 ,pixelSize) - outputGroupMaskOut(8, moduleSize-i-1, formatInfoBits, i) + outputGroupMaskOut(8, moduleSize-i-1, formatInfoBits, i, cons.FormatPart) } } else { // 7-14 //out.WriteModule(moduleSize - (15 - i), 8 , formatInfoBits[i] == 1 ,pixelSize) - outputGroupMaskOut(moduleSize-(15-i), 8, formatInfoBits, i) + outputGroupMaskOut(moduleSize-(15-i), 8, formatInfoBits, i, cons.FormatPart) y := 15 - i if y <= 6 { y-- } //out.WriteModule(8, y , formatInfoBits[i] == 1 ,pixelSize) - outputGroupMaskOut(8, y, formatInfoBits, i) + outputGroupMaskOut(8, y, formatInfoBits, i, cons.FormatPart) } } } @@ -620,15 +620,15 @@ func drawQRCodeFormatInformation(level int, moduleSize int, outputGroupMaskOut f // The format information is a 15-bit sequence contaning 5 data bits,with 10 error correction bits calculated using the // (15,5) BCH code. The first three data bits contain the symbol number(in binary). which identifies the version // and error correction level, as shown in Table 13. -func drawMicroQRCodeFormatInformation(version model.VersionId, level int, moduleSize int, outputGroupMaskOut func(x int, y int, maskBits map[int][]util.Bit, maskBitIdx int)) { +func drawMicroQRCodeFormatInformation(version model.VersionId, level int, moduleSize int, outputGroupMaskOut func(x int, y int, maskBits map[int][]util.Bit, maskBitIdx int, part cons.QRCodeStructPart)) { var formatInfoBits = cons.MicroQRCodeFormatInformationBitsMap[version][level] for i := 0; i < 15; i++ { if i < 8 { // h: 14 - 7 - outputGroupMaskOut(1+i, model.FINDER_PATTERN_MODULE_SIZE+1, formatInfoBits, i) + outputGroupMaskOut(1+i, model.FINDER_PATTERN_MODULE_SIZE+1, formatInfoBits, i, cons.FormatPart) } else { // w: 0 - 6 - outputGroupMaskOut(model.FINDER_PATTERN_MODULE_SIZE+1, 15-i, formatInfoBits, i) + outputGroupMaskOut(model.FINDER_PATTERN_MODULE_SIZE+1, 15-i, formatInfoBits, i, cons.FormatPart) } } } @@ -651,7 +651,7 @@ func drawMicroQRCodeFormatInformation(version model.VersionId, level int, module // 9 10 11 ... // 12 13 14 // 15 16 17 -func drawVersionInformation(qr *QRCodeStruct, outputGroupOut func(x int, y int, val bool)) { +func drawVersionInformation(qr *QRCodeStruct, outputGroupOut func(x int, y int, val bool, part cons.QRCodeStructPart)) { version := qr.Version.Id if version < 7 { return @@ -662,17 +662,17 @@ func drawVersionInformation(qr *QRCodeStruct, outputGroupOut func(x int, y int, for col := 0; col < 6; col++ { // bottom_left //out.WriteModule(col, moduleSize - 8 - 3 + row , versionInfoBits[ col * 3 + row] == 1 ,pixelSize) - outputGroupOut(col, moduleSize-8-3+row, versionInfoBits[cons.VersionInformationBitsLen-1-(col*3+row)] == 1) + outputGroupOut(col, moduleSize-8-3+row, versionInfoBits[cons.VersionInformationBitsLen-1-(col*3+row)] == 1, cons.VersionPart) // top_right //out.WriteModule(moduleSize - 8 - 3 + row, col , versionInfoBits[ col * 3 + row] == 1 ,pixelSize) - outputGroupOut(moduleSize-8-3+row, col, versionInfoBits[cons.VersionInformationBitsLen-1-(col*3+row)] == 1) + outputGroupOut(moduleSize-8-3+row, col, versionInfoBits[cons.VersionInformationBitsLen-1-(col*3+row)] == 1, cons.VersionPart) } } } // drawData : draw data and set mask. // Mask rule in Page 58,7.8 Data Masking. -func drawData(version *model.Version, moduleSize int, codewordsBits []util.Bit, out output.Output, outputGroupOutMask func(x int, y int, val bool, hasMask bool)) { +func drawData(version *model.Version, moduleSize int, codewordsBits []util.Bit, out output.Output, outputGroupOutMask func(x int, y int, val bool, hasMask bool, part cons.QRCodeStructPart)) { var moduleBitIdx int for pos := range iterateModulesPlacement(version, moduleSize, out.IsModuleSet) { var bit bool @@ -680,7 +680,7 @@ func drawData(version *model.Version, moduleSize int, codewordsBits []util.Bit, bit = codewordsBits[moduleBitIdx] == 1 } //out.WriteModule(pos.X ,pos.Y ,bit,pixelSize) - outputGroupOutMask(pos.X, pos.Y, bit, true) + outputGroupOutMask(pos.X, pos.Y, bit, true, cons.DataPart) moduleBitIdx++ } } diff --git a/core/mode/numeric_mode_test.go b/core/mode/numeric_mode_test.go index 9125152..4f8c361 100644 --- a/core/mode/numeric_mode_test.go +++ b/core/mode/numeric_mode_test.go @@ -11,47 +11,49 @@ import ( "strconv" "testing" ) + var home = os.Getenv("HOME") -var desktop = home+"/Desktop/gqrcode/" +var desktop = home + "/Desktop/gqrcode/" + func TestImageToImg(t *testing.T) { - img1 := image.NewRGBA(image.Rect(0,0,10,10)) - for i:=0;i<10;i++{ - for j:=0;j<10;j++{ - img1.Set(i,j,image.Black) + img1 := image.NewRGBA(image.Rect(0, 0, 10, 10)) + for i := 0; i < 10; i++ { + for j := 0; j < 10; j++ { + img1.Set(i, j, image.Black) } } - file1,_:=os.Create(desktop+"img.png") + file1, _ := os.Create(desktop + "img.png") defer file1.Close() - png.Encode(file1,img1) + png.Encode(file1, img1) - img2 := image.NewRGBA(image.Rect(0,0,100,100)) + img2 := image.NewRGBA(image.Rect(0, 0, 100, 100)) draw.Draw(img2, img2.Bounds(), &image.Uniform{C: image.White}, image.ZP, draw.Src) //(0,0)-(10,10) blue draw.Draw(img2, - image.Rectangle{image.ZP,image.Point{X: 10, Y: 10}}, - &image.Uniform{C: color.RGBA{0,0,255,255}}, image.ZP, draw.Src) + image.Rectangle{image.ZP, image.Point{X: 10, Y: 10}}, + &image.Uniform{C: color.RGBA{0, 0, 255, 255}}, image.ZP, draw.Src) //(10,10)-(20,20) black - r:= image.Rectangle{Min: image.Point{X: 10, Y: 10}, Max: image.Point{X: 20, Y: 20}} - draw.Draw(img2,r,img1,image.Pt(0,0), draw.Src) + r := image.Rectangle{Min: image.Point{X: 10, Y: 10}, Max: image.Point{X: 20, Y: 20}} + draw.Draw(img2, r, img1, image.Pt(0, 0), draw.Src) - file2,_:=os.Create(desktop+"img2.png") + file2, _ := os.Create(desktop + "img2.png") defer file2.Close() - png.Encode(file2,img2) + png.Encode(file2, img2) } // See qrcode_test.go func TestNumericNewQRCode(t *testing.T) { } -func TestBoolDefaultVal(t *testing.T){ +func TestBoolDefaultVal(t *testing.T) { var def bool - init:=false - fmt.Println("default:"+ strconv.FormatBool( reflect.ValueOf(def).IsValid())) + init := false + fmt.Println("default:" + strconv.FormatBool(reflect.ValueOf(def).IsValid())) fmt.Printf("default:%v\n", reflect.ValueOf(def).Kind()) fmt.Printf("default:%v\n", reflect.ValueOf(def).IsZero()) - fmt.Println("init:"+ strconv.FormatBool(reflect.ValueOf(init).IsValid())) + fmt.Println("init:" + strconv.FormatBool(reflect.ValueOf(init).IsValid())) fmt.Printf("init:%v\n", reflect.ValueOf(init).Kind()) fmt.Printf("init:%v\n", reflect.ValueOf(init).IsZero()) -} \ No newline at end of file +} diff --git a/core/mode/qrcodestruct.go b/core/mode/qrcodestruct.go index 1f63efe..778dce9 100644 --- a/core/mode/qrcodestruct.go +++ b/core/mode/qrcodestruct.go @@ -2,9 +2,7 @@ package mode import ( "errors" - "fmt" "github.com/KangSpace/gqrcode/core/cons" - "github.com/KangSpace/gqrcode/core/logger" "github.com/KangSpace/gqrcode/core/model" "github.com/KangSpace/gqrcode/core/output" "io" @@ -139,7 +137,7 @@ func (qr *QRCodeStruct) EncodeToBase64(out output.Output) (base64Str string, err } func (qr *QRCodeStruct) innerEncode(out output.Output) (out_ output.Output, err error) { - defer func() { + /*defer func() { if rec := recover(); rec != nil { switch x := rec.(type) { case string: @@ -151,7 +149,7 @@ func (qr *QRCodeStruct) innerEncode(out output.Output) (out_ output.Output, err } logger.Error(err) } - }() + }()*/ return qr.buildQRCode(out), nil } diff --git a/core/mode/structuredappend_mode.go b/core/mode/structuredappend_mode.go index 64ab346..1bce3b3 100644 --- a/core/mode/structuredappend_mode.go +++ b/core/mode/structuredappend_mode.go @@ -11,9 +11,8 @@ package mode // 1. Structured Append mode is not available for Micro QR Code Symbol. // - type StructuredAppend struct { *AbstractMode } -// TODO NOT IMPLEMENT \ No newline at end of file +// TODO NOT IMPLEMENT diff --git a/core/model/separator.go b/core/model/separator.go index d524ed0..4c146e0 100644 --- a/core/model/separator.go +++ b/core/model/separator.go @@ -2,8 +2,5 @@ package model // Define Separator here - type Separator struct { - } - diff --git a/core/model/timingpattern.go b/core/model/timingpattern.go index e58bf06..bfcc0b4 100644 --- a/core/model/timingpattern.go +++ b/core/model/timingpattern.go @@ -8,8 +8,8 @@ type TimingPattern struct { W *PositionAxesRange } -func NewTimingPattern(version *Version) *TimingPattern{ - timingPattern := new(TimingPattern) +func NewTimingPattern(version *Version) *TimingPattern { + timingPattern := new(TimingPattern) positions := timingPattern.GetTimingPatternPositions(version) timingPattern.H = positions[0] timingPattern.W = positions[1] @@ -17,25 +17,25 @@ func NewTimingPattern(version *Version) *TimingPattern{ } // GetTimingPatternPositions :Get timing pattern positions for specified version -func (tp *TimingPattern) GetTimingPatternPositions(version *Version) []*PositionAxesRange{ +func (tp *TimingPattern) GetTimingPatternPositions(version *Version) []*PositionAxesRange { versionId := version.Id - positionAxesRange := make([]*PositionAxesRange,0,2) + positionAxesRange := make([]*PositionAxesRange, 0, 2) moduleSize := version.GetModuleSize() p1 := FINDER_PATTERN_MODULE_SIZE + 1 p2 := FINDER_PATTERN_MODULE_SIZE - 1 - p3 := moduleSize - FINDER_PATTERN_MODULE_SIZE -1 - if versionId < 0{ + p3 := moduleSize - FINDER_PATTERN_MODULE_SIZE - 1 + if versionId < 0 { // Micro QRCode Timing Pattern // Horizontal timing pattern. - positionAxesRange = append(positionAxesRange,&PositionAxesRange{From:&PositionAxes{X: p1 ,Y: 0},To:&PositionAxes{X:moduleSize,Y: 0} }) + positionAxesRange = append(positionAxesRange, &PositionAxesRange{From: &PositionAxes{X: p1, Y: 0}, To: &PositionAxes{X: moduleSize, Y: 0}}) // vertical timing pattern. - positionAxesRange = append(positionAxesRange,&PositionAxesRange{From:&PositionAxes{X:0,Y:p1},To:&PositionAxes{X:0, Y:moduleSize} }) - }else{ + positionAxesRange = append(positionAxesRange, &PositionAxesRange{From: &PositionAxes{X: 0, Y: p1}, To: &PositionAxes{X: 0, Y: moduleSize}}) + } else { // QRCode Timing Pattern // Horizontal timing pattern. - positionAxesRange = append(positionAxesRange,&PositionAxesRange{From:&PositionAxes{X: p1 ,Y: p2},To:&PositionAxes{X:p3,Y: p2} }) + positionAxesRange = append(positionAxesRange, &PositionAxesRange{From: &PositionAxes{X: p1, Y: p2}, To: &PositionAxes{X: p3, Y: p2}}) // vertical timing pattern. - positionAxesRange = append(positionAxesRange,&PositionAxesRange{From:&PositionAxes{X:p2,Y:p1},To:&PositionAxes{X:p2, Y:p3} }) + positionAxesRange = append(positionAxesRange, &PositionAxesRange{From: &PositionAxes{X: p2, Y: p1}, To: &PositionAxes{X: p2, Y: p3}}) } return positionAxesRange -} \ No newline at end of file +} diff --git a/core/output/image_output.go b/core/output/image_output.go index 88a4d7f..8720ebe 100644 --- a/core/output/image_output.go +++ b/core/output/image_output.go @@ -3,6 +3,7 @@ package output import ( "bytes" "errors" + "github.com/KangSpace/gqrcode/core/cons" "github.com/KangSpace/gqrcode/core/model" "github.com/KangSpace/gqrcode/util" "github.com/KangSpace/gqrcode/util/imaging" @@ -83,22 +84,39 @@ func (out *ImageOutput) Init(version *model.Version, qz *model.QuietZone) { // Write : write data func (out *ImageOutput) Write(x int, y int, black bool) { - setColor := out.getWriteColor(black) + setColor := out.getWriteColor(black, cons.DataPart) out.image.Set(x, y, setColor) out.modules[x][y] = &black } // WriteModule : write data -func (out *ImageOutput) WriteModule(x int, y int, black bool, pixelSize int) { - setColor := out.getWriteColor(black) +func (out *ImageOutput) WriteModule(x int, y int, black bool, pixelSize int, part cons.QRCodeStructPart) { + setColor := out.getWriteColor(black, part) out.WriteModuleColor(x, y, black, setColor, pixelSize) } // getWriteColor: get color by BaseOutput.CodeColor -func (out *ImageOutput) getWriteColor(black bool) color.Color { +func (out *ImageOutput) getWriteColor(black bool, part cons.QRCodeStructPart) color.Color { if black { if out.BaseOutput.CodeColor.DataColor != nil { - return out.BaseOutput.CodeColor.DataColor + var color = image.Black.C + switch part { + case cons.DataPart: + color = out.BaseOutput.CodeColor.DataColor + case cons.FinderPatternPart: + color = out.BaseOutput.CodeColor.FinderPatternColor + case cons.AlignmentPart: + color = out.BaseOutput.CodeColor.AlignmentPatternColor + case cons.QuietZonePart: + color = out.BaseOutput.CodeColor.QuietZoneColor + case cons.TimingPatternPart: + color = out.BaseOutput.CodeColor.TimingPatternColor + case cons.FormatPart: + color = out.BaseOutput.CodeColor.FormatColor + case cons.VersionPart: + color = out.BaseOutput.CodeColor.VersionColor + } + return color } return image.Black.C } diff --git a/core/output/output.go b/core/output/output.go index b5cbedb..714e7d4 100644 --- a/core/output/output.go +++ b/core/output/output.go @@ -1,6 +1,7 @@ package output import ( + "github.com/KangSpace/gqrcode/core/cons" "github.com/KangSpace/gqrcode/core/model" "image" "image/color" @@ -44,24 +45,34 @@ type BaseOutput struct { // CodeColor color for qrcode type CodeColor struct { - AlignmentColor color.Color - TimingPatternColor color.Color - QuietZoneColor color.Color - DataColor color.Color + FinderPatternColor color.Color + AlignmentPatternColor color.Color + TimingPatternColor color.Color + QuietZoneColor color.Color + DataColor color.Color + FormatColor color.Color + VersionColor color.Color } // var ( + BlackColor = image.Black + BlueColor = color.NRGBA{0, 127, 255, 255} + RedCode = color.NRGBA{255, 82, 25, 255} + OrangeCode = color.NRGBA{255, 146, 0, 255} + GreenCode = color.NRGBA{0, 176, 66, 255} // DefaultCodeColor default color is black for QRCode - DefaultCodeColor = CodeColor{image.Black, image.Black, image.White, image.Black} + DefaultCodeColor = CodeColor{BlackColor, BlackColor, BlackColor, image.White, BlackColor, BlackColor, BlackColor} // BlueCodeColor #007FFF/rgba(0,127,255,1) - BlueCodeColor = CodeColor{color.RGBA{0, 127, 255, 1}, color.RGBA{0, 127, 255, 1}, image.White, color.RGBA{0, 127, 255, 1}} + BlueCodeColor = CodeColor{BlueColor, BlueColor, BlueColor, image.White, BlueColor, BlueColor, BlueColor} // RedCodeColor #FF5219/rgba(255,82,25,1) - RedCodeColor = CodeColor{color.RGBA{255, 82, 25, 1}, color.RGBA{255, 82, 25, 1}, image.White, color.RGBA{255, 82, 25, 1}} + RedCodeColor = CodeColor{RedCode, RedCode, RedCode, image.White, RedCode, RedCode, RedCode} // OrangeCodeColor #FF9200/rgba(255,146,0,1) - OrangeCodeColor = CodeColor{color.RGBA{255, 146, 0, 1}, color.RGBA{255, 146, 0, 1}, image.White, color.RGBA{255, 146, 0, 1}} + OrangeCodeColor = CodeColor{OrangeCode, OrangeCode, OrangeCode, image.White, OrangeCode, OrangeCode, OrangeCode} // GreenCodeColor #00B042/rgba(0,176,66,1) - GreenCodeColor = CodeColor{color.RGBA{0, 176, 66, 1}, color.RGBA{0, 176, 66, 1}, image.White, color.RGBA{0, 176, 66, 1}} + GreenCodeColor = CodeColor{GreenCode, GreenCode, GreenCode, image.White, GreenCode, GreenCode, GreenCode} + // ColorfulCodeColor MultiColor for QRCodeStruct Part + ColorfulCodeColor = CodeColor{DefaultCodeColor.DataColor, RedCodeColor.DataColor, GreenCodeColor.DataColor, image.White, BlueCodeColor.DataColor, OrangeCodeColor.DataColor, DefaultCodeColor.DataColor} ) // LogoOption : Option for add logo image at center of QRCode @@ -98,7 +109,7 @@ type Output interface { Init(version *model.Version, qz *model.QuietZone) Write(x int, y int, black bool) // WriteModule :write per module by pixelSize - WriteModule(x int, y int, black bool, pixelSize int) + WriteModule(x int, y int, black bool, pixelSize int, part cons.QRCodeStructPart) WriteModuleColor(x int, y int, dark bool, setColor color.Color, pixelSize int) // IsModuleSet : check the module whether or not be set IsModuleSet(x int, y int) bool diff --git a/doc/images/qr/byte_colorful_200x200.png b/doc/images/qr/byte_colorful_200x200.png new file mode 100644 index 0000000000000000000000000000000000000000..647f2957377eb09b57431df364770a44a74cb481 GIT binary patch literal 1256 zcmeAS@N?(olHy`uVBq!ia0vp^CqS5k2}mkgS)OEIU|H|!;uumf=gr-N7jL^rG(4Q) z$v($}|7D|G5WDRX_E!tos}`_ZENz?5y#2}PGhJ7;Z+@^jUN3Vq?B2zmYpd^m&(F_) z{~*Wy&R@nK`9flxi4z5I5f%IYT{`|aux`@fYtK_{?EL@N{CXVA{^yM!Km+_jv)BMBv>I++jip8xjy z=bP{I_x-*7`1FrUFJGTA7TH(#v_eTPzRmvp@*J6FiTgiP&;2}t=5m=E>kDFL|G%4m z`PQGu+T}gPV$ASn1i!PhW-$VB0kw($Ke*0(dc*g!X$?nIpv-8jU*H62z{A~{pa(dhG!uCA@Th z@wM~A;-p32U*_+vyjNCnWL~-oa^gCv{H=Tce0c$#d*#3E_vZ;8-rWCEusW^{C1q92 zcyz$={JztB%gYY`jAs1z@!@^>j}x}OGJyp$aw*n(b%u$MZ}9e{PM7kS=&hDw9=flHx55KrfcJl7DGxi z?|#U+mTo@h-yN4t3l2Z|vOZbaXWm43K)Do!S3Fh_pDoz{Qv87DC_#?62$ z0Or;=eC9T{*D;yr-QHez;HzOr(w0NOh%-QrIExP*wrh&f+=wU)psbJOz(VW)|9KA_ VEax>Yn+D`Cc)I$ztaD0e0sy&}O%(tD literal 0 HcmV?d00001 diff --git a/doc/images/qr/byte_colorful_400x400.png b/doc/images/qr/byte_colorful_400x400.png new file mode 100644 index 0000000000000000000000000000000000000000..c6d002dacab205671520805c7d89cd9e828e1d94 GIT binary patch literal 2193 zcmb_ee=yr;7!TKqQ<2>aT^GMj&E49OBX4y2)AQyFc=IG{eILZFql*2{&977WRO!2zJtMB6QZLc;&Oy5QxTa{A9&xI{qmXn zugBQvVwD`<9f zD{8K}O&LbuLyx=j+bEKjk8?Am`kmZ5a|f3Rv5Es8ec;jZJ)-r(de!As4XqfS%`ejH#<97b)8X3%rgZWcFqmi8LVV>u1!L8|TD|CDPd?`)c{Y)26Z&-ktaII4 zU583~*L*28Iqzzh_A0aq(5VX}#@y`Ww}Hdwz1?Hm`>Xl(pMzZj2P;r^!a%HfeBQ4D zmtfbfv@CizUHKZC8V=FY?~kIdXWuaI7+kotks#R+{8A%Ma^GlerC(HRl&JxW$X`;0 zB;YyS5E+fh$e*5F$QUH8+fyJ#r%_PgGRA_ChVj}#{ZW^{&AABKNV3rHH+j3 zth&ulw@jw3x(1pQ(jylY`>UDK$ho&{#89k(b^sZZOdw0y^;{m-W{tBoc&@E?QSGKI{g1l~Nykk)5r&5I>IbQ9$e<#|q0KfKH7V&7WK*t7~J` zIm2nUUnQ}`)D}a9meODc9rJHGv-^JeE^Q4IW T?c=nEjsO--jfrZ0FXi@Mn22Gm literal 0 HcmV?d00001 diff --git a/test/qrcode_test.go b/test/qrcode_test.go index d3b7131..b4f08d1 100644 --- a/test/qrcode_test.go +++ b/test/qrcode_test.go @@ -373,12 +373,15 @@ func TestByteQRCode(t *testing.T) { t.Fatal(err) } } + +// TestByteQRCodeWithColor :Test byte(IOS-8859-1) QRCode func TestByteQRCodeWithColor(t *testing.T) { - data := "https://kangspace.org" + //data := "https://kangspace.org" + data := "是你让我看透生命这东西,四个字“坚持到底”……看那扑翅的飞蛾,不顾一切地朝着灯光的方向扑去;看那缓缓的蜗牛,不变地朝着一个目标“金字塔顶”而坚持。\n  李白看到了“只要功夫深铁杵磨成针”他成为了诗之仙,文飞剑舞。\n  司马迁懂得生死如鸿毛、如泰山,沿着泰山攀爬,才能成就大事业。正应了那句“世上无难事,只要肯攀登”,他成就了那部伟大的《史记》,汗青留名,永垂不朽。\n  爱迪生,仅发明灯泡就让他失败了3000多次。然而,他没有放弃,宁愿“在大海中捞针”,也要坚持不懈。最终,他成功了,他的名字同“光明”刻在了一起。就是一样的精神,使它成为了发明大王。\n  库提斯,仅有上半身,而当你看到他是怎样幸福地生活、怎样灵巧地行走、怎样地游着滑板到演讲台上时,你便会知道一个强壮、坚强、执着、顽强的励志大师是可以这样成功的。\n  古今中外,名人志士、成功人士,有多少的人共同验证着这样一句话:“成功就是坚持到底”。路是人走出来的,没有比脚更长的路。坚持沿着自己的路走下去,便会有意想不到的成功、收获。\n  眺望远方,因为有梦想,所以追求。流水潺潺,水滴石穿。人生有道,天道酬勤。骐骥一跃,不能十步;驽马十驾,功在不舍。锲而舍之,朽木不折;锲而不舍,金石可镂。将执着的追求进行到底,没有比脚更长的路。" fmt.Println(len(data)) fileNamePrefix := "byte_color" - fileName := gqrcodePath + fileNamePrefix + ".gif" - out := output.NewOutput(&output.BaseOutput{Type: output.PNG, Size: 400, CodeColor: output.BlueCodeColor}) + fileName := gqrcodePath + fileNamePrefix + ".png" + out := output.NewOutput(&output.BaseOutput{Type: output.PNG, Size: 800, CodeColor: output.ColorfulCodeColor}) qrcode, err := gqrcode.NewQRCodeAutoQuiet(data) if err != nil { t.Fatal(err) diff --git a/util/datastream.go b/util/datastream.go index 2372e1c..63ede3c 100644 --- a/util/datastream.go +++ b/util/datastream.go @@ -5,68 +5,71 @@ type Bit = byte // Module : use byte to represent symbol module. value is 0/1 type Module = byte + // Define Data Stream here type DataStream struct { count int - data []Bit + data []Bit } -func NewDataStream(capacity int) *DataStream{ - data:= make([]byte,capacity) +func NewDataStream(capacity int) *DataStream { + data := make([]byte, capacity) ds := new(DataStream) ds.data = data ds.count = 0 return ds } -func (ds *DataStream) GetCount() int{ +func (ds *DataStream) GetCount() int { return ds.count } -func (ds *DataStream) GetData() []Bit{ +func (ds *DataStream) GetData() []Bit { return ds.data[:ds.count] } -func (ds *DataStream) AddBit(b []Bit ,count int){ +func (ds *DataStream) AddBit(b []Bit, count int) { bLen := len(b) if bLen == 0 && count == 0 { return } ds.autoGrow(count) - if bLen 0 && i 0 && i < bitsCount; i += bitLen { max := i + bitLen - if max > bitsCount{ + if max > bitsCount { max = bitsCount bitLen = max - i } - byteOutChan <- BitsToByte(ds.data[i:max],bitLen) + byteOutChan <- BitsToByte(ds.data[i:max], bitLen) } close(byteOutChan) }() return byteOutChan } -func (ds *DataStream) pushInData(bs []byte){ - for _,b := range bs { +func (ds *DataStream) pushInData(bs []byte) { + for _, b := range bs { ds.data[ds.count] = b ds.count++ } @@ -102,22 +105,22 @@ func (ds *DataStream) pushInData(bs []byte){ func (ds *DataStream) autoGrow(count int) { currentDataLength := len(ds.data) if currentDataLength < ds.count+count { - ds.grow(ds.count+count-currentDataLength) + ds.grow(ds.count + count - currentDataLength) } } // grow up the data capacity of DataStream func (ds *DataStream) grow(growBy int) { currentLength := len(ds.data) - if growBy == 0{ + if growBy == 0 { growBy = currentLength if growBy < 128 { growBy = 128 } else if growBy >= 1024 { growBy = 1024 } - }else { - if growBy / 2 >0 { + } else { + if growBy/2 > 0 { growBy = growBy + 1 } } diff --git a/util/datastream_test.go b/util/datastream_test.go index af36098..dd0a4ff 100644 --- a/util/datastream_test.go +++ b/util/datastream_test.go @@ -7,13 +7,13 @@ import ( func TestNewDataStream(t *testing.T) { nds := NewDataStream(10) - fmt.Println("new nds: ",&nds) - bBits:= []byte{1,1,1,1} - nds.AddBit(&bBits,len(bBits)) + fmt.Println("new nds: ", &nds) + bBits := []byte{1, 1, 1, 1} + nds.AddBit(bBits, len(bBits)) //0b101 i := 5 count := 5 - nds.AddIntBit(i,count) - fmt.Println("final nds: ",&nds," ",nds) - fmt.Println("final nds data: ",nds.GetData()) + nds.AddIntBit(i, count) + fmt.Println("final nds: ", &nds, " ", nds) + fmt.Println("final nds data: ", nds.GetData()) } diff --git a/util/util.go b/util/util.go index b9a3245..7d0be30 100644 --- a/util/util.go +++ b/util/util.go @@ -193,6 +193,18 @@ func IteratorTwoByte(data string) <-chan uint16 { return twoByteChain } +// IteratorStringByte : iterate by rune +func IteratorStringByte(data string) <-chan rune { + byteChain := make(chan rune) + go func() { + for _, char := range data { + byteChain <- char + } + close(byteChain) + }() + return byteChain +} + func IteratorTwoByteEach(data string) <-chan []uint16 { dataLen := len(data) if dataLen%2 > 0 { diff --git a/util/util_test.go b/util/util_test.go index ebc9caa..8d308be 100644 --- a/util/util_test.go +++ b/util/util_test.go @@ -7,22 +7,21 @@ import ( func TestIntToBinaryArray(t *testing.T) { defer catchPanic(t) - is := []int{1,2,3,4,10,11,12,13,14,15,16,0,-1,67} - for _,i:=range is{ + is := []int{1, 2, 3, 4, 10, 11, 12, 13, 14, 15, 16, 0, -1, 67} + for _, i := range is { bs := IntTo8BitArray(i) - fmt.Println(i," binary: ",bs) + fmt.Println(i, " binary: ", bs) } fmt.Println("SUCCESS") } - func TestIntTo8BitArray(t *testing.T) { defer catchPanic(t) - is := []int{1,2,3,4,10,11,12,13,14,15,16,0,-1,67,255,257} - for _,i:=range is{ + is := []int{1, 2, 3, 4, 10, 11, 12, 13, 14, 15, 16, 0, -1, 67, 255, 257} + for _, i := range is { bs := IntTo8BitArray(i) - fmt.Println(i," binary: ",bs) + fmt.Println(i, " binary: ", bs) } fmt.Println("SUCCESS") @@ -30,19 +29,19 @@ func TestIntTo8BitArray(t *testing.T) { func TestBitsToByte(t *testing.T) { defer catchPanic(t) - bitArray1 := []byte{0,0,0,0,0,0,0,1} + bitArray1 := []byte{0, 0, 0, 0, 0, 0, 0, 1} bitArray10 := IntTo8BitArray(10) bitArray255 := IntTo8BitArray(255) - fmt.Println(bitArray1,"from 1 to :",Bits8ToByte(bitArray1)) - fmt.Println(bitArray10,"from 10 to :",Bits8ToByte(bitArray10)) - fmt.Println(bitArray255,"from 255 to :",Bits8ToByte(bitArray255)) + fmt.Println(bitArray1, "from 1 to :", Bits8ToByte(bitArray1)) + fmt.Println(bitArray10, "from 10 to :", Bits8ToByte(bitArray10)) + fmt.Println(bitArray255, "from 255 to :", Bits8ToByte(bitArray255)) } func TestTemp1(t *testing.T) { fmt.Println(byte(1)) } -func catchPanic(t *testing.T){ +func catchPanic(t *testing.T) { if err_ := recover(); err_ != nil { //err = errors.New(err_.(string)) //fmt.Println("err:",reflect.TypeOf(err_)) @@ -52,4 +51,4 @@ func catchPanic(t *testing.T){ fmt.Print(err_) t.Fail() } -} \ No newline at end of file +}