Writing chars to a file as binary / correctly encoded

Hi, currently trying to generate ESC/POS commands from OF

I’ve used a command line tool which outputs chars to the receipt printer, which look like this in TextEdit (ie. basic chars);

`ˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇüˇˇflˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇ˛?‡˛ˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇ¯?¿~?ˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇ?IJˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇ`>aˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇ¸a>aˇˇˇˇˇˇˇˇˇˇˇˇˇ`

And like so as binary in Sublime Text;

ffff ffff ffff ffff 0604 0000 0000 0007
067f f800 0000 0000 007f dfff ffe3 ffff
ffff ffff ffff ffff ffff ffff ffff ffff
ffff ffff ffff ffff ffff ffff ffff ffff
ffff ffff ffff ffff 0000 0000 0000 0000
0000 0000 0000 0000 003f 9dc8 7ff1 ffff
ffff ffff ffff ffff ffff ffff ffff ffff
ffff ffff ffff ffff ffff ffff ffff ffff
ffff ffff ffff fff8 0000 0000 0000 0000
0000 0000 0000 0000 0000 0000 0670 3fff

The tool is written in C and is just printing out chars like so;

  putchar(0x80);

  //  Line breaks
  for (int j = 0; j < 4; j++) {
    putchar(0x0a);
  }

  //  "Cut paper" command
  putchar(0x1d);
  putchar(0x56);
  putchar(0x00);

So I’m wondering how best to write these chars to a file from within OF?

Cheers

have you tried https://github.com/bakercp/ofxESCPOS
cheers

Yep, briefly - but it seems to be connecting directly to the serial port which is unnecesarily complicated as it needs a /dev/ location - whereas Mac uses CUPS, and to the best of my knowledge the /dev/ usb devices aren’t static.

At the moment I can do this easily from the command line;

lpr -o raw -H localhost -P MyThermalPrinterOnCups MyTextFile.txt

Or even …

png2pos -c -p  MyImage.png > MyTextFile.txt && lpr -o raw -H localhost -P MyThermalPrinterOnCups MyTextFile.txt

So what I’m aiming to do is generate that MyTextFile.txt from within OpenFrameworks (my own ESC/POS bitmaps) and then send a ofSystem command to print it

Hence the structure / format of that text file being the thing that’s stumped me. I’m totally clueless when it comes to chars, UTF encoding, buffers etc!

On a semi-related note I was also stumped by some of the abstractions for pixels in the latest versions of OF - ie. many tutorials and resources talk of iterating through unsigned chars - but it seems now with ofPixel you have to query for an ofColor?

Not mandatory. If you want to access the unsigned chars you can call getData() on the ofPixels object.
Hence if you are using an ofImage you can call ofImageInstance.getPixels().getData()

1 Like

something like this should work

vector<char> c;

c.push_back(0xff);//this is how you add more chars
c.push_back(0xff);

ofBuffer b;
b.set(&c[0], c.size());
ofBufferToFile("buffer_non_binary.txt", b, false);
ofBufferToFile("buffer_binary.txt", b, true);

Hope it helps.

cheers

1 Like

Super, thanks for the help!

Looking closer to what’s needed though the MIME / encoding are still quite different. Using file -I MyFile.txt I see that the types from png2pos is;

output.txt: application/octet-stream; charset=binary

Whereas the ofBuffer objects are;

buffer_binary.txt: text/plain; charset=unknown-8bit
buffer_non_binary.txt: text/plain; charset=unknown-8bit

I wouldn’t bother about that as long as the file contents are the same.

It’s working! Very pleasing results from the cheap thermal printer - though it panics with any raw file over 18kb and starts printing UTF chars.

Solution is to reset after each print and resize images before generating the raw file, and printing them in a queue with a timer.

Current project is wrapped up in many unfinished addons, so here are the basics of what’s being done;

typedef vector<char> PrintCommands;

PrintCommands generatePos(ofImage & img) {
    

    //////////////////////////
    // ADD HEADERS TO FILE  //
    //////////////////////////

    PrintCommands c;
    c.clear();
    c.push_back(0x1D);
    c.push_back(0x76);
    c.push_back(0x30);
    c.push_back(0x00);
    
    unsigned short headerX = (img.getWidth() + 7) / 8; // width in characters
    unsigned short headerY = img.getHeight(); // height in pixels
    
    c.push_back((headerX >> 0) & 0xFF);
    c.push_back((headerX >> 8) & 0xFF);
    c.push_back((headerY >> 0) & 0xFF);
    c.push_back((headerY >> 8) & 0xFF);


    
    //////////////////////////
    // GENERATE DOTS        //
    //////////////////////////


    int mask = 0x80;
    int i = 0;
    int temp = 0;
    
    for (int y = 0; y < img.getHeight(); y++) {
        for (int x = 0; x < img.getWidth(); x++) {
            
            
            int value = img.getColor(x,y).getBrightness();
            value = (value << 8) | value;
            if (value == 0) {
                temp |= mask;
            }
            
            mask = mask >> 1;
            i++;
            if (i == 8) {
                c.push_back(temp);
                mask = 0x80;
                i = 0;
                temp = 0;
            }
        }
        if(i != 0) {
            c.push_back(temp);
            i = 0;
        }
    }
    
    return c;
    
}


void reset() {
    ofSystem("cupsdisable -c Thermal_Printer_H58_Printer_USB && cupsenable Thermal_Printer_H58_Printer_USB");
}

void print(PrintCommands c) {
    
        
        //////////////////////////
        // STR > BUFFER > FILE  //
        //////////////////////////


        ofBuffer b;
        b.set(&c[0], c.size());
        string filename = "output.txt";
        ofBufferToFile(filename, b , true);
    
    //////////////////////////
    // SYSTEM PRINT w. CUPS //
    //////////////////////////


        string pwd = ofSystem("cd ../../../ && pwd");
        pwd.erase(std::remove(pwd.begin(), pwd.end(), '\n'), pwd.end());
        string url = pwd + "/data/output.txt";
        ofSystem("lp -d Thermal_Printer_H58_Printer_USB -o raw " + url);
}

Thanks again :slight_smile: