Suggestions on printing complicated HTML + Raster Receipt.

603 views
Skip to first unread message

Alexander di Chiara

unread,
Sep 24, 2013, 5:51:21 PM9/24/13
to jzebra...@googlegroups.com
Hi Tres, hi everybody, 

this is Alex, nice to meet you all and thanks for all the suggestion i got from this great group till now.

I've parsed almost every post of the last year and i didn't find anything on my actual topic. 
Sure to have some advice i'll try to simplify below what i am doing. 

As the subject, i have 20+ different receipt to print in a vending machine (and that's fixed with linux) and the same to be available on smal PC based kiosks in different shops.
Being each one completely different from the others (logos, qr code, barcodes.. etc) it's very hard to approach this with a ESCP straight solution. Tonnes of lines and less compatibility with different printers available to the shops.

By now, that's what i've suppose to do in the last 2 days.
- Implemented perfectly jZebra --> OT: thanks, sounds great and by the way doesn't blame as much as Tres suggests, dunno why but in my chrome version (which is the same on all the machines) it's always working without additional permission requests. 

- Port all the tickets in pure and strong typed html5 including assets and no css. Is all about inline styles.

- Wrote this couple of functions (which is a replica for all ticket, whenever is gonna work): 

  var changeWindow = window.open('','','width=2,height=2');

  if (printdata.type == 1) { // First type ticket
  changeWindow.document.write(sunrise);  
  var canvas = document.getElementById("hiddens"); // Set the canvas

   $(changeWindow.document.body).html2canvas({  // Raster the canvas 
                canvas: hiddens,
                onrendered: function() {
                
                    setTimeout(function () {changeWindow.close();} , 100);
                    var raster = canvas.toDataURL('image/png'); // Full data:image
                    var output = raster.replace(/^data:image\/(png|jpg);base64,/, ""); // Just the Base 64 data (see Second Option)
    
                    applet.setPaperSize("80mm", "175mm"); 
     applet.setAutoSize(true);
     applet.setOrientation("portrait");    
     applet.appendImage(raster, "ESCP"); 
    applet.append("\n");

  while (!applet.isDoneAppending()) { console.log('appending...'); }
  if (applet.isDoneAppending()) { applet.print(); } // Print as tutorial
                },
                width: 280, // We know width and height cause they are standard for each ticket.
                height: 560
           });
  }

 I even tried another solution based on tutorial, instead of appendImage, filtering the raster string: 

  // Second Option
// applet.append64(output); // Append just base64 data.
// applet.printPS(); // Following the tutorial.

Okay. The First way jZebra says that's a limit of 510 px height due to the matrix format of the language. Understandable, some trick here? 
The Second solution prints just straight chars and goes all the way down to the array. 

I've tried to mix up the solution also, no way ;)

Actual printer is Epson TM, i have a couple of models to test, but still the same. 

I was arguing about bring the getImageData method exposed to the bytearray and spool the raw matrix into. 

Remember also if i'm going straight to window.print(); i have no paper cut at the end of the receipt and the header is a little mismatched probably due to the chrome/firefox printing assistant. 

Everything is Chrome based, i've also tried the chrome --kiosk --kiosk-printing, still no cut but full A4 page printed, which is wrong. ;)

Thanks a lot for your time reading. Any Ideas? 

Cheers,
Alexander




Tres Finocchiaro

unread,
Sep 25, 2013, 9:04:48 PM9/25/13
to jZebra users
Hi Alexander!

Thank you for the detailed information.

You have a very interesting use of the applet.

I think your code is ok.  Here is the output using appendImage(String base64, String languageType, int x, int y):  http://i.imgur.com/jnj2oMP.jpg
(*Note:  EPL requires X/Y coordinates, ESC/P does not)

Upon revisiting the ESCP image code, I don't think the ESCP image code is correct and I don't have a device to test this on.  I agree, 510 doesn't make much sense, and I don't know how I derived that value either, as the comments in the source code do not make sense. (It's sending "ESC v", which does not seem to be correct according to any version of the ESC/P manual.  Are you able to print any raster graphics at all?)

If you can help by contributing the proper ESCP commands, I will update ImageWrapper.java and have this corrected for you soon.  Line 308 of ImageWrapper.java has the logic I'm talking about.

-Tres

Here's the code that worked with EPL:
      function printEPLHTML() {
           $("#content").html2canvas({ 
                canvas: hidden_screenshot,
                onrendered: function() {printBase64Image($("canvas")[0].toDataURL('image/png'));}
           });
      }
      
      function printBase64Image(base64data) {
      if (qz != null) {
               qz.findPrinter("
Zebra LP2844");
               while (!qz.isDoneFinding()) {
 //wait for printer to finish finding
               
               if (qz.getPrinter() == null) { alert("Can't find printer!"); return; }
 
 
               qz.append("\nN\nq609\nQ203,26\n");            
               qz.append("B5,26,0,1A,3,7,152,B,\"1234\"\nA310,26,0,3,1,1,N,\"SKU 00000 MFG 0000\"\n");
               qz.append("A310,56,0,3,1,1,N,\"QZ PRINT APPLET\"\nA310,86,0,3,1,1,N,\"TEST PRINT SUCCESSFUL\"\n");
               qz.append("A310,116,0,3,1,1,N,\"FROM SAMPLE.HTML\"\nA310,146,0,3,1,1,N,\"EDIT SAMPLE.HTML\"\n");
               qz.appendImage(base64data, "EPL", 150, 300);
               while (!qz.isDoneAppending()) {} //wait for image to download to java
               qz.append("\nP1,1\n");
               qz.print();
   }
   monitorPrinting();
      }

-Tres

 
 

--
--
To unsubscribe from this group, send email to jzebra-users...@googlegroups.com
 
http://code.google.com/p/jzebra
 
---
You received this message because you are subscribed to the Google Groups "jZebra users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to jzebra-users...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.

Alexander di Chiara

unread,
Sep 26, 2013, 5:21:03 PM9/26/13
to jzebra...@googlegroups.com
Tres,

thanks a lot for this reply. It is quite interesting cause it's something more complex like a lab/exp for a new kind of small businesses. I will post some open ideas soon. ;)

Yep, exactly, i really can't print any raster at all. 
Looking for alternatives in the last week i stumbled upon a beautiful piece of code even with a good quick translation in java, and being a png a bitmapped "container" could be definitely useful, right? 



In any case, i have a draft to get the canvas pixel grid and store it directly in an array, in the case the png is not working as expected. 

Did it before some exps here: http://www.ti-promotiontest.ch/vale/

About me, you have full support, just let me know what you think about integrate that solution, cause i've got no time to go deep into your jZebra code sorry. 
Still think that something similar should be okay.

Thanks again, 
Alexander

Tres Finocchiaro

unread,
Sep 26, 2013, 5:27:01 PM9/26/13
to jZebra users

The ESCP commands are all we need.  The rest of the pixel logic has been coded for b&w. We're obtaining a device soon that supports ESCP. 

The black&white pixels are all taken care of (we support bits, hex and inverted) just need to know what command is best to send them to the Epson printers.  I'll likely use that first tutorial.

Alexander di Chiara

unread,
Sep 26, 2013, 5:39:51 PM9/26/13
to jzebra...@googlegroups.com
As before, glad to help. 

I've found it literally significant and quick. And i think being talking about Zebra is even better to write and debug the porting. Cool about the logic no worries, i was just thinking about shortening the distance between the applet and the javascript. I mean, i don't like frameworks so much, could just be a suggestion to have an user friendly softbed javascript frame. ;)

While i'm trying some stuff on this side, keep on touch and for sure brainstorm as you like.

Thanks.

capp...@yahoo.com

unread,
Sep 26, 2013, 6:23:43 PM9/26/13
to jzebra...@googlegroups.com
To be honest, it is best to use "Epson Flash Logo" utility if you are using it's driver and just save your logo to somewhere fixed (fixed keycodes) to NV memory and print it with function "GS ( L ..." (see ESC POS guide)

Epson clearly states that downloading bit image functions will be deprecated on future printer models. Hence it is essential to save your image to the perma memory and use it from there. The disadvantages using Epson Flash Utility might be:

- Only works on Windows (once you write to printer's memory, it works in anywhere though)
- Limits programmability (though in this case you can still use NV functions to save a new one on top of the old one, but it is complicated as it is; this is generally a rare case as receipts generally have one logo on top and that is changed infrequently.)

I hope these help you on printing a raster...

Bahadir


From: Alexander di Chiara <alexander...@gmail.com>
To: jzebra...@googlegroups.com
Sent: Friday, 27 September 2013, 0:39
Subject: Re: [jZebra] Suggestions on printing complicated HTML + Raster Receipt.

               qz.append("B5,26,0,1A,3,7,152, B,\"1234\"\nA310,26,0,3,1,1,N, \"SKU 00000 MFG 0000\"\n");
               qz.append("A310,56,0,3,1,1,N,\ "QZ PRINT APPLET\"\nA310,86,0,3,1,1,N,\" TEST PRINT SUCCESSFUL\"\n");
               qz.append("A310,116,0,3,1,1,N, \"FROM SAMPLE.HTML\"\nA310,146,0,3,1, 1,N,\"EDIT SAMPLE.HTML\"\n");
               qz.appendImage(base64data, "EPL", 150, 300);
               while (!qz.isDoneAppending()) {} //wait for image to download to java
               qz.append("\nP1,1\n");
               qz.print();
   }
   monitorPrinting();
      }
On Tue, Sep 24, 2013 at 5:51 PM, Alexander di Chiara <alexander...@gmail.com> wrote:
Hi Tres, hi everybody, 

this is Alex, nice to meet you all and thanks for all the suggestion i got from this great group till now.

I've parsed almost every post of the last year and i didn't find anything on my actual topic. 
Sure to have some advice i'll try to simplify below what i am doing. 

As the subject, i have 20+ different receipt to print in a vending machine (and that's fixed with linux) and the same to be available on smal PC based kiosks in different shops.
Being each one completely different from the others (logos, qr code, barcodes.. etc) it's very hard to approach this with a ESCP straight solution. Tonnes of lines and less compatibility with different printers available to the shops.

By now, that's what i've suppose to do in the last 2 days.
- Implemented perfectly jZebra --> OT: thanks, sounds great and by the way doesn't blame as much as Tres suggests, dunno why but in my chrome version (which is the same on all the machines) it's always working without additional permission requests. 

- Port all the tickets in pure and strong typed html5 including assets and no css. Is all about inline styles.

- Wrote this couple of functions (which is a replica for all ticket, whenever is gonna work): 

  var changeWindow = window.open('','','width=2,hei ght=2');

  if (printdata.type == 1) { // First type ticket
  changeWindow.document.write(su nrise);  
  var canvas = document.getElementById("hidde ns"); // Set the canvas

   $(changeWindow.document.body) .html2canvas({  // Raster the canvas 
                canvas: hiddens,
                onrendered: function() {
                
                    setTimeout(function () {changeWindow.close();} , 100);
                    var raster = canvas.toDataURL('image/png'); // Full data:image
                    var output = raster.replace(/^data:image\/( png|jpg);base64,/, ""); // Just the Base 64 data (see Second Option)
    
                    applet.setPaperSize("80mm", "175mm"); 
     applet.setAutoSize(true);
     applet.setOrientation("portra it");    

Tres Finocchiaro

unread,
Sep 26, 2013, 6:29:55 PM9/26/13
to jZebra users

Bahadir,

Since the OP needs the logo to change frequently, I think the download -each-time is a necessity.

IIRC, the flash process can be done with ESC/P as well.....

-Tres

Alexander di Chiara

unread,
Sep 26, 2013, 6:47:39 PM9/26/13
to jzebra...@googlegroups.com
Fully Agreed Tres thanks, and thanks Bahadir i've consider it for the vending machine and deployed a sample, but if now is a 20+ could be more than a hundred logos, and is not gonna happen, considering the total distribution.

Looking at the sample i think is for sure less difficult to implement it into jZebra. Tres, as i told you, any discussion is open, i am busy but tracking it on.

capp...@yahoo.com

unread,
Sep 26, 2013, 6:58:11 PM9/26/13
to jzebra...@googlegroups.com
and Tres, ESC * command is the print bit image command. there is also GS * and GS / but those are not commonly used.


From: Alexander di Chiara <alexander...@gmail.com>
To: jzebra...@googlegroups.com
Sent: Friday, 27 September 2013, 1:47

Tres Finocchiaro

unread,
Oct 2, 2013, 12:23:00 AM10/2/13
to jZebra users
Alexander,

I have implemented the code recommended by previous emails.

It doesn't throw any errors when I run it but I don't have a device yet to try it on.

Can you test it for me?

You'll need to call appendImage("/path/to/image.png", "ESCP"); from a JavaScript function similar to the Print ZPL Image button.

-Tres

Tres Finocchiaro

unread,
Oct 2, 2013, 12:23:58 AM10/2/13
to jZebra users
Sorry, forgot the link:


Extract only the "dist" folder and edit sample.html as needed.

-Tres

Alexander di Chiara

unread,
Oct 2, 2013, 10:29:02 AM10/2/13
to jzebra...@googlegroups.com
Tres,

for sure, thank you very much. I'll be out of the office till tomorrow morning Zurich Time. 

I'll go forward on test it ASAP tomorrow and let you know.

Thanks again,
Alex

Alexander di Chiara

unread,
Oct 3, 2013, 2:02:46 PM10/3/13
to jzebra...@googlegroups.com
Hi Tres,

being a busy moment, sorry had just half an hour to test today. 

Just the time to implement 1.6.3 jar into my code.. in the attach what's going on. 

Also by me no errors from the applet, and i let you notice that:

a) i'm forced to compile the png on the fly with canvas and is client side, so it's not really saved as a file but passed as a raster like data:image/png;base64,(code) in string.
b) some parts of the png are corrected (even if really small) and they got repeated correctly as the stream goes down. You can see them zooming my pic on the left.
c) just to help: seems like to me that some bit of the dot matrix shift down (or up) when closing the dpi region in height (if the code sample we took is assumed correct).

Tomorrow morning i have a good time off to test directly with png files and different sizes and i'll keep you posted.

Thank you so much by now.
Alex
ticket_test.jpg

Alexander di Chiara

unread,
Oct 4, 2013, 5:51:24 AM10/4/13
to jzebra...@googlegroups.com
Hi Tres,

after a further investigation and some more tests, i think we're almost there and i confirm is something on the byte appending.

I have printed the jzebra and a sample larger PNG. As you can see from the attachment on the left is the standard raster with chrome, on the right is qz.

Resolution is roughly 1/2 on the original, and if the image resides in the top left corner of the matrix is still okay.
If the image is larger and goes more than one quadrant, you can see what's happening. 

Last thing, there's no cut, i had a quick look at the code and the command isn't appended, so maybe is just that. 

Keep in touch, thanks,
Alex

Alexander di Chiara

unread,
Oct 4, 2013, 5:52:32 AM10/4/13
to jzebra...@googlegroups.com
Sorry the attachment was too big and refused, here we are ;)
ticket_test2.jpg

Tres Finocchiaro

unread,
Oct 4, 2013, 8:45:29 AM10/4/13
to jZebra users
Interesting.  As an experiment, can you make both image heights a multiple of 3 and try again?

-Tres

Alexander di Chiara

unread,
Oct 4, 2013, 11:08:28 AM10/4/13
to jzebra...@googlegroups.com
Yup, interesting. 

Okay, i did a couple of things at the same time to verify another story: 

Top and Bottom left, same images as before with height multiple of 3: 

a) It's graphically even worst for jZebra image (result broken) and it's more or less the same for the larger png. 
b) the spooler doesn't work on the fly and the printer hangs for some seconds, and then prints everything together. If image height is not multiple of 3, prints immediately. Clearly still no cut. 

Top and Bottom right, a taller image that still stands into 128px width. No matter what, even if is half in size, is not broken.
The bottom raster with chrome to show you that is "exactly" the half.

I have some ideas, let me give a better look to the code ;)

