9

Using JasperReport to generate an image, and then trying to print that image on a Zebra printer GC420t. The image is generated but not printing. I have double checked the connection and ports. I have read this SO link and also the calibration one, but nothing works.

Code:

public void generateReport(Map<String, Object> parameters, List<Label> labels)
            throws JRException, IOException, ConnectionException, ZebraPrinterLanguageUnknownException{
        // TODO Auto-generated method stub
        JRBeanCollectionDataSource dataSource = new JRBeanCollectionDataSource(labels);
        System.out.println(" Wait !!");
        JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, parameters, dataSource);
        if(jasperPrint != null && jasperPrint.getPages()!=null && jasperPrint.getPages().size()>=0){
            FileOutputStream fos = new FileOutputStream("C:\\Users\\desktop\\Labels.png");
            //JasperExportManager.exportReportToPdfStream(jasperPrint, fos);
            BufferedImage rendered_image = null;
            rendered_image = (BufferedImage) JasperPrintManager.printPageToImage(jasperPrint, 0, 1.6f);
            ImageIO.write(rendered_image, "png", fos);
            Connection thePrinterConn = new DriverPrinterConnection("GC420t");
            try{
                for (DiscoveredPrinterDriver printer : UsbDiscoverer.getZebraDriverPrinters()){
                    System.out.println(printer);
                }
                thePrinterConn.open();
                if(zPrinter==null){
                    zPrinter = ZebraPrinterFactory.getInstance(thePrinterConn);
                }
                PrinterStatus printerStatus = zPrinter.getCurrentStatus();
                if(printerStatus.isReadyToPrint){
                    System.out.println("Ready to print !!");
                    DocFlavor flavor = DocFlavor.INPUT_STREAM.AUTOSENSE;
                    DocAttributeSet das = new HashDocAttributeSet();
                    FileInputStream fis = new FileInputStream("C:\\Users\\desktop\\Labels.png");
                    Doc mydoc = new SimpleDoc(fis, flavor, das);
                    PrintRequestAttributeSet aset = new HashPrintRequestAttributeSet();
                    aset.add(OrientationRequested.PORTRAIT);
                    @SuppressWarnings("unused")
                    PrinterJob pj = PrinterJob.getPrinterJob();
                    PrintService[] services = PrintServiceLookup.lookupPrintServices(flavor, aset);
                    PrintService defaultService = PrintServiceLookup.lookupDefaultPrintService();
                    for (int i = 0; i < services.length; i++){
                      System.out.println(services[i].getName());
                    }
                    if(services.length == 0){
                        if(defaultService == null){
                         //no printer found
                        }
                        else{
                            //print using default
                            DocPrintJob job = defaultService.createPrintJob();
                            try{
                                job.print(mydoc, aset);
                            }catch (PrintException e){
                                // TODO Auto-generated catch block
                                e.printStackTrace();
                            }
                        }
                    }
                    else{
                         PrintService service = ServiceUI.printDialog(null, 200, 200, services, defaultService, flavor, aset);
                         if (service != null){
                             DocPrintJob job = service.createPrintJob();
                             try{
                                 job.print(mydoc, aset);
                             }catch(PrintException e){
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                             }
                        }
                   }
                   //ZebraImageI image = ZebraImageFactory.getImage("C:\\Users\\desktop\\Labels.png");
                }
                else{
                    System.out.println("Something went wrong");
                }
            }finally{
                thePrinterConn.close();
            }
            System.out.println("Report generated !!");
        }
    }

I read the EPL 2 manual and converted the image into binary graphic data for immediate printing.

Code:

