如何用Go语言实现Brother QL-800标签打印机打印功能?
解决Brother QL-800 Go语言打印问题
核心问题分析
你的代码存在两个致命问题:
- 光栅数据完全无效:
textToRasterData直接返回0x20,没有生成任何实际的文本点阵数据,打印机接收不到有效打印内容。 - 指令序列不符合QL-800规范:重复设置模式指令,标签宽度、打印模式等参数配置错误,导致打印机无法识别指令。
分步修复方案
1. 生成有效光栅数据
QL-800采用300dpi分辨率,需要将文本转换为对应宽度的点阵数据(比如62mm标签对应744像素宽)。直接用freetype库生成位图,再转换成Brother光栅格式:
import ( "image" "image/color" "image/draw" "github.com/golang/freetype" "github.com/golang/freetype/truetype" ) func textToRasterData(text string) []byte { // 62mm标签对应744像素宽,高度按需设置为100像素 img := image.NewGray(image.Rect(0, 0, 744, 100)) draw.Draw(img, img.Bounds(), image.NewUniform(color.Gray{255}), image.Point{}, draw.Src) // 加载本地字体文件,替换为你的字体路径(比如系统字体路径) fontBytes, err := os.ReadFile("arial.ttf") if err != nil { log.Fatal(err) } f, err := truetype.Parse(fontBytes) if err != nil { log.Fatal(err) } c := freetype.NewContext() c.SetDPI(300) c.SetFont(f) c.SetFontSize(24) c.SetClip(img.Bounds()) c.SetDst(img) c.SetSrc(image.NewUniform(color.Gray{0})) // 绘制文本,调整位置避免超出标签范围 _, err = c.DrawString(text, freetype.Pt(10, 30)) if err != nil { log.Fatal(err) } // 转换为Brother光栅格式(每行按字节打包,高位在前) var raster []byte bounds := img.Bounds() for y := bounds.Min.Y; y < bounds.Max.Y; y++ { var byteVal byte for x := bounds.Min.X; x < bounds.Max.X; x++ { bitPos := 7 - (x % 8) if img.GrayAt(x, y).Y < 128 { // 黑色像素标记 byteVal |= 1 << bitPos } if (x+1)%8 == 0 { raster = append(raster, byteVal) byteVal = 0 } } // 处理每行剩余的不足8位的像素 if bounds.Max.X%8 != 0 { raster = append(raster, byteVal) } } return raster }
2. 修正指令序列
严格遵循Brother QL系列的光栅指令规范,正确的初始化流程如下:
func generateRasterCommand(text string) []byte { rasterData := textToRasterData(text) return append( []byte{ 0x1B, 0x40, // 初始化打印机 0x1B, 0x69, 0x4D, 0x02, // 设置标签打印模式(模式2对应QL-800) 0x1B, 0x69, 0x7A, 0x4A, // 设置标签宽度为62mm(对应744像素) 0x1B, 0x69, 0x41, 0x08, // 设置默认打印浓度 }, append(rasterData, 0x1B, 0x69, 0x5A)..., // 追加光栅数据+打印切纸指令 ) }
3. 调试技巧
- 抓包对比数据:用打印机监控工具抓取Java代码成功打印的原始数据,和Go代码发送的数据对比,定位指令差异。
- RAW文件测试:把生成的指令保存为
.bin文件,用系统命令直接发送:- Windows:
copy /b output.bin "Brother QL-800" - Linux:
lp -d QL-800 -o raw output.bin
- Windows:
- 验证打印机名称:调用
printer.List()列出系统可用打印机,确保printerName完全匹配。
完整修正代码
package main import ( "image" "image/color" "image/draw" "log" "os" "github.com/alexbrainman/printer" "github.com/golang/freetype" "github.com/golang/freetype/truetype" ) func generateRasterCommand(text string) []byte { rasterData := textToRasterData(text) return append( []byte{ 0x1B, 0x40, // 初始化打印机 0x1B, 0x69, 0x4D, 0x02, // 标签模式 0x1B, 0x69, 0x7A, 0x4A, // 62mm标签宽度 0x1B, 0x69, 0x41, 0x08, // 打印浓度 }, append(rasterData, 0x1B, 0x69, 0x5A)..., // 光栅数据 + 打印切纸 ) } func textToRasterData(text string) []byte { // 62mm标签宽度对应744像素(300dpi),高度100像素 img := image.NewGray(image.Rect(0, 0, 744, 100)) draw.Draw(img, img.Bounds(), image.NewUniform(color.Gray{255}), image.Point{}, draw.Src) // 加载本地字体文件,替换为你的字体路径 fontPath := "arial.ttf" fontBytes, err := os.ReadFile(fontPath) if err != nil { log.Fatalf("Failed to read font file: %v", err) } f, err := truetype.Parse(fontBytes) if err != nil { log.Fatalf("Failed to parse font: %v", err) } c := freetype.NewContext() c.SetDPI(300) c.SetFont(f) c.SetFontSize(24) c.SetClip(img.Bounds()) c.SetDst(img) c.SetSrc(image.NewUniform(color.Gray{0})) // 绘制文本,位置调整为(10, 30) _, err = c.DrawString(text, freetype.Pt(10, 30)) if err != nil { log.Fatalf("Failed to draw string: %v", err) } // 转换为Brother光栅格式(每行按字节打包,高位在前) var raster []byte bounds := img.Bounds() for y := bounds.Min.Y; y < bounds.Max.Y; y++ { var byteVal byte for x := bounds.Min.X; x < bounds.Max.X; x++ { bitPos := 7 - (x % 8) if img.GrayAt(x, y).Y < 128 { byteVal |= 1 << bitPos } if (x+1)%8 == 0 { raster = append(raster, byteVal) byteVal = 0 } } // 处理每行剩余的位 if bounds.Max.X%8 != 0 { raster = append(raster, byteVal) } } return raster } func printBrotherRaster(printerName, text string) error { p, err := printer.Open(printerName) if err != nil { return err } defer p.Close() err = p.StartDocument("LabelPrint", "RAW") if err != nil { return err } defer p.EndDocument() err = p.StartPage() if err != nil { return err } data := generateRasterCommand(text) _, err = p.Write(data) if err != nil { return err } err = p.EndPage() if err != nil { return err } log.Println("Label sent to printer successfully!") return nil } func main() { // 获取打印机名称,可通过printer.List()获取 printerName := "Brother QL-800" text := "Hello, Brother QL-800!" err := printBrotherRaster(printerName, text) if err != nil { log.Fatalf("Print failed: %v", err) } }
内容的提问来源于stack exchange,提问作者fritsMaister
相关产品推荐
相关产品推荐

