英文:
Image error when printing non-solid color image on CSN-A2 thermal printer
问题
我已经创建了一些代码,实现了ESC/POS ESC *位图打印命令[1]在CSN-A2[2]上的实现。该代码使用ImageMagick将任意图像转换为黑白,并使用抖动算法。如果我将纯黑白图像发送到打印机,它会正常打印。如果我发送其他图像,图像中的各种矩形会出现问题。
使用以下代码,我生成命令,然后将其发送到通过串行连接连接的CSN-A2。
我已经将imageSlice
写出来,以确认之前的转换步骤是否正确,并确认它们是正确的。
英文:
I have created some code that implements the ESC/POS ESC * bit image printing command [1] for a CSN-A2 [2]. That code uses ImageMagick to convert an arbitrary image to black and white and uses a dithering algorithm. If I send a purely black and white image to the printer, it prints fine. If I send it anything else, various rectangles in the image are messed up.
[1] https://reference.epson-biz.com/modules/ref_escpos/index.php?content_id=88
[2] https://cdn-shop.adafruit.com/datasheets/CSN-A2+User+Manual.pdf
Using the following code, I generate the command and then send it to the CSN-A2, which is attached via a serial connection.
I have
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
}
I have written out the imageSlice
s to confirm the previous transformation steps worked and confirmed they are correct.
答案1
得分: 1
问题是,当我将数据传输到打印机时,我没有为stty
提供正确的设置。我还没有弄清楚具体哪些设置是错误的,但以下是我现在正在使用的设置,它可以正常工作。
stty -F /dev/serial0 0:0:cbe:0:3:1c:7f:15:4:0:0:0:11:13:1a:0:12:f:17:16:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0
英文:
The problem was, when I was piping the data to the printer, I had not provided the correct settings to stty
. I haven't figured out precisely which ones were wrong yet, but here's what I'm using now, which works.
stty -F /dev/serial0 0:0:cbe:0:3:1c:7f:15:4:0:0:0:11:13:1a:0:12:f:17:16:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论