The JavaDocs indicate that the GraphicsEnvironment supports "screen and printer devices".
I can see how to obtain information about screen devices, but I can't seem to be able to find out information about how to obtain informaiton about a Printer Device.
Basically, when printing, I want to be able to create a compatible buffered image by using the devices GraphicsConfiguration.
The main reasons for wanting to do this is:
- We want to buffer a page request on the first request of the page and simply paint back the buffer on subsequent requests of the page (as the page contains a number of images and some complex rendering - rather then wasting time painting each page request, we want to use a buffer)
- Maintain the high resolution output of the printer. We have found that if we paint directly to the printers Graphics context, we obtain a substantually higher quanity output then we do if we try and use a buffered image of the same size.
I've tried searching the JavaDocs and Google without luck.
Any suggestions??
Cheers
Updated based on additional ideas
Based on additional ideas, it has been suggested to try using something like...
GraphicsConfiguration conf = ((Graphics2D) graphics).getDeviceConfiguration();
assert conf.getDevice().getType() == GraphicsDevice.TYPE_PRINTER;
System.out.println("Device: " + conf.getDevice().getIDstring());
final AffineTransform trans = conf.getDefaultTransform();
double dpi = trans.transform(new Point2D.Float(72, 0), null).getX();
System.out.println(dpi + " DPI");
Rectangle bounds = conf.getBounds();
System.out.println("page size: " + bounds.width + "x" + bounds.height);
// now you could do
buffer = conf.createCompatibleImage(bounds.width, bounds.height);
// verify values, you wouldn’t do this in production code:
Which does actually generate a BufferedImage
which would be translated to the printers DPI
To make testing easier, I wrote a simple print
method...
public void print(Graphics2D g2d, double width, double height) {
Font font = g2d.getFont();
font = font.deriveFont(64f);
g2d.setFont(font);
FontMetrics fm = g2d.getFontMetrics();
String text = "Hello World!";
double x = (width - fm.stringWidth(text)) / 2;
double y = (height - fm.getHeight()) / 2;
g2d.drawString(text, (float) x, (float) y);
}
Which I could user either the printer Graphics
context or other Graphics
context.
Now obvious, when printing to an A4 page @ 72dpi, the resulting image size is 595x841, at 600dpi (which was been reported by the example above), this results in an image of 4970x7029. Okay, this is fine, I'll only need to scale the image down when drawing to the target printer Graphics
context using something like...
g2d.drawImage(buffer, 0, 0, (int) pageFormat.getImageableWidth(), (int) pageFormat.getImageableWidth(), null);
(This is test, so don't jump on me about quality related issues just yet)...
(Normal on the left, BufferedImage
on the right)...okay, that won't do
So, I then thought, I could apply an AffineTransform
scale to the buffer Graphics
context, using something like...
double scale = dpi / 72d;
AffineTransform scaleAT = AffineTransform.getScaleInstance(scale, scale);
g2d.setTransform(scaleAT);
print(g2d, pageFormat.getImageableWidth(), pageFormat.getImageableWidth());
This would mean I wouldn't need to apply any "print mode" type translations within the underlying existing paint routines we have...
This resulted in...
But wait an minute, what's gone wrong here?
So I went back and had a look at all the measurements...
GraphicsConfiguration conf = ((Graphics2D) graphics).getDeviceConfiguration();
//...
Rectangle bounds = conf.getBounds();
buffer = conf.createCompatibleImage(bounds.width, bounds.height);
Was reporting an image size of 4960x7015, but it should be 4970x7029...but wait, what about the imaginable area...at 600dpi it should be, 3768x5827...so that can't be relied upon.
Even after correcting for this, the result still doesn't have the image lining up with expectations in either position nor quality...
Graphics2D
provides a method to get aGraphicsConfiguration
which is linked toGraphicsDevice
. What is missing is the information, when you can safely assume that aGraphics
is aGraphics2D
in the context of printing.E.g. the following program works in my setup: