How to Print Java Screens

Important! You may do well to start with this more recent List of Java Image Software maintained by Marco Schmidt. I have not updated this page in over a year, so some problems may well have been solved in better ways. I believe this page is still useful, if you think not please let me know.
Here is a recent addition, Portable Network Graphics (PNG) encoder. Thanks to David Eisenberg at david@catcode.com

Support for printing a screen was absent in Java 1.0, and added in 1.1, but with a number of bugs, both in the concept and implementation. Some problems remain in the 1.2 version.

The general idea is the same as for drawing to an offscreen buffer. First obtain a "special" Graphics g context, and recreate your screen, using this context for all the regular drawing operations. In the case of an offscreen buffer, the result is drawing into a bitmap or pixelmap.

Here, with a different specialized Graphics context, the result is writing a file of PostScript commands. Since PostScript also has commands like drawString and drawLine, it is more or less a direct translation. You then send this file to a printer that understands PostScript. The result is finally drawing a bitmap on paper.

The standard 1.1 example goes like this:

    Toolkit tk;
    if (null != (tk = Toolkit.getDefaultToolkit ())) {

/* This launches a Print Dialog,
 * that's why it needed aFrame to construct the Dialog.
 * Dialog details depend on platform.
 * There are a set of properties you can pass in and out,
 * but they depend on platform,
 * will someday be standardized they tell us. */

        PrintJob pj = tk.getPrintJob
           (aFrame,
            aFrame.getTitle () + " print",
            (Properties)null);

/* Null if user cancels out -- otherwise go ahead */

        if (null != pj) {

/* Graphics context which produces PostScript code,
 * that can be rendered by a PostScript printer or viewer,
 * instead of actually drawing into a bit map,
 * that shows up on the screen. */

            Graphics pg = pj.getGraphics ();
            if (null != pg) {

/* Do not assume defaults -- set them */

                Font myFont = top.getFont ();
                if (null == myFont)
                    myFont = new Font("Courier", Font.PLAIN, 14);

                pg.setFont(myFont);

/* Walk your tree and render everything into Graphics pg.
 * This method defaults to paint () for Component,
 * but many things override it,
 * especially all peer-based (AWT) components,
 * because they do not **really** draw into g,
 * but g tells them **how** to draw.
 * And here we really do have to draw into g,
 * to generate the PostScript code. */

                top.printAll (pg);

/* The dispose flushes it to be printed,
 * or closes the file if that was the destination. */

                pg.dispose ();
            }

/* We could get another pg and print another page... */

            pj.end ();
        }
    }
Well, that's really not hard, too bad it doesn't work, for a couple of reasons --

I have been able to work around these problems, with the aid of some code that others have written, copyrighted, and shared with the public.

PSGr
PSGr (the PostScript Graphics Context) implements all public methods of the Graphics class, for example drawRect () and drawString () but instead of drawing on the screen, it writes a file of the equivalent PostScript commands for printing. Unlike the awt offering, PSGr offers additional (non-Graphics) public methods related to PostScript, with scale () the one of most interest here. PSGr was written and is copyright by Ernest Friedman-Hill email at ejfried@ca.sandia.gov I did the port from 1.0 to 1.1 Java, that is available here.
JpegEncoder
JpegEncoder processes an Image, and produces a compressed JPEG encoding of that Image. For our purpose, the Image will be an OffScreenImage, for which we can do getGraphics (), and into which we draw to replicate the Java screen. JpegEncoder was written and is copyright by James R weeks email at james@obrador.com
GifEncoder.java
Produces a GIF compressed encoding of an Image, again for our purpose, an OffScreenImage, into which we have replicated the Java screen. Written and Copyright (C) 1996 by Jef Poskanzer email at jef@acme.com

I have made two minor but useful additions to GifEncoder:

ImageEncoder.java
Base class for GifEncoder, and for some other encoders too. See the acme site.
IntHashtable.java
Support class for GifEncoder.
BitmapEncoder.java
Produces a Microsoft Windows Bitmap Encoding. Again for our purpose, from an OffScreenImage, into which we have replicated the Java screen. Written by Jean-Pierre Dubé, and presented as Java Tip 60, by Javaworld
LoadBitmap.java
LoadBitmap is not part of this demo, it is for input rather than output. It allows your Java program to load and display a Microsoft Windows Bitmap Encoded image, as easily as a GIF or JPG image. Written by Jeff West, with John D. Mitchell, and presented as Java Tip 43, by Javaworld

What I am doing here is trying to make these classes better known, providing an example of their use, and also providing some additional useful code. I want to stress that this is not a "mirror site" or support site for these classes, and I certainly am not taking credit for them.

If you find them useful, by all means thank the original authors, and please let me know too. If you have any problems with the code presented here, please write to me, and do not bother the original authors.

You might want to visit the original sites, and see if they have newer versions.

You also might want to drop Sun a note, and ask why they still don't provide these things.

Because applets are not allowed to print or save files, the example is written as an application. You will have to download the sources and compile it.


Please see my otherJava Techniques

Please also visit theMorris Hirsch home page.

Was this Helpful?

Was this Helpful? Was it what you were looking for? How did you find this page? Search result, following a link, recommendation? Please let me know.

Finally, if you did NOT find this page useful, or you think the information is out of date, or you know other information that should be mentioned here, please let me know that too. Email me at morris_hirsch@brown.edu

Legalities

This software is provided free of charge with no support. Email me at morris_hirsch@brown.edu if you do have a problem, and I will try to help, but I cannot promise to.

Except for all sections which are identified as the work, and copyright, of others, this work is Copyright (C) 1998 by Morris Hirsch. All rights reserved, except as granted here.

Redistribution and use in source and binary forms, with or without modification, for any purpose, are permitted, except as may be restricted by original copyright holders, provided that the following conditions are met:

DISCLAIMER

This software is provided free of charge with no support.
This software is provided in source format; You are advised to examine it and understand it, before putting it to use.
This software uses only algorithms and coding techniques that are available to the public in the open literature. You are however, advised to make your own determination of legality, for your intended use.
This software is provided by the Author and Contributors ``AS IS'' and any express or implied warranties, including, but not limited to, the implied warranties of merchantability and fitness for a particular purpose, are disclaimed.
In no event shall the Author or Contributors, or their Agents, be liable for any direct, indirect, incidental, special, exemplary, or consequential damages (including, but not limited to, procurement of substitute goods or services; loss of use, data, or profits; or business interruption) however caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way out of the use of this software, even if advised of the possibility of such damage.
1