使用"光栅模式"直接打印到以太网打印机:需要基本指导

ref*_*tis 9 c printing graphics cocoa-touch objective-c

我经历了一个问题,迷迷糊糊的方式超出了我的专业领域,我没有一个导师可以寻求这方面的帮助.

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

我想要做的是保持我已经跨平台工作的代码 - 即它是一个UIView/NSView,如果你不熟悉OS X/iOS,它只是一个标准的vanilla视图,我可以渲染成PDF/PNG格式.值得庆幸的是,打印机具有"光栅图形"模式,似乎是我需要的.

不幸的是,无论是命令规范的破坏英语,还是我对基本C之外的任何东西的完全缺乏了解,或者我完全缺乏关于图形的知识,我都不知道如何从我拥有的命令规范开始.我知道打印机和我的网络工作,因为我可以通过网络解决它并发送基本的feed命令.但是,我不知道如何从PNG开始 - >无论打印机需要什么使它成为'光栅模式'的工作.

该规范可在http://www.star-m.jp/eng/service/usermanual/linemode_cm_en.pdf上找到,如果你想提供帮助,你想要开始阅读它的页面是3-68,具体的命令我甚至没有开始使用的是3-78/3-79.

我只能给你一个勾选标记但是我向你保证,如果你能为我提供正确方向的一点,你将会有我不朽的感激之情.

Ric*_*son 11

编写了几个打印机驱动程序后,我可以确认,由于打印机的工作方式,文档通常会令人困惑.你提到的文件对我来说实际上并不坏.

我认为你以光栅模式进行打印是正确的,总体来说这将是最好的结果.

从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
Run Code Online (Sandbox Code Playgroud)

Obv.在上面的\ x1b中是ESC的C编码(即字符27 0x1b).

从我阅读的所有文档中,以下是如何在光栅模式下格式化图像.在线模式下,当垂直和水平交换时,它完全不同.来自热敏打印机程序设计手册(TSP552,TSP552II,TSP2000)

星光栅数据

这相当于以下字节流.

星光栅字节

在第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)];
Run Code Online (Sandbox Code Playgroud)

只需将它喷到打印机上即可获得如上所示的图片.在这里,您可以轻松调整和播放确切的命令,以获得有用的功能.通常这是我设法弄清楚应该做什么的唯一方法.

订正

参考.评论.

如果每个像素有一个字节,那么你需要将它们合并为一系列位; 以下应该根据您的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];
}
Run Code Online (Sandbox Code Playgroud)

rev.3a

看看Star 的Mac CUPS支持,它有驱动程序的源代码,其中包含很多关于如何完成此操作的线索.有时代码比文档更容易阅读.

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));
Run Code Online (Sandbox Code Playgroud)

我修改了上面的代码以包含修复程序,希望它们会更接近.如果不扫描打印机发出的信息,那么诊断发生的情况将非常有用.

供参考jsStarUSB.cpp中 580:650之间的代码在我看来与生成缓冲区(存储在其中nextOut)所需的内容一致,该缓冲区包含要直接发送到打印机的格式的栅格数据.


Pro*_*ica 4

我有预感这可能与旧的 Seiko 打印机相同,只是你的打印机支持网络。如果是这样,请查看此处的 C 代码。它尝试输出到串行端口 /dev/cua,它认为打印机位于该端口。

但如果命令相同,代码应该对您有帮助。它采用可移植位图格式(纯 ASCII 文本)作为输入。

但我不知道。微软表示Star Micronics 的工作原理与 Epson LQ 相同,在这种情况下有充足的文档

相关链接:


更新!;-) 试试这个,完全未经测试的代码:

/* Call with grayscale images of height 256, width 256. */

- (void) outputraster(char* pixels, int rows)
{
    const char initializeRaster[] =    "\x1B\x2A\x72\x52";
    const char enterRaster[] =         "\x1B\x2A\x72\x41";
    const char formFeed[] =            "\x1B\x0C\x00";
    const char clearRaster[] =         "\x1B\x2A\x72\x43";
    const char exitRaster[] =          "\x1B\x2A\x72\x42";

/* The FF means 255 lines: */
    char setRasterPageLength[]         "\x1B\x2A\x72\x50\xFF\x0";


/* The FF FF means 256 lines and 256 rows: */
    char sendRasterData[] =            "\x62\xFF\xFF";

    [self sendBytes:initializeRaster ofLength:sizeof(initializeRaster)];
    [self sendBytes:enterRaster ofLength:sizeof(enterRaster)];
    [self sendBytes:clearRaster ofLength:sizeof(clearRaster)];
    [self sendBytes:setRasterPageLength ofLength:sizeof(setRasterPageLength)];
    [self sendBytes:sendRasterData ofLength:sizeof(sendRasterData)];

    while (rows)
    {
        for (int x = 0; x < 255; x++)
        {
            [self sendBytes:pixels[x] ofLength:256];
        }

        rows --;
    }
}
Run Code Online (Sandbox Code Playgroud)

更新!


我晚上查看文档,偶然发现如何打印预存储的徽标。然后我研究了如何定义该徽标,文档的这一部分看起来更加彻底替代文本 替代文本 替代文本

类似打印机的位图格式说明: 替代文本

另外,请参阅第 34 页及后续页,了解 Star 打印机位图格式的说明。