Alex
ticket_test3.jpg

Alexander di Chiara

unread,
Oct 4, 2013, 12:53:31 PM10/4/13
to jzebra...@googlegroups.com
Hi Tres, 

gave a look as i said, and comparing with the 128px width bound we have i'm pretty sure that's something related to this: 

builder.append(new byte[] {0x1B, 0x2A, 33, -128, 0});

-> 128, 0 // nH * 256 + nL -> this means max Width i think. Shouldn't be dynamically settled with bounds position of our getWidth(); ? 

I really have the cue that i can't go over 128px width for some reasons. Smaller are working with both the dimensions splitted in half, but not broken.

Just a clue, let me know ;)

Alex

Tres Finocchiaro

unread,
Oct 7, 2013, 9:03:26 PM10/7/13
to jZebra users
Alex,

I think you are correct (although I don't completely understand why the original author used a -128 instead of 128.

Here's the new code:
byte nL = (byte)((int)(getWidth() % 256));
byte nH = (byte)((int)(getWidth()/256));
builder.append(new byte[] {0x1B, 0x2A, 33, nL , nH});

I read the code more carefully and it appears the author pads the height of the image automatically to 24 pixels so height should not matter.

Width isn't an issue either since the data is sent in vertical slices 1px wide, so neither width nor height should break it.

Let me know how well it works.

Try it here:

-Tres

Alexander di Chiara

unread,
Oct 8, 2013, 5:14:57 AM10/8/13
to jzebra...@googlegroups.com
Tres,

Thanks Mate. 

The remainder op is actually a very cool idea. I think we're almost there! 

As you can see the printing is finally not broken, no problems with spooling and it's almost correct.
Sorry i had to photoshop mask some ticket conf parts ;)

I think, according to the epson paper, that my rasters are normally printed in single density. I wrote a small chrome USB api app to test it, and in single density prints full width. 
So, it's maybe a good suggestion to add a third argument to the API command that lets the developer select which kind of density he's using. (32 - Single, or 33 - Double.)

For all the rest is quick and responsive, and should be fine for production. 

A simple note on the cut: 

I'm using this trick to have a correct and fluid cut: 
applet.appendImage(raster, "ESCP");
setTimeout(function () {applet.appendHex("x1Dx56x41");} , 50);

using this code the cut happens before the raster, probably due to the raster composite timelapse:
applet.appendHex("x1Dx56x41");
applet.appendImage(raster, "ESCP");

and using this the spooler hangs for some seconds and sometimes there's no cut. 
if (applet.isDoneAppending()) { 
       applet.appendHex("x1Dx56x41");
applet.print(); }

Hope this also helps. 
Alex
density.png
ticket_good.png

Tres Finocchiaro

unread,
Oct 8, 2013, 9:52:54 AM10/8/13
to jZebra users
A slightly safer way to time the cut properly (not very obvious in the sample.html) is this method:

function jzebraDoneAppending() {
   if (qz != null) {
 
      // Applet not loaded
      alert("Applet not loaded!");
   } else if (qz.getException() != null) {
   
      // Some error occured
      alert(qz.getException().getLocalizedMessage());
   } else {
 
       // Cut the paper 
      qz.appendHex("x1Dx56x41");
   }
}

