在CSN-A2热敏打印机上打印非纯色图像时出现图像错误。

huangapple go评论121阅读模式
英文:

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.

在CSN-A2热敏打印机上打印非纯色图像时出现图像错误。

[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

  1. package test
  2. import (
  3. "bytes"
  4. "context"
  5. "encoding/binary"
  6. "fmt"
  7. "gopkg.in/gographics/imagick.v2/imagick"
  8. )
  9. type EscStarArtworkTransformer struct {
  10. maxWidth uint
  11. }
  12. func NewEscStarArtworkTransformer(maxWidth uint) *EscStarArtworkTransformer {
  13. return &EscStarArtworkTransformer{
  14. maxWidth: maxWidth,
  15. }
  16. }
  17. func (t *EscStarArtworkTransformer) Transform(ctx context.Context, mw *imagick.MagickWand) ([]byte, error) {
  18. logger := FromLoggerContext(ctx)
  19. density := uint(24)
  20. if mw.GetImageWidth() > t.maxWidth {
  21. if err := mw.ThumbnailImage(t.maxWidth, mw.GetImageHeight()*t.maxWidth/mw.GetImageWidth()); err != nil {
  22. panic(err) // TODO
  23. }
  24. }
  25. {
  26. pattern := imagick.NewMagickWand()
  27. defer pattern.Destroy()
  28. if err := pattern.ReadImage("pattern:gray50"); err != nil {
  29. panic(err) // TODO
  30. }
  31. if err := mw.RemapImage(pattern, imagick.DITHER_METHOD_FLOYD_STEINBERG); err != nil {
  32. panic(err) // TODO
  33. }
  34. }
  35. {
  36. extendHeight := density - (mw.GetImageHeight() % density)
  37. if extendHeight != 0 && extendHeight != density {
  38. if err := mw.SetGravity(imagick.GRAVITY_NORTH); err != nil {
  39. panic(err) // TODO
  40. }
  41. pw := imagick.NewPixelWand()
  42. defer pw.Destroy()
  43. pw.SetColor("white")
  44. if err := mw.SetBackgroundColor(pw); err != nil {
  45. panic(err) // TODO
  46. }
  47. if err := mw.ExtentImage(mw.GetImageWidth(), mw.GetImageHeight()+extendHeight, 0, 0); err != nil {
  48. panic(err) // TODO
  49. }
  50. }
  51. }
  52. {
  53. pw := imagick.NewPixelWand()
  54. defer pw.Destroy()
  55. if err := mw.RotateImage(pw, 270); err != nil {
  56. panic(err) // TODO
  57. }
  58. }
  59. if err := mw.FlipImage(); err != nil {
  60. panic(err) // TODO
  61. }
  62. imageHeight := mw.GetImageHeight()
  63. imageWidth := mw.GetImageWidth()
  64. widthBuffer := new(bytes.Buffer)
  65. if err := binary.Write(widthBuffer, binary.LittleEndian, uint16(imageHeight)); err != nil {
  66. logger.WithError(err).Error("failed to convert image width to binary little endian")
  67. return nil, fmt.Errorf("convert image width to binary little endian: %w", err)
  68. }
  69. data := []byte{0x1b, 0x33, 0}
  70. rowHeader := []byte{0x1b, 0x2a, 0x21} // ESC * 33
  71. rowHeader = append(rowHeader, widthBuffer.Bytes()...)
  72. for left := uint(0); left < imageWidth; left += density {
  73. imageSlice := mw.Clone()
  74. defer imageSlice.Destroy()
  75. if err := imageSlice.CropImage(density, imageHeight, int(left), 0); err != nil {
  76. logger.WithError(err).Error("failed to crop image slice", err)
  77. return nil, fmt.Errorf("crop image slice: %w", err)
  78. }
  79. exportedPixels, err := imageSlice.ExportImagePixels(0, 0, uint(density), imageHeight, "I", imagick.PIXEL_CHAR)
  80. if err != nil {
  81. logger.WithError(err).Error("failed to export image slice pixels")
  82. return nil, fmt.Errorf("export image slice pixels: %w", err)
  83. }
  84. exportedBytes, ok := exportedPixels.([]byte)
  85. if !ok {
  86. logger.Error("failed to convert exported image slice pixels to bytes")
  87. return nil, fmt.Errorf("convert exported image slice pixels to bytes")
  88. }
  89. rasterizedRow := make([]byte, (len(exportedBytes)+7)/8)
  90. for i, x := range exportedBytes {
  91. if x == 0xff {
  92. rasterizedRow[i/8] |= 0x80 >> uint(i%8)
  93. }
  94. }
  95. data = append(data, rowHeader...)
  96. data = append(data, rasterizedRow...)
  97. data = append(data, 0x0a)
  98. }
  99. data = append(data, 0x1b, 0x32) // ESC 2
  100. return data, nil
  101. }

I have written out the imageSlices 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

huangapple
  • 本文由 发表于 2023年3月19日 03:10:18
  • 转载请务必保留本文链接:https://go.coder-hub.com/75778087.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定