private byte[] getEplGraphics(int top, int left, BufferedImage bufferedImage) throws IOException {
        ByteArrayOutputStream fs = new ByteArrayOutputStream();

        //int canvasWidth = bufferedImage.getWidth();
        // loop from top to bottom
        System.out.println(bufferedImage.getHeight());
        System.out.println(bufferedImage.getWidth());

        int maxY = bufferedImage.getHeight() + (64- bufferedImage.getHeight()%64);
        int maxX = bufferedImage.getWidth() + (64- bufferedImage.getWidth()%64);
        System.out.println(maxX);
        System.out.println(maxY);
        int p3 = maxX / 8;
        int p4 = maxY/ 8;
        int len = 0;
        String gw = "N\nGW0,0," + p3 + "," + p4 + ",";
        fs.write(gw.getBytes());
        for (int y = 0; y < maxY; ++y) {
            // from left to right
            for (int x = 0; x < maxX;) {
                byte abyte = 0;
                // get 8 bits together and write to memory

                for (int b = 0; b < 8; ++b, ++x) {
                    // set 1 for white,0 for black
                    int dot = 1;

                    // pixel still in width of bitmap,
                    // check luminance for white or black, out of bitmap set to white

                    if (x < bufferedImage.getWidth() && y < bufferedImage.getHeight()) {
                        int c = bufferedImage.getRGB(x, y);
                        int red = (c & 0x00ff0000) >> 16;
                        int green = (c & 0x0000ff00) >> 8;
                        int blue = c & 0x000000ff;
                        Color color = new Color(red, green, blue);
                        int luminance = (int) ((color.getRed() * 0.3) + (color.getGreen() * 0.59)
                                + (color.getBlue() * 0.11));
                        dot = luminance > 127 ? 1 : 0;

                    }

                    abyte |= (byte) (dot << (7 - b)); // shift left,
                    // then OR together to get 8 bits into a byte
                }

                // System.out.print( (char)(abyte + 48 ) );
                // write here
                len++;
                fs.write(abyte);
            }
        }
        System.out.println("GW Length::"+len);
        // Assign memory position here
        // fs.write('\n');
        fs.write("\nP1".getBytes());
        fs.flush();
        // System.out.println(fs);
        return fs.toByteArray();
    }

After converting the image into binary graphics data, it's not printing the data.

How can I get the printer to print the image?

Dave Jarvis
  • 30,436
  • 41
  • 178
  • 315
Lokesh Pandey
  • 1,739
  • 23
  • 50
  • What's the image size? Most of those EPL printers are 203 dpi and there are physical limitations to what they can print. – tresf Sep 12 '17 at 15:01
  • The image size is width 384 pixel and height 288 pixel. I am trying to print the image size of 4/3 – Lokesh Pandey Sep 13 '17 at 03:08
  • A side note** it's printing in zpl but i want it in epl – Lokesh Pandey Sep 14 '17 at 08:04
  • @Lokesh, why are you dividing the height by 8? The height should be the pixel height of the image, not the byte height. The EPL manual, p. 108 states the width -- `p3` -- is in bytes however the height -- `p4` -- (referred to as "length") is in dots, i.e. pixels. – tresf Sep 14 '17 at 15:10
  • In regards to image dimension, `384x288` would be a 1.9 x 1.4 inches which should be easily supported by the hardware you've mentioned and is fortunately divisible by 8 making the byte padding less of a concern while prototyping. – tresf Sep 14 '17 at 15:14
  • I know but what is the problem I am not getting it's not printing the image – Lokesh Pandey Sep 15 '17 at 02:43
  • @community the bounty has been expired, And I have 23 hours to award. But I have only received one answer from petter and that didn't answer the question properly. I am not sure what am I supposed to do ? Need help. – Lokesh Pandey Sep 19 '17 at 03:14
  • 1
    assuming you've already successfully sent other EPL commands to the printer but the image is the only outstanding issue, you can baseline test by comparing the output from your program with the output from a known working program, such as QZ Tray. Use a Generic/Text driver and print to `file:` port. The `sample.html` has an EPL button that prints an image. Assuming the baseline works, compare the files with a hex editor and observe the differences. Try to use a pure black/white to account for luminosity. I'd link the source code, but it's in Java. Disclaimer, I'm the author of QZ Tray. – tresf Sep 19 '17 at 19:57

1 Answers1

1

Using jasper-reports, render an image, convert image to EPL and send to zebra printer, is normally not the correct solution to print on a thermal printer. This kind of code is not only slower, but you can also have lower resolution (which may produce problems for example with barcodes)

You have two standard options

  1. Use the printer protocol and send a text file.

  2. Install the printer driver and use the JRPrintServiceExporter

Using the printer protocol

This is what I normally use (mostly to get code bars printed perfectly, no image, but direct command to print code bar). You will not use jasper-reports for this, instead you setup your txt file (you can use a design program in your case zebra-designer) and then you use libraries like freemarker to replace/insert dynamic data in your direct protocol file. When done you send it directly to printer for example via serial port (also wireless using bluetooth-serial adapter)

Using printer driver

In this solution you need to install the correct printer driver and then you use this driver to send a print job. In jasper-report to send a printer job you use code like:

PrintRequestAttributeSet printRequestAttributeSet = new HashPrintRequestAttributeSet();
//set page size etc if you need to
PrintServiceAttributeSet printServiceAttributeSet = new HashPrintServiceAttributeSet();
//set print service attributes
JRPrintServiceExporter exporter = new JRPrintServiceExporter();
exporter.setExporterInput(new SimpleExporterInput(jasperPrint));
SimplePrintServiceExporterConfiguration expConfig = new SimplePrintServiceExporterConfiguration();
String printerName = "myPrinterName"; //Check the name of printer
PrintService service = Printerlookup.getPrintservice(printerName, Boolean.TRUE, Boolean.TRUE);
expConfig.setPrintService(service);
expConfig.setPrintRequestAttributeSet(printRequestAttributeSet);
expConfig.setPrintServiceAttributeSet(printServiceAttributeSet);
expConfig.setDisplayPageDialog(Boolean.FALSE);
exporter.setConfiguration(expConfig);
exporter.exportReport(); 

If your are not printing correctly your debug method is to export to pdf and then use the print dialog from pdf to print to printer (remember you are using driver, so you can select it in dialog)

With pdf

  • it prints correctly! - Crap, that's strange but you have a workaround (export to pdf and print that)

  • it does not print correctly! - Crap, the driver is not working as it should be (contact supplier), and while they are working try with different image types (I would try with .bmp), check all settings in printer dialog (these you can set to later to printRequestAttributeSet).

I don't care, I'm actually only interested in converting png to EPL2 language

Please update question, remove jasper and instead show png image, show expected output and show current output, this is some code that can help you with this, but be sure first that you really don't care:

Use ZEBRA SDK see printImage command

ZebraPrinter printer = ZebraPrinterFactory.getInstance(connection);
printer.printImage("sample.jpg", x, y);

Using the EPL2 GW command it's in C# but languages are similar

How to convert image to PCX see code.zip file ToPCX.java