// Warning, due to re-branding, future versions will deprecate jzebraDoneAppending() (i.e. in favor of "qzDoneAppending()", etc).

In terms of the single/double density, I'll add that feature tonight.  Proposed usage:

// Single density:  Default behavior.  Image's natural size.
qz.appendImage("/path/to/image", "ESCP", "single");
//or 
qz.appendImage("/path/to/image", "ESCP", 32);
 
 

// Double density:   May make image appear smaller (higher resolution)
qz.appendImage("/path/to/image", "ESCP", "double");
//or
qz.appendImage("/path/to/image", "ESCP", 33);


-Tres

Tres Finocchiaro

unread,
Oct 8, 2013, 9:54:26 AM10/8/13
to jZebra users
*typo:

function jzebraDoneAppending() {
   if (qz == null) {
 
   ...

Alexander di Chiara

unread,
Oct 8, 2013, 3:13:39 PM10/8/13
to jzebra...@googlegroups.com
Thanks, confirming thiscutting is safe too, at this point should i completely deprecate isDoneAppending() in anycase, right?

Sure, sounds perfect, IMHO considering you're keeping the comment in the source i would vote and prefer the decimal version compared to the text one, just cause with a quick esc/pos guide search the user has two solid relevant hooks to say is doing it right. Searching the pdf for single or double density quickly recap on 32 and 33, and let you think you're good on the road. 
Being the commands x3 bytes or 24 bits or dots, i would also consider to specify it in the comments for future use, saying something like 24 dots Single density etc...

It's also true that for consistency all the arguments are strings with "single", but javascript coders does not mind so much about types in general. 
For sure, you choose ;)

Cheers.

Tres Finocchiaro

unread,
Oct 8, 2013, 10:54:21 PM10/8/13
to jZebra users
Alex,

I have to thank you again for all of your help.  I've added "single", "double" and "triple" as options. :)

Try it out and let me know your success.  There's a button provided with the sample.html.

The isDonePrinting() is not a bad approach and will remain in future versions, however using function jzebraDoneAppending() just makes the code easier to manage.

Here's 1.6.5.  If the bit density setting works well for you, I'll feature it on the front page.


-Tres

Alexander di Chiara

unread,
Oct 9, 2013, 9:58:40 AM10/9/13
to jzebra...@googlegroups.com
Tres,

you're very welcome, thanks a lot to you too, we're quite a good team :)

