objective-c - 使用 'raster mode' : need basic guidance 直接打印到以太网打印机

标签 objective-c c cocoa-touch graphics printing

我遇到了一个方式超出我专业领域的问题,而且我没有导师可以寻求帮助。

我有一台收据打印机,需要通过 iOS 应用进行交互。打印机与设备位于同一网络上,因此我可以通过支持的“线路模式命令”对其进行寻址

我想做的是保留我已有的跨平台代码——即它是一个 UIView/NSView,如果你不熟悉 OS X/iOS,它只是一个标准的普通 View 我可以渲染成 PDF/PNG 格式。值得庆幸的是,打印机具有“光栅图形”模式,这似乎正是我所需要的。

不幸的是,无论是命令规范的英文破烂,还是我对基本 C 以外的任何知识都一无所知,或者我完全缺乏图形方面的知识,我什至不知道如何从我的命令规范开始有。我知道打印机和我的网络工作因为我可以通过网络寻址它并向它发送基本的进纸命令。但是,我不知道如何从 PNG -> 打印机需要什么才能使它的“光栅模式”工作。

规范可在 http://www.star-m.jp/eng/service/usermanual/linemode_cm_en.pdf 获得,如果您想提供帮助,您希望开始阅读的页面是 3-68,而我在开始使用时遇到困难的具体命令位于 3-78/3-79。

我只能给你一个勾号,但我向你保证,如果你能为我提供一个正确方向的一点,我将永远感激你。

最佳答案

在编写了一些打印机驱动程序后,我可以确认由于打印机的工作方式,文档通常很困惑。你提到的文件对我来说实际上并不坏。

我认为您在光栅模式下打印是正确的,总体而言这将提供最佳结果。

根据 Star 文档,我认为您需要发送:

1. \x1b*rR  Initialize raster mode
2. \x1b*rA  Enter raster mode
3. \x1b*rC  Clear raster data
4. \x1b*rml
4. b\x##\x##\xAA\xAA\xAA....<DATA>..........
5. \x1b\x0C\x00 Raster Form feed(??) - should spit out the data.
6. \x1b*rB  Clear raster data

很明显。上面的\x1b是ESC的C编码(即字符27 0x1b)。

从我一直在阅读的所有文档中,以下是图像应该如何在光栅模式下格式化。在行模式下,它完全不同,因为垂直和水平被交换了。来自 THERMAL PRINTER PROGRAMMER'S MANUAL (TSP552,TSP552II,TSP2000)

Star Raster Data

这等同于以下字节流。

Star Raster bytes

在第 4 个命令行上,实际上是 'b' 后跟两个定义大小的字节。此大小计算为流 % 256 和/256 中包含的像素数。因此对于 320x1 为 0x40,0x01

所以,将上面的内容插入一个简单的测试程序中,你应该用这个来测试:

char rasterImage [] = {
0x1b, '*', 'r', 'R',       //  Initialize raster mode
0x1b, '*', 'r', 'A',       // Enter raster mode
0x1b, '*', 'r', 'C',       // Clear raster data
//          n1  n2 d1    d2..
0x1b, 'b', 0x2, 0, 0x00, 0x00, // data
0x1b, 'b', 0x2, 0, 0x1F, 0xF8,
0x1b, 'b', 0x2, 0, 0x3F, 0xFC,
0x1b, 'b', 0x2, 0, 0x77, 0xEE,
0x1b, 'b', 0x2, 0, 0xF8, 0x1F,
0x1b, 'b', 0x2, 0, 0xF8, 0x1F,
0x1b, 'b', 0x2, 0, 0xF8, 0x1F,
0x1b, 'b', 0x2, 0, 0x0F, 0xF0,
0x1b, 'b', 0x2, 0, 0x1F, 0xF8,
0x1b, 'b', 0x2, 0, 0x1F, 0xF8,
0x1b, 'b', 0x2, 0, 0x3E, 0x7C,
0x1b, 'b', 0x2, 0, 0x38, 0x1C,
0x1b, 'b', 0x2, 0, 0x79, 0x9E,
0x1b, 'b', 0x2, 0, 0x73, 0xCE,
0x1b, 'b', 0x2, 0, 0x73, 0xCE,
0x1b, 'b', 0x2, 0, 0xF9, 0x9F,
0x1b, 'b', 0x2, 0, 0xF8, 0x1F,
0x1b, 'b', 0x2, 0, 0xFE, 0x7F,
0x1b, 'b', 0x2, 0, 0xFF, 0xFF,
0x1b, 'b', 0x2, 0, 0xFF, 0xFF,
0x1b, 'b', 0x2, 0, 0x00, 0x00,
0x1b, 'b', 0x2, 0, 0x00, 0x00,
0x1b, 'b', 0x2, 0, 0x00, 0x00,
0x1b, 'b', 0x2, 0, 0x00, 0x00};

