0

I have a Java Swing app in which the user can generate a PDF file from a JPanel. But it takes more than 6304 milliseconds to generate that single JPanel screenshot.

Here is the code I use :

private void printStamp()
{
  long startTime=System.currentTimeMillis();

  if ( panelPhoto.isALabelSelected == false )
    {
       notificationErrorPopup("No stamp is selected !");
    }
  else
    {
    Document document = new Document();
    try
      {
        PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(
                            "C:\\Users\\Admin71\\Desktop\\test1.pdf"));
        writer.setCompressionLevel(0);
        document.open();
        PdfContentByte contentByte = writer.getDirectContent();
        PdfTemplate template = contentByte.createTemplate(panelBasTotal.panelShow.getWidth(),
                                panelBasTotal.panelShow.getHeight());
        Graphics2D g2 = template.createGraphics(panelBasTotal.panelShow.getWidth(),
                                panelBasTotal.panelShow.getHeight());
        g2.scale(1.0d, 1.0d);
        panelBasTotal.panelShow.printAll(g2); // also tried with jp.paint(g2)
        panelBasTotal.panelShow.addNotify();
        panelBasTotal.panelShow.validate();
        g2.dispose();
        contentByte.addTemplate(template, 0, 0);
      }
    catch (Exception e)
      {
        e.printStackTrace();
      }
    finally
      {
        if ( document.isOpen() )
        {
            document.close();
        }
      }
    System.out.println("Duration of Pdf printing :" + (System.currentTimeMillis()-startTime));
  }
}

Am I doing something wrong or is this delay normal ?

Zek101
  • 203
  • 4
  • 13
  • Can't you post a [short complete runnable example](http://stackoverflow.com/help/mcve) we can test out. – Paul Samsotha Sep 04 '14 at 03:30
  • 1
    Also try creating an image from the panel first, as seen [here](http://stackoverflow.com/a/25580014/2587435). See if there's any difference. – Paul Samsotha Sep 04 '14 at 03:34
  • I am afraid that would bring flames: the JPanel itself contains more than 900 lines. – Zek101 Sep 04 '14 at 03:34
  • Ok peeskillet thank you for the advice, I will try that ! – Zek101 Sep 04 '14 at 03:36
  • 2
    Drawing content using *native* PDF operators and operands is *fast*. Drawing through `Graphics2D` uses Java methods that are passed to `PdfGraphics2D`. First you lose time on the Java side to create all the graphical operations to draw the `JPanel`; then all these Java-related graphical operations are translated into PDF operations in a way that isn't as optimal as when a human being would code the PDF syntax. To make an anology: creating HTML from Word can never be as good as writing HTML manually. By choosing `Graphics2D` over native PDF, you're introducing several levels of complexity. – Bruno Lowagie Sep 04 '14 at 06:05
  • Thanks for the precisions Bruno ! – Zek101 Sep 04 '14 at 20:46

1 Answers1

0

Following peeskillet's advice and taking inspiration from the link he has provided, I have managed to reduce the generation time from about 6.5 seconds to about 2.5 seconds which is now a perfectly acceptable time.

Here is the new code:

    private void printStamp()
    {
        long startTime = System.currentTimeMillis();
        if ( panelPhoto.isALabelSelected == false )
            {
                notificationErrorPopup("No stamp is selected !");
            }
        else
            {
                try
                    {
                        String fileName = "C:\\Users\\Admin71\\Desktop\\test1.pdf";
                        int width= panelBasTotal.panelShow.getWidth();
                        int height=panelBasTotal.panelShow.getHeight();
                        final java.awt.Image image = getImageFromPanel(panelBasTotal.panelShow, width, height);

                        Document d = new Document(new com.itextpdf.text.Rectangle (width, height));
                        PdfWriter writer = PdfWriter.getInstance(d, new FileOutputStream(fileName));
                        d.open();

                        Image iTextImage = Image.getInstance(writer, image, 1);
                        iTextImage.setAbsolutePosition(0f, 0f);
                        iTextImage.scalePercent(100);
                        d.add(iTextImage);
                        d.close();
                    }
                catch (Exception e)
                    {
                        e.printStackTrace();
                    }

                System.out.println("Time spent:" + (System.currentTimeMillis() - startTime));
                notificationInfoPopup("Pdf generation finished !");
            }
    }

public static java.awt.Image getImageFromPanel(Component component, int width, int height)
    {
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        component.paint(image.getGraphics());
        return image;
    }
Zek101
  • 203
  • 4
  • 13