In attach the final solution, i've even set the resolution to double density in some heavy graphic tickets to have the QR code printed perfectly, which means a very good phone scan.

Just 2 little thing to complete the production step, and probably they are my fault. Every couple of printings the windows spooler is not flushed and the job stays there. 

At the same time i have this (HOO ! something.. or j e or 3, printed on the top left corner of same samples, not all the time, like above let's say 2/3rd of the time and it seems connected to the no flush in the spool. 

Code is the same as before, maybe there's a better way to "close" the print job?

Let me know your ideas! 
Thanks again for everything.
ticket_good.jpg

Tres Finocchiaro

unread,
Oct 9, 2013, 1:45:14 PM10/9/13
to jZebra users
Thanks.  Does ESC @ reset the printer and clear that message?

I don't currently have a way of "clearing" the spooler, so this needs to be resolved before I advertise this as working...  Any help from the ESC/POS users out there is greatly appreciated.

-Tres

Alexander di Chiara

unread,
Oct 10, 2013, 6:49:36 AM10/10/13
to jzebra...@googlegroups.com
Ok thanks, i will try to experiment this afternoon and let you know. 

Mao Rodriguez

unread,
Apr 9, 2014, 6:33:02 PM4/9/14
to jzebra...@googlegroups.com
My main problem is that the image is cut ESCP and qz-print-free_1.8.0_src.7z. Attached image.

code:

qz.appendImage(getPath() + "img/image_sample_x2.png", "ESCP", "32");
qz.print();

thanks
IMG_20140409_170501.jpg

Tres Finocchiaro

unread,
Apr 9, 2014, 8:11:07 PM4/9/14
to jZebra users
Yes, it appears to be ignoring the line-height setting here:


You could try "32" or "single" instead but I doubt it will help.

I'm not entirely sure what would cause this.  What printer make and model are you using?

As Bahadir had originally suggested, he prefers the flash utility for loading images, although I understand this is not ideal for most web clients.

-Tres

Mao Rodriguez

unread,
Apr 11, 2014, 11:49:31 AM4/11/14
to jzebra...@googlegroups.com
Hello, my printer is an Epson RAW t90 ESC / POS, try from the application that comes with it and prints normally, this is the error when printing from qz-print, and you try 32, 33, 1, 2, "single" and "double" without any changes. my last options are to try experimenting with earlier versions and putting the paper width settings to see if it helps.

Tres Finocchiaro

unread,
Apr 11, 2014, 12:57:15 PM4/11/14
to jZebra users
There must be something incompatible with our code and your printer.

If you can review the source code and offer recommendations we would be happy to incorporate it into the next build.


-Tres
On Fri, Apr 11, 2014 at 11:49 AM, Mao Rodriguez <rpmo...@gmail.com> wrote:
Hello, my printer is an Epson RAW t90 ESC / POS, try from the application that comes with it and prints normally, this is the error when printing from qz-print, and you try 32, 33, 1, 2, "single" and "double" without any changes. my last options are to try experimenting with earlier versions and putting the paper width settings to see if it helps.

--
--
To unsubscribe from this group, send email to jzebra-users...@googlegroups.com
 
http://code.google.com/p/jzebra

---
You received this message because you are subscribed to the Google Groups "jZebra users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to jzebra-users...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply all
Reply to author
Forward
0 new messages