[self.currentDataBeingSent appendBytes:rasterImage length:sizeof(rasterImage)];

只需将其喷到打印机上,您就会得到如上图所示的照片。在这里您可以轻松地调整和使用确切的命令来获得有用的东西。通常这是我设法弄清楚应该做什么的唯一方法。

修订版 3

引用。评论。

如果每个像素有一个字节,那么您需要将它们合并成一系列位;以下应该根据您的 pastebin 代码完成这项工作。我还将 char* 更改为未签名,因为它已签名可能会在位操作时导致问题。

NSUInteger bitmapBytePerRow = width/8;
NSUInteger bytesPerRow = 3 + bitmapBytePerRow;

[self.currentDataBeingSent = [NSMutableData dataWithLength:bytesPerRow * height];
[self.currentDataBeingSent appendBytes:initializeRaster length:sizeof(initializeRaster)];
[self.currentDataBeingSent appendBytes:enterRaster length:sizeof(enterRaster)];

NSUInteger byteOffset = 0;
for (NSUInteger y = 0; y < height; y++)
{
    unsigned char *rasterCommandForRow = (unsigned char *)calloc(bytesPerRow, sizeof(char));
    unsigned char *current_raster = rasterCommandForRow; 
    *current_raster++ = '\x6B';     
    *current_raster++ = (width*height) % 256;
    *current_raster++ = (width*height) / 256;
    
    unsigned char mask = '\x80' ;
    unsigned char out = 0 ;
    for (NSUInteger x = 0; x < width; x++)
    {
        if (*(data + (byteOffset * sizeof(char))))
            out |= mask ;
        byteOffset++;
        mask >>= 1 ;
        if( 0 == mask )
        {
            mask = '\x80' ;
            *current_raster++ = out ;
            if( out )
        lastDot = nextOut ;
            out = 0 ;
        }
        
    }
    
    // handle partially finished byte .
    if( ( '\x80' != mask ) && ( 0 != out ) )
        *current_raster++ = out ;

    [self.currentDataBeingSent appendBytes:rasterCommandForRow length:bytesPerRow];
}

修订版 3a

查看 Mac CUPS support从 Star 那里得到了驱动程序的源代码,其中包含许多有关如何完成此操作的线索。有时代码比文档更容易阅读。

starcupsdrv-3.1.1_mac_20100423.zip\starcupsdrv-3.1.1_mac\SourceCode\

包含 starcupsdrv-src-3.1.1.tar.gz\ 子文件夹 starcupsdrv\src\

查看 rastertostar.c,重要的一点是 n1/n2 值的计算。这些根本不是 X 和 Y,而是基于像素数,lastBlackPixel 是来自源的像素数。

putchar('b');
putchar((char) ((lastBlackPixel > 0)?(lastBlackPixel % 256):1));
putchar((char) (lastBlackPixel / 256));

我已经修改了上面的代码以包含修复程序,希望这会更接近。如果不发布打印机输出的扫描件,这将有助于诊断正在发生的事情。

供引用 jsStarUSB.cpp 580:650 之间的代码在我看来,您需要生成一个缓冲区(存储在 nextOut 中),其中包含要直接发送到打印机的格式的光栅数据。

转。 4 (2023)

Joshua May 在评论中建议 rasterImage 不需要每一行的 ESC (0x1b) - 只需要 'b' 并且只需删除“对我有用”的 0x1b。

关于objective-c - 使用 'raster mode' : need basic guidance 直接打印到以太网打印机,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3995703/

相关文章:

iphone - UINavigationController 未按需要设置动画

iphone - 在 UITextfield 中使用 NSNumberFormatter 进行实时格式化

connect() 函数耗时过长

c - 如何在 for 循环中使用 strtok()?

ios - 如何将操作发送到从 UIAlertView 委托(delegate)的 UIImage subview

ios - UITableview 下的滑动工具栏

ios - 保护资源视频文件

iphone - 为每个用户生成唯一的号码并对数据进行加密

objective-c - 如何在单击按钮时以编程方式将 NSTextFields 中的值添加到核心数据中?

c - 将 const char 与 int 连接成一个 char*