You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Go语言实现Brother QL-800标签打印机打印功能?

解决Brother QL-800 Go语言打印问题

核心问题分析

你的代码存在两个致命问题:

  1. 光栅数据完全无效:textToRasterData直接返回0x20,没有生成任何实际的文本点阵数据,打印机接收不到有效打印内容。
  2. 指令序列不符合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
  • 验证打印机名称:调用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 21:34:55