diff --git a/.bettercodehub.yml b/.bettercodehub.yml new file mode 100644 index 0000000..69138f3 --- /dev/null +++ b/.bettercodehub.yml @@ -0,0 +1,4 @@ +exclude: +- /cmd/zplgfa/.* +languages: +- go \ No newline at end of file diff --git a/.gitignore b/.gitignore index 99e2e24..bdf5dfe 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ *.zpl cmd/zplgfa/*.png cmd/zplgfa/zplgfa +zplgfa.coverprofile +coverage.html +test.zpl.bin* diff --git a/cmd/zplgfa/README.md b/cmd/zplgfa/README.md index 4aaf30e..0c97448 100644 --- a/cmd/zplgfa/README.md +++ b/cmd/zplgfa/README.md @@ -17,6 +17,12 @@ So if your image file is `label.png` and the IP of your printer is `192.168.178. zplgfa -file label.png | nc 192.168.178.42 9100 ``` +or via the integrated network capability: + +```sh +zplgfa -file label.png -ip 192.168.178.42 +``` + You can also use some effects, e.g. blur: ```sh diff --git a/cmd/zplgfa/image.go b/cmd/zplgfa/image.go new file mode 100644 index 0000000..cb47185 --- /dev/null +++ b/cmd/zplgfa/image.go @@ -0,0 +1,49 @@ +package main + +import ( + "image" + "image/color" + "math" +) + +type imageSet interface { + Set(x, y int, c color.Color) +} + +func editImageInvert(img image.Image) image.Image { + b := img.Bounds() + + imgSet := img.(imageSet) + for y := b.Min.Y; y < b.Max.Y; y++ { + for x := b.Min.X; x < b.Max.X; x++ { + oldPixel := img.At(x, y) + r, g, b, a := oldPixel.RGBA() + r = 65535 - r + g = 65535 - g + b = 65535 - b + pixel := color.RGBA{uint8(r), uint8(g), uint8(b), uint8(a)} + imgSet.Set(x, y, pixel) + } + } + return img +} + +func editImageMonochrome(img image.Image) image.Image { + b := img.Bounds() + + imgSet := img.(imageSet) + for y := b.Min.Y; y < b.Max.Y; y++ { + for x := b.Min.X; x < b.Max.X; x++ { + oldPixel := img.At(x, y) + r, g, b, a := oldPixel.RGBA() + if r > math.MaxUint16/2 || g > math.MaxUint16/2 || b > math.MaxUint16/2 { + r, g, b = 65535, 65535, 65535 + } else { + r, g, b = 0, 0, 0 + } + pixel := color.RGBA{uint8(r), uint8(g), uint8(b), uint8(a)} + imgSet.Set(x, y, pixel) + } + } + return img +} diff --git a/cmd/zplgfa/main.go b/cmd/zplgfa/main.go index 289a3d2..86dc3fb 100644 --- a/cmd/zplgfa/main.go +++ b/cmd/zplgfa/main.go @@ -4,12 +4,10 @@ import ( "flag" "fmt" "image" - "image/color" _ "image/gif" _ "image/jpeg" _ "image/png" "log" - "math" "os" "strings" @@ -23,19 +21,47 @@ import ( func main() { var filenameFlag string + var zebraCmdFlag string var graphicTypeFlag string var imageEditFlag string + var networkIpFlag string + var networkPortFlag string var imageResizeFlag float64 var graphicType zplgfa.GraphicType + var cmdSent bool flag.StringVar(&filenameFlag, "file", "", "filename to convert to zpl") + flag.StringVar(&zebraCmdFlag, "cmd", "", "send special command to printer [calib,feed]") flag.StringVar(&graphicTypeFlag, "type", "CompressedASCII", "type of graphic field encoding") flag.StringVar(&imageEditFlag, "edit", "", "manipulate the image [invert,monochrome]") + flag.StringVar(&networkIpFlag, "ip", "", "send zpl to printer") + flag.StringVar(&networkPortFlag, "port", "9100", "network port of printer") flag.Float64Var(&imageResizeFlag, "resize", 1.0, "zoom/resize the image") // load flag input arguments flag.Parse() + // send special commands to printer + if strings.Contains(zebraCmdFlag, "calib") && networkIpFlag != "" { + if err := sendCalibCmdToZebra(networkIpFlag, networkPortFlag); err == nil { + cmdSent = true + } + } + if strings.Contains(zebraCmdFlag, "feed") && networkIpFlag != "" { + if err := sendFeedCmdToZebra(networkIpFlag, networkPortFlag); err == nil { + cmdSent = true + } + } + + // check input parameter + if filenameFlag == "" { + if cmdSent { + return + } + log.Printf("Warning: no input file specified\n") + return + } + // open file file, err := os.Open(filenameFlag) if err != nil { @@ -43,6 +69,7 @@ func main() { return } + // close file when complete defer file.Close() // load image head information @@ -62,28 +89,31 @@ func main() { } // select graphic field type - switch graphicTypeFlag { + switch strings.ToUpper(graphicTypeFlag) { case "ASCII": graphicType = zplgfa.ASCII - case "Binary": + case "BINARY": graphicType = zplgfa.Binary - case "CompressedASCII": + case "COMPRESSEDASCII": graphicType = zplgfa.CompressedASCII default: graphicType = zplgfa.CompressedASCII } // apply image manipulation functions - switch { - case strings.Contains(imageEditFlag, "monochrome"): + if strings.Contains(imageEditFlag, "monochrome") { img = editImageMonochrome(img) - case strings.Contains(imageEditFlag, "blur"): + } + if strings.Contains(imageEditFlag, "blur") { img = blur.Gaussian(img, float64(config.Width)/300) - case strings.Contains(imageEditFlag, "edge"): + } + if strings.Contains(imageEditFlag, "edge") { img = effect.Sobel(img) - case strings.Contains(imageEditFlag, "segment"): + } + if strings.Contains(imageEditFlag, "segment") { img = segment.Threshold(img, 128) - case strings.Contains(imageEditFlag, "invert"): + } + if strings.Contains(imageEditFlag, "invert") { img = editImageInvert(img) } @@ -98,48 +128,11 @@ func main() { // convert image to zpl compatible type gfimg := zplgfa.ConvertToZPL(flat, graphicType) - // output zpl with graphic field date to stdout - fmt.Println(gfimg) -} - -type imageSet interface { - Set(x, y int, c color.Color) -} - -func editImageInvert(img image.Image) image.Image { - b := img.Bounds() - - imgSet := img.(imageSet) - for y := b.Min.Y; y < b.Max.Y; y++ { - for x := b.Min.X; x < b.Max.X; x++ { - oldPixel := img.At(x, y) - r, g, b, a := oldPixel.RGBA() - r = 65535 - r - g = 65535 - g - b = 65535 - b - pixel := color.RGBA{uint8(r), uint8(g), uint8(b), uint8(a)} - imgSet.Set(x, y, pixel) - } + if networkIpFlag != "" { + // send zpl to printer + sendDataToZebra(networkIpFlag, networkPortFlag, gfimg) + } else { + // output zpl with graphic field data to stdout + fmt.Println(gfimg) } - return img -} - -func editImageMonochrome(img image.Image) image.Image { - b := img.Bounds() - - imgSet := img.(imageSet) - for y := b.Min.Y; y < b.Max.Y; y++ { - for x := b.Min.X; x < b.Max.X; x++ { - oldPixel := img.At(x, y) - r, g, b, a := oldPixel.RGBA() - if r > math.MaxUint16/2 || g > math.MaxUint16/2 || b > math.MaxUint16/2 { - r, g, b = 65535, 65535, 65535 - } else { - r, g, b = 0, 0, 0 - } - pixel := color.RGBA{uint8(r), uint8(g), uint8(b), uint8(a)} - imgSet.Set(x, y, pixel) - } - } - return img } diff --git a/cmd/zplgfa/network.go b/cmd/zplgfa/network.go new file mode 100644 index 0000000..968c384 --- /dev/null +++ b/cmd/zplgfa/network.go @@ -0,0 +1,27 @@ +package main + +import ( + "fmt" + "net" +) + +func sendDataToZebra(ip, port, str string) error { + tcpAddr, err := net.ResolveTCPAddr("tcp", ip+":"+port) + conn, err := net.DialTCP("tcp4", nil, tcpAddr) + if err == nil { + defer conn.Close() + + payloadBytes := []byte(fmt.Sprintf("%s\r\n\r\n", str)) + _, err = conn.Write(payloadBytes) + return err + } + return err +} + +func sendFeedCmdToZebra(ip, port string) error { + return sendDataToZebra(ip, port, "^xa^aa^fd ^fs^xz") +} + +func sendCalibCmdToZebra(ip, port string) error { + return sendDataToZebra(ip, port, "~jc^xa^jus^xz") +} diff --git a/tests/test10.gif b/tests/test10.gif new file mode 100644 index 0000000..61d8c42 Binary files /dev/null and b/tests/test10.gif differ diff --git a/tests/test11.gif b/tests/test11.gif new file mode 100644 index 0000000..90e22d2 Binary files /dev/null and b/tests/test11.gif differ diff --git a/tests/test12.gif b/tests/test12.gif new file mode 100644 index 0000000..071259c Binary files /dev/null and b/tests/test12.gif differ diff --git a/tests/test8.jpg b/tests/test8.jpg new file mode 100644 index 0000000..f2cba55 Binary files /dev/null and b/tests/test8.jpg differ diff --git a/tests/test9.jpg b/tests/test9.jpg new file mode 100644 index 0000000..f2f22fc Binary files /dev/null and b/tests/test9.jpg differ diff --git a/tests/tests.json b/tests/tests.json index 3884263..609001d 100644 --- a/tests/tests.json +++ b/tests/tests.json @@ -38,5 +38,30 @@ "filename": "./tests/test7.png", "zplstring": "^XA,^FS^FO0,0^GFA,71,128,4,!::FE3KF::!FFE3FFFF::!E223FFFF::!:::FFFFC7FF::!FFFFC7C7::!FFFFC47F::!::^FS,^XZ", "graphictype": "CompressedASCII" + }, + { + "filename": "./tests/test6.png", + "zplstring": "XlhBLF5GUwpeRk8wLDAKXkdGQiw1MSw1MSwzLAr//wD//wD//wD+PwD+PwD+PwD//wD/4wD/4wD/4wD//wDiIwDiIwDiIwD//wD//wD//wBeRlMsXlhaCg==", + "graphictype": "Binary" + }, + { + "filename": "./tests/test9.jpg", + "zplstring": "^XA,^FS^FO0,0^GFA,100,7600,76,,:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::^FS,^XZ", + "graphictype": "CompressedASCII" + }, + { + "filename": "./tests/test10.gif", + "zplstring": "^XA,^FS^FO0,0^GFA,122,7600,76,mN03800::,::mN03800:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::mPF00::mN03800::^FS,^XZ", + "graphictype": "CompressedASCII" + }, + { + "filename": "./tests/test11.gif", + "zplstring": "^XA,^FS^FO0,0^GFA,611,7200,12,1CgH0:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::gIFC::1CgH0::^FS,^XZ", + "graphictype": "CompressedASCII" + }, + { + "filename": "./tests/test12.gif", + "zplstring": "^XA,^FS^FO0,0^GFA,6039,4500000,750,1CrG0zY0zY0zY0:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::rGFzYFzYFzYFC7::1CrG0zY0zY0zY0::^FS,^XZ", + "graphictype": "CompressedASCII" } ] \ No newline at end of file diff --git a/zplgfa_test.go b/zplgfa_test.go index b5affdf..59396c7 100644 --- a/zplgfa_test.go +++ b/zplgfa_test.go @@ -76,15 +76,15 @@ func Test_ConvertToZPL(t *testing.T) { default: graphicType = CompressedASCII } + gfimg := ConvertToZPL(flat, graphicType) - // remove whitespace - only for the test - gfimg = strings.Replace(gfimg, " ", "", -1) - gfimg = strings.Replace(gfimg, "\n", "", -1) - - switch graphictype { - case "Binary": + if graphictype == "Binary" { gfimg = base64.StdEncoding.EncodeToString([]byte(gfimg)) + } else { + // remove whitespace - only for the test + gfimg = strings.Replace(gfimg, " ", "", -1) + gfimg = strings.Replace(gfimg, "\n", "", -1) } if gfimg != zplstring {