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

CSN-A2热敏打印机打印非纯色图像时出现图像异常问题

CSN-A2热敏打印机ESC/POS ESC*位图像打印非纯色图像错乱问题

我基于ESC/POS的ESC*位图像打印命令,给CSN-A2热敏打印机写了一段Go代码。代码通过ImageMagick将任意图像转换为黑白图像,并使用Floyd-Steinberg抖动算法处理。目前纯黑白图像可以正常打印,但非纯色图像打印时,画面多个区域会出现错乱。

打印对比图

以下是生成打印命令并发送到串口连接的打印机的代码:

package test

import (
    "bytes"
    "context"
    "encoding/binary"
    "fmt"

    "gopkg.in/gographics/imagick.v2/imagick"
)

type EscStarArtworkTransformer struct {
    maxWidth uint
}

func NewEscStarArtworkTransformer(maxWidth uint) *EscStarArtworkTransformer {
    return &EscStarArtworkTransformer{
        maxWidth: maxWidth,
    }
}

func (t *EscStarArtworkTransformer) Transform(ctx context.Context, mw *imagick.MagickWand) ([]byte, error) {
    logger := FromLoggerContext(ctx)

    density := uint(24)

    if mw.GetImageWidth() > t.maxWidth {
        if err := mw.ThumbnailImage(t.maxWidth, mw.GetImageHeight()*t.maxWidth/mw.GetImageWidth()); err != nil {
            panic(err) // TODO
        }
    }

    {
        pattern := imagick.NewMagickWand()
        defer pattern.Destroy()

        if err := pattern.ReadImage("pattern:gray50"); err != nil {
            panic(err) // TODO
        }

        if err := mw.RemapImage(pattern, imagick.DITHER_METHOD_FLOYD_STEINBERG); err != nil {
            panic(err) // TODO
        }
    }

    {
        extendHeight := density - (mw.GetImageHeight() % density)
        if extendHeight != 0 && extendHeight != density {
            if err := mw.SetGravity(imagick.GRAVITY_NORTH); err != nil {
                panic(err) // TODO
            }

            pw := imagick.NewPixelWand()
            defer pw.Destroy()

            pw.SetColor("white")

            if err := mw.SetBackgroundColor(pw); err != nil {
                panic(err) // TODO
            }

            if err := mw.ExtentImage(mw.GetImageWidth(), mw.GetImageHeight()+extendHeight, 0, 0); err != nil {
                panic(err) // TODO
            }
        }
    }

    {
        pw := imagick.NewPixelWand()
        defer pw.Destroy()

        if err := mw.RotateImage(pw, 270); err != nil {
            panic(err) // TODO
        }
    }

    if err := mw.FlipImage(); err != nil {
        panic(err) // TODO
    }

    imageHeight := mw.GetImageHeight()
    imageWidth := mw.GetImageWidth()

    widthBuffer := new(bytes.Buffer)
    if err := binary.Write(widthBuffer, binary.LittleEndian, uint16(imageHeight)); err != nil {
        logger.WithError(err).Error("failed to convert image width to binary little endian")
        return nil, fmt.Errorf("convert image width to binary little endian: %w", err)
    }

    data := []byte{0x1b, 0x33, 0}

    rowHeader := []byte{0x1b, 0x2a, 0x21} // ESC * 33
    rowHeader = append(rowHeader, widthBuffer.Bytes()...)

    for left := uint(0); left < imageWidth; left += density {
        imageSlice := mw.Clone()
        defer imageSlice.Destroy()

        if err := imageSlice.CropImage(density, imageHeight, int(left), 0); err != nil {
            logger.WithError(err).Error("failed to crop image slice", err)
            return nil, fmt.Errorf("crop image slice: %w", err)
        }

        exportedPixels, err := imageSlice.ExportImagePixels(0, 0, uint(density), imageHeight, "I", imagick.PIXEL_CHAR)
        if err != nil {
            logger.WithError(err).Error("failed to export image slice pixels")
            return nil, fmt.Errorf("export image slice pixels: %w", err)
        }

        exportedBytes, ok := exportedPixels.([]byte)
        if !ok {
            logger.Error("failed to convert exported image slice pixels to bytes")
            return nil, fmt.Errorf("convert exported image slice pixels to bytes")
        }

        rasterizedRow := make([]byte, (len(exportedBytes)+7)/8)
        for i, x := range exportedBytes {
            if x == 0xff {
                rasterizedRow[i/8] |= 0x80 >> uint(i%8)
            }
        }

        data = append(data, rowHeader...)
        data = append(data, rasterizedRow...)
        data = append(data, 0x0a)
    }

    data = append(data, 0x1b, 0x32) // ESC 2

    return data, nil
}

我已经导出imageSlice确认前期图像转换步骤是正确的,但非纯色图像打印时仍然存在异常。


内容的提问来源于stack exchange,提问作者Justin Hendrickson

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 20:17:10