Petter Friberg
  • 21,252
  • 9
  • 60
  • 109
  • Thank you for your time and answer, it was working correct for pdf in my case also. But I want to print an image using EPL and you code doesn't look like that. Can you tell me by looking at my code is that a nice way to convert an image into raw one. Because an EPL it convert the graphic data into raw and then prints. – Lokesh Pandey Sep 16 '17 at 03:01
  • as far as converting your image to EPL probably an easy way to check is to use the zebra design program, design a label with same image and print it to file, you will get the result, do the same with your program, this way you can check if you are correct. I have not tested with zebra, but it works with other printers as honeywell using the bartender program. – Petter Friberg Sep 16 '17 at 10:09
  • @Lokesh but looking at the code you provided it seems like you are sending EPL commands through the printer driver (and AFIK this is not correct), If you like to send EPL commands you should be connected directly to printer (for example using serial port). – Petter Friberg Sep 16 '17 at 10:19
  • Yea I am connected directly through the printer – Lokesh Pandey Sep 16 '17 at 10:22
  • @Lokesh maybe you can use the SDK that zebra provides, it surely has methods to convert image https://www.zebra.com/us/en/products/software/barcode-printers/link-os/link-os-sdk.html. – Petter Friberg Sep 16 '17 at 10:40
  • I have already gone through the documentation, they provide printImage() function and that function does everything. But the problem here is to get this function we need to instantiate a Zebra instance and also get the DriverConnection which only works in window. Zebra doesn't have anything for linux users. That why I have come around this solution converting it to EPL format and then print – Lokesh Pandey Sep 16 '17 at 10:47
  • so your are basically asking how to convert an image to pcx in java?, that's what your really interested in? – Petter Friberg Sep 16 '17 at 10:51
  • My question is how could i convert an image into raw one according to EPL standard and print it. – Lokesh Pandey Sep 16 '17 at 10:54
  • Not sure why you have the jasper-reports tag, if you like to send EPL command you should not pass through driver anyway later I will check if I can give you an example of output of EPL command that would print an image if connected correctly to printer. – Petter Friberg Sep 16 '17 at 11:29
  • I have included that because my code contains some jasper syntax so to avoid confusion – Lokesh Pandey Sep 16 '17 at 11:36
  • 1
    @Lokesh I found some link that you can check for how to covert to PCX, this is related to [EPL but in C#](https://web.archive.org/web/20140315232324/http://nicholas.piasecki.name/blog/2013/02/using-the-epl2-gw-command/) and here you can find [code on how to covert to pcx using java](http://www.informit.com/articles/article.aspx?p=684049&seqNum=5) check the code.zip it has a ToPCX class, they will both do no dithering of the image but from what I see in your code your not searching for that – Petter Friberg Sep 18 '17 at 07:13
  • This answer does not help the question. The OP is asking for EPL advice, which is a raw/control language syntax problem. EPL needs no driver. Please do not make assumptions about the technology being used. – tresf Sep 19 '17 at 19:39
  • @QZSupport I kind of agree even if I think OP is maybe creating an XY problem as question is posted. He would have the possibility to use driver (since he has an jasper-print) and if question was only focused on converting a a png image to EPL (hence png --> pcx), the question probably should have been focused only on this (not including jasper, since this will confuse future users using jasper), I added an comment with links to code on how to covert png to pcx, but I have not had feedback yet, if I get some time, I will try it (but can only test on intermec) – Petter Friberg Sep 19 '17 at 19:52
  • @PetterFriberg on Windows, the ZDesigner driver works with raw EPL, ZPL as well as graphical data so the proposed solution generally works too. We have the request working in Java here: https://github.com/qzind/tray/blob/91b4ae146e72d2e702a2a32b4c9b46f4e64f1278/src/qz/printer/ImageWrapper.java#L327-L333 – tresf Sep 19 '17 at 20:05
  • Also, the fact that the OP has stated he's already successfully printed the same image with ZPL -- successfully -- suggests the raw route is a preferred technique in this question. – tresf Sep 19 '17 at 20:09
  • @QZSupport What I'm trying to answer is that to first generate image with jasper-report and then try to print it via EPL seems like you are doing an incorrect software solution, I'm still either you go the EPL way and put your text (report) directly in file (send as text ecc) or you go the jasper-report way and use the printer driver (in both solution the result will be better, then this hybrid way). – Petter Friberg Sep 19 '17 at 20:15
  • 1
    *then yeah I can agree, "don't care about what I do, tell me how to convert a png to EPL2", but then the question should be concentrate on this, as it is it would be really bad-practice to give indications that the solution to print to zebra is using jasper-report --> render image and then covert it to send it via EPL* – Petter Friberg Sep 19 '17 at 20:17
  • Yes, the Jasper portion of the question is simply irrelevant to the technical problem and should probably be removed. – tresf Sep 19 '17 at 20:23
  • @QZSupport yes either this, or the user maybe should remove jasper and send text directly or use the printer driver as described in answer, hence why I still feel that the answer is relevant. Printing a label first using jasper then rendering an image, then converting to pcx, then sending as image to printer is not normally a correct solution, since both the resolution and the velocity of similar solution will be reduced. – Petter Friberg Sep 19 '17 at 20:44
  • 1
    These raw languages really suffer in two areas... 1. Multilingual support and 2. Layout. EPL and ZPL are pretty decent for layout (as opposed to some others, like ESC/POS), but still can only print basic geometric shapes and require learning the raw language. Converting from image to raw is especially helpful when only a portion of the document is graphical. This may seem bad design, but it's not as uncommon as one would think, especially when mixing with other device-specific raw commands. The OP hasn't explained the content, so this answer is optimistically presumptuous. – tresf Sep 19 '17 at 20:59
  • @QZSupport To be honest instead I often see people miss-using this also sending image's of barcodes, often the most simple solution as using a design program, export to file and use freemaker or similar to substitute/add your dynamic text is a much cleaner and better solution. This question if only focused on png --> EPL2 needs example of image, example of code, current output, expected output, I'm still not sure what do with this answer the question is tagged with jasper and I really do not think people should see OP questions as good solution to print to zebra. – Petter Friberg Sep 19 '17 at 21:10
  • @PetterFriberg It's requirement to create a report in image format and then print it to automate things. So I don't know why it's a incorrect software solution. And also as i already mentioned my code contains some jasper syntax so i had to mention it. People who know about jasper they understood what it there doing. And to print I have another function which is doing that. So I don't see any confusion here. – Lokesh Pandey Sep 20 '17 at 02:50
  • @PetterFriberg I am following your link thanks for that. – Lokesh Pandey Sep 20 '17 at 02:53
  • @Lokesh I'm a [jasper answerer](https://stackoverflow.com/tags/jasper-reports/topusers), The problem with your solution is that you may have problem reading for example barcodes, this since to correctly print barcodes on thermal printer you need to follow predefined density (that respects resolution dpi of printer head) also you are going a long way to print which normally is not needed,hence develop jrxml, fill report, export image, convert image to epl, send epl. I would see your solution in general as a bad solution to print zebra or print to thermal printer from jasper (hence the answer). – Petter Friberg Sep 20 '17 at 06:51
  • *but then again I don't know all your requirements, why you are doing this, I see only someone in question trying to print from jasper-reports to a zebra printer and I'm trying to answer with what I believe is best solution to achieve this.* – Petter Friberg Sep 20 '17 at 06:54
  • Probably if you are trying to make a standard framework that works with jrxml and creates a EPL2 file, the best way would be to develop a custom [JRExporter](http://jasperreports.sourceforge.net/api/net/sf/jasperreports/engine/JRExporter.html), that converts text in jasper report to text command, barcodes to barcode command, lines to line commands ecc. – Petter Friberg Sep 20 '17 